diff options
-rw-r--r-- | lld/COFF/Driver.cpp | 43 | ||||
-rw-r--r-- | lld/COFF/Driver.h | 6 | ||||
-rw-r--r-- | lld/COFF/DriverUtils.cpp | 21 | ||||
-rw-r--r-- | llvm/include/llvm/Option/ArgList.h | 2 |
4 files changed, 45 insertions, 27 deletions
diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp index 23ff0501da8..7bddffc5bf4 100644 --- a/lld/COFF/Driver.cpp +++ b/lld/COFF/Driver.cpp @@ -227,7 +227,29 @@ static bool isDecorated(StringRef Sym) { void LinkerDriver::parseDirectives(StringRef S) { ArgParser Parser; // .drectve is always tokenized using Windows shell rules. - opt::InputArgList Args = Parser.parseDirectives(S); + // /EXPORT: option can appear too many times, processing in fastpath. + opt::InputArgList Args; + std::vector<StringRef> Exports; + std::tie(Args, Exports) = Parser.parseDirectives(S); + + for (StringRef E : Exports) { + // If a common header file contains dllexported function + // declarations, many object files may end up with having the + // same /EXPORT options. In order to save cost of parsing them, + // we dedup them first. + if (!DirectivesExports.insert(E).second) + continue; + + Export Exp = parseExport(E); + if (Config->Machine == I386 && Config->MinGW) { + if (!isDecorated(Exp.Name)) + Exp.Name = Saver.save("_" + Exp.Name); + if (!Exp.ExtName.empty() && !isDecorated(Exp.ExtName)) + Exp.ExtName = Saver.save("_" + Exp.ExtName); + } + Exp.Directives = true; + Config->Exports.push_back(Exp); + } for (auto *Arg : Args) { switch (Arg->getOption().getUnaliasedOption().getID()) { @@ -244,25 +266,6 @@ void LinkerDriver::parseDirectives(StringRef S) { case OPT_entry: Config->Entry = addUndefined(mangle(Arg->getValue())); break; - case OPT_export: { - // If a common header file contains dllexported function - // declarations, many object files may end up with having the - // same /EXPORT options. In order to save cost of parsing them, - // we dedup them first. - if (!DirectivesExports.insert(Arg->getValue()).second) - break; - - Export E = parseExport(Arg->getValue()); - if (Config->Machine == I386 && Config->MinGW) { - if (!isDecorated(E.Name)) - E.Name = Saver.save("_" + E.Name); - if (!E.ExtName.empty() && !isDecorated(E.ExtName)) - E.ExtName = Saver.save("_" + E.ExtName); - } - E.Directives = true; - Config->Exports.push_back(E); - break; - } case OPT_failifmismatch: checkFailIfMismatch(Arg->getValue()); break; diff --git a/lld/COFF/Driver.h b/lld/COFF/Driver.h index 3f7fad1038f..bbb6cc97532 100644 --- a/lld/COFF/Driver.h +++ b/lld/COFF/Driver.h @@ -56,8 +56,10 @@ public: llvm::opt::InputArgList parse(StringRef S) { return parse(tokenize(S)); } // Tokenizes a given string and then parses as command line options in - // .drectve section. - llvm::opt::InputArgList parseDirectives(StringRef S); + // .drectve section. /EXPORT options are returned in second element + // to be processed in fastpath. + std::pair<llvm::opt::InputArgList, std::vector<StringRef>> + parseDirectives(StringRef S); private: // Parses command line options. diff --git a/lld/COFF/DriverUtils.cpp b/lld/COFF/DriverUtils.cpp index e0641e04a01..0fe9e48b403 100644 --- a/lld/COFF/DriverUtils.cpp +++ b/lld/COFF/DriverUtils.cpp @@ -751,19 +751,30 @@ opt::InputArgList ArgParser::parse(ArrayRef<const char *> Argv) { } // Tokenizes and parses a given string as command line in .drective section. -opt::InputArgList ArgParser::parseDirectives(StringRef S) { - // Make InputArgList from string vectors. +// /EXPORT options are processed in fastpath. +std::pair<opt::InputArgList, std::vector<StringRef>> +ArgParser::parseDirectives(StringRef S) { + std::vector<StringRef> Exports; + SmallVector<const char *, 16> Rest; + + for (StringRef Tok : tokenize(S)) { + if (Tok.startswith_lower("/export:") || Tok.startswith_lower("-export:")) + Exports.push_back(Tok.substr(strlen("/export:"))); + else + Rest.push_back(Tok.data()); + } + + // Make InputArgList from unparsed string vectors. unsigned MissingIndex; unsigned MissingCount; - opt::InputArgList Args = - Table.ParseArgs(tokenize(S), MissingIndex, MissingCount); + opt::InputArgList Args = Table.ParseArgs(Rest, MissingIndex, MissingCount); if (MissingCount) fatal(Twine(Args.getArgString(MissingIndex)) + ": missing argument"); for (auto *Arg : Args.filtered(OPT_UNKNOWN)) warn("ignoring unknown argument: " + Arg->getSpelling()); - return Args; + return {std::move(Args), std::move(Exports)}; } // link.exe has an interesting feature. If LINK or _LINK_ environment diff --git a/llvm/include/llvm/Option/ArgList.h b/llvm/include/llvm/Option/ArgList.h index aaea68bf8e2..a80921fa842 100644 --- a/llvm/include/llvm/Option/ArgList.h +++ b/llvm/include/llvm/Option/ArgList.h @@ -390,6 +390,8 @@ private: void releaseMemory(); public: + InputArgList() : NumInputArgStrings(0) {} + InputArgList(const char* const *ArgBegin, const char* const *ArgEnd); InputArgList(InputArgList &&RHS) |