summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/COFF/Driver.cpp43
-rw-r--r--lld/COFF/Driver.h6
-rw-r--r--lld/COFF/DriverUtils.cpp21
-rw-r--r--llvm/include/llvm/Option/ArgList.h2
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)
OpenPOWER on IntegriCloud