From: Rafael Espindola <rafael.espindola@gmail.com> Date: Sat, 13 Jun 2015 12:49:52 +0000 (+0000) Subject: Bring in a BumpPtrStringSaver from lld and simplify the interface. X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=8e2ed1643a03a892f0d97bcc0098c3c53eee1e6b;p=oota-llvm.git Bring in a BumpPtrStringSaver from lld and simplify the interface. StringSaver now always saves to a BumpPtrAllocator. The only reason for having the virtual saveImpl is so lld can have a thread safe version. The reason for the distinct BumpPtrStringSaver class is to avoid the virtual destructor. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@239669 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/Support/CommandLine.h b/include/llvm/Support/CommandLine.h index 1ad8a3bfd93..ed809211ea9 100644 --- a/include/llvm/Support/CommandLine.h +++ b/include/llvm/Support/CommandLine.h @@ -33,6 +33,9 @@ namespace llvm { +class BumpPtrStringSaver; +class StringSaver; + /// cl Namespace - This namespace contains all of the command line option /// processing machinery. It is intentionally a short name to make qualified /// usage concise. @@ -1676,16 +1679,6 @@ StringMap<Option *> &getRegisteredOptions(); // Standalone command line processing utilities. // -/// \brief Saves strings in the inheritor's stable storage and returns a stable -/// raw character pointer. -class StringSaver { - virtual void anchor(); - -public: - virtual const char *SaveString(const char *Str) = 0; - virtual ~StringSaver(){}; // Pacify -Wnon-virtual-dtor. -}; - /// \brief Tokenizes a command line that can contain escapes and quotes. // /// The quoting rules match those used by GCC and other tools that use diff --git a/include/llvm/Support/StringSaver.h b/include/llvm/Support/StringSaver.h new file mode 100644 index 00000000000..f3853ee9157 --- /dev/null +++ b/include/llvm/Support/StringSaver.h @@ -0,0 +1,42 @@ +//===- llvm/Support/StringSaver.h -------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_STRINGSAVER_H +#define LLVM_SUPPORT_STRINGSAVER_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Twine.h" +#include "llvm/Support/Allocator.h" + +namespace llvm { + +/// \brief Saves strings in the inheritor's stable storage and returns a stable +/// raw character pointer. +class StringSaver { +protected: + ~StringSaver() {} + virtual const char *saveImpl(StringRef S); + +public: + StringSaver(BumpPtrAllocator &Alloc) : Alloc(Alloc) {} + const char *save(const char *S) { return save(StringRef(S)); } + const char *save(StringRef S) { return saveImpl(S); } + const char *save(const Twine &S) { return save(StringRef(S.str())); } + const char *save(std::string &S) { return save(StringRef(S)); } + +private: + BumpPtrAllocator &Alloc; +}; + +class BumpPtrStringSaver final : public StringSaver { +public: + BumpPtrStringSaver(BumpPtrAllocator &Alloc) : StringSaver(Alloc) {} +}; +} +#endif diff --git a/lib/LibDriver/LibDriver.cpp b/lib/LibDriver/LibDriver.cpp index d028e4bbca5..44929580f82 100644 --- a/lib/LibDriver/LibDriver.cpp +++ b/lib/LibDriver/LibDriver.cpp @@ -19,6 +19,7 @@ #include "llvm/Option/ArgList.h" #include "llvm/Option/Option.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/StringSaver.h" #include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" @@ -67,30 +68,10 @@ static std::string getOutputPath(llvm::opt::InputArgList *Args) { llvm_unreachable("internal error"); } -namespace { -// FIXME: Should re-use StringSaver from lld. -class StrDupSaver : public cl::StringSaver { - std::vector<char *> Dups; - -public: - ~StrDupSaver() override { - for (std::vector<char *>::iterator I = Dups.begin(), E = Dups.end(); I != E; - ++I) { - char *Dup = *I; - free(Dup); - } - } - const char *SaveString(const char *Str) override { - char *Dup = strdup(Str); - Dups.push_back(Dup); - return Dup; - } -}; -} - int llvm::libDriverMain(int Argc, const char **Argv) { SmallVector<const char *, 20> NewArgv(Argv, Argv + Argc); - StrDupSaver Saver; + BumpPtrAllocator Alloc; + BumpPtrStringSaver Saver(Alloc); cl::ExpandResponseFiles(Saver, cl::TokenizeWindowsCommandLine, NewArgv); Argv = &NewArgv[0]; Argc = static_cast<int>(NewArgv.size()); diff --git a/lib/Support/CMakeLists.txt b/lib/Support/CMakeLists.txt index 79aae158435..eac189b67a4 100644 --- a/lib/Support/CMakeLists.txt +++ b/lib/Support/CMakeLists.txt @@ -83,6 +83,7 @@ add_llvm_library(LLVMSupport StringExtras.cpp StringMap.cpp StringPool.cpp + StringSaver.cpp StringRef.cpp SystemUtils.cpp TargetParser.cpp diff --git a/lib/Support/CommandLine.cpp b/lib/Support/CommandLine.cpp index 3cabc54a73a..dcaacf6248d 100644 --- a/lib/Support/CommandLine.cpp +++ b/lib/Support/CommandLine.cpp @@ -32,6 +32,7 @@ #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" +#include "llvm/Support/StringSaver.h" #include "llvm/Support/raw_ostream.h" #include <cstdlib> #include <map> @@ -78,7 +79,6 @@ void parser<double>::anchor() {} void parser<float>::anchor() {} void parser<std::string>::anchor() {} void parser<char>::anchor() {} -void StringSaver::anchor() {} //===----------------------------------------------------------------------===// @@ -564,7 +564,7 @@ void cl::TokenizeGNUCommandLine(StringRef Src, StringSaver &Saver, // End the token if this is whitespace. if (isWhitespace(Src[I])) { if (!Token.empty()) - NewArgv.push_back(Saver.SaveString(Token.c_str())); + NewArgv.push_back(Saver.save(Token.c_str())); Token.clear(); continue; } @@ -575,7 +575,7 @@ void cl::TokenizeGNUCommandLine(StringRef Src, StringSaver &Saver, // Append the last token after hitting EOF with no whitespace. if (!Token.empty()) - NewArgv.push_back(Saver.SaveString(Token.c_str())); + NewArgv.push_back(Saver.save(Token.c_str())); // Mark the end of response files if (MarkEOLs) NewArgv.push_back(nullptr); @@ -656,7 +656,7 @@ void cl::TokenizeWindowsCommandLine(StringRef Src, StringSaver &Saver, if (State == UNQUOTED) { // Whitespace means the end of the token. if (isWhitespace(Src[I])) { - NewArgv.push_back(Saver.SaveString(Token.c_str())); + NewArgv.push_back(Saver.save(Token.c_str())); Token.clear(); State = INIT; // Mark the end of lines in response files @@ -691,7 +691,7 @@ void cl::TokenizeWindowsCommandLine(StringRef Src, StringSaver &Saver, } // Append the last token after hitting EOF with no whitespace. if (!Token.empty()) - NewArgv.push_back(Saver.SaveString(Token.c_str())); + NewArgv.push_back(Saver.save(Token.c_str())); // Mark the end of response files if (MarkEOLs) NewArgv.push_back(nullptr); @@ -779,26 +779,6 @@ bool cl::ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer, return AllExpanded; } -namespace { -class StrDupSaver : public StringSaver { - std::vector<char *> Dups; - -public: - ~StrDupSaver() override { - for (std::vector<char *>::iterator I = Dups.begin(), E = Dups.end(); I != E; - ++I) { - char *Dup = *I; - free(Dup); - } - } - const char *SaveString(const char *Str) override { - char *Dup = strdup(Str); - Dups.push_back(Dup); - return Dup; - } -}; -} - /// ParseEnvironmentOptions - An alternative entry point to the /// CommandLine library, which allows you to read the program's name /// from the caller (as PROGNAME) and its command-line arguments from @@ -818,8 +798,9 @@ void cl::ParseEnvironmentOptions(const char *progName, const char *envVar, // Get program's "name", which we wouldn't know without the caller // telling us. SmallVector<const char *, 20> newArgv; - StrDupSaver Saver; - newArgv.push_back(Saver.SaveString(progName)); + BumpPtrAllocator A; + BumpPtrStringSaver Saver(A); + newArgv.push_back(Saver.save(progName)); // Parse the value of the environment variable into a "command line" // and hand it off to ParseCommandLineOptions(). @@ -840,7 +821,8 @@ void CommandLineParser::ParseCommandLineOptions(int argc, // Expand response files. SmallVector<const char *, 20> newArgv(argv, argv + argc); - StrDupSaver Saver; + BumpPtrAllocator A; + BumpPtrStringSaver Saver(A); ExpandResponseFiles(Saver, TokenizeGNUCommandLine, newArgv); argv = &newArgv[0]; argc = static_cast<int>(newArgv.size()); diff --git a/lib/Support/StringSaver.cpp b/lib/Support/StringSaver.cpp new file mode 100644 index 00000000000..d6b84e53dcc --- /dev/null +++ b/lib/Support/StringSaver.cpp @@ -0,0 +1,19 @@ +//===-- StringSaver.cpp ---------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/StringSaver.h" + +using namespace llvm; + +const char *StringSaver::saveImpl(StringRef S) { + char *P = Alloc.Allocate<char>(S.size() + 1); + memcpy(P, S.data(), S.size()); + P[S.size()] = '\0'; + return P; +} diff --git a/unittests/Support/CommandLineTest.cpp b/unittests/Support/CommandLineTest.cpp index 328c4b7fcf3..e0fbf5b09e5 100644 --- a/unittests/Support/CommandLineTest.cpp +++ b/unittests/Support/CommandLineTest.cpp @@ -10,6 +10,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/Config/config.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/StringSaver.h" #include "gtest/gtest.h" #include <stdlib.h> #include <string> @@ -146,26 +147,20 @@ TEST(CommandLineTest, UseOptionCategory) { "Category."; } -class StrDupSaver : public cl::StringSaver { - const char *SaveString(const char *Str) override { - return strdup(Str); - } -}; - -typedef void ParserFunction(StringRef Source, llvm::cl::StringSaver &Saver, +typedef void ParserFunction(StringRef Source, StringSaver &Saver, SmallVectorImpl<const char *> &NewArgv, bool MarkEOLs); void testCommandLineTokenizer(ParserFunction *parse, const char *Input, const char *const Output[], size_t OutputSize) { SmallVector<const char *, 0> Actual; - StrDupSaver Saver; + BumpPtrAllocator A; + BumpPtrStringSaver Saver(A); parse(Input, Saver, Actual, /*MarkEOLs=*/false); EXPECT_EQ(OutputSize, Actual.size()); for (unsigned I = 0, E = Actual.size(); I != E; ++I) { if (I < OutputSize) EXPECT_STREQ(Output[I], Actual[I]); - free(const_cast<char *>(Actual[I])); } }