[lld] r312594 - lld-link: Add --rsp-quoting= flag.

Nico Weber via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 5 16:46:45 PDT 2017


Author: nico
Date: Tue Sep  5 16:46:45 2017
New Revision: 312594

URL: http://llvm.org/viewvc/llvm-project?rev=312594&view=rev
Log:
lld-link: Add --rsp-quoting= flag.

This ports https://reviews.llvm.org/D19425 from clang /
https://reviews.llvm.org/D22015 from the ELF port to COFF lld. This can be
useful when linking COFF files on a posix host.

https://reviews.llvm.org/D37452

Modified:
    lld/trunk/COFF/Driver.cpp
    lld/trunk/COFF/Driver.h
    lld/trunk/COFF/DriverUtils.cpp
    lld/trunk/COFF/Options.td
    lld/trunk/test/COFF/responsefile.test

Modified: lld/trunk/COFF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Driver.cpp?rev=312594&r1=312593&r2=312594&view=diff
==============================================================================
--- lld/trunk/COFF/Driver.cpp (original)
+++ lld/trunk/COFF/Driver.cpp Tue Sep  5 16:46:45 2017
@@ -202,6 +202,7 @@ static bool isDecorated(StringRef Sym) {
 // specified by /defaultlib.
 void LinkerDriver::parseDirectives(StringRef S) {
   ArgParser Parser;
+  // .drectve is always tokenized using Windows shell rules.
   opt::InputArgList Args = Parser.parse(S);
 
   for (auto *Arg : Args) {

Modified: lld/trunk/COFF/Driver.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Driver.h?rev=312594&r1=312593&r2=312594&view=diff
==============================================================================
--- lld/trunk/COFF/Driver.h (original)
+++ lld/trunk/COFF/Driver.h Tue Sep  5 16:46:45 2017
@@ -48,18 +48,17 @@ public:
 
 class ArgParser {
 public:
-  // Parses command line options.
-  llvm::opt::InputArgList parse(llvm::ArrayRef<const char *> Args);
-
-  // Concatenate LINK environment varirable and given arguments and parse them.
+  // Concatenate LINK environment variable and given arguments and parse them.
   llvm::opt::InputArgList parseLINK(std::vector<const char *> Args);
 
   // Tokenizes a given string and then parses as command line options.
   llvm::opt::InputArgList parse(StringRef S) { return parse(tokenize(S)); }
 
 private:
+  // Parses command line options.
+  llvm::opt::InputArgList parse(llvm::ArrayRef<const char *> Args);
+
   std::vector<const char *> tokenize(StringRef S);
-  std::vector<const char *> replaceResponseFiles(std::vector<const char *>);
 
   COFFOptTable Table;
 };

Modified: lld/trunk/COFF/DriverUtils.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/DriverUtils.cpp?rev=312594&r1=312593&r2=312594&view=diff
==============================================================================
--- lld/trunk/COFF/DriverUtils.cpp (original)
+++ lld/trunk/COFF/DriverUtils.cpp Tue Sep  5 16:46:45 2017
@@ -38,8 +38,6 @@
 
 using namespace llvm::COFF;
 using namespace llvm;
-using llvm::cl::ExpandResponseFiles;
-using llvm::cl::TokenizeWindowsCommandLine;
 using llvm::sys::Process;
 
 namespace lld {
@@ -718,20 +716,40 @@ static const llvm::opt::OptTable::Info I
 
 COFFOptTable::COFFOptTable() : OptTable(InfoTable, true) {}
 
-// Parses a given list of options.
-opt::InputArgList ArgParser::parse(ArrayRef<const char *> ArgsArr) {
-  // First, replace respnose files (@<file>-style options).
-  std::vector<const char *> Argv = replaceResponseFiles(ArgsArr);
+static cl::TokenizerCallback getQuotingStyle(opt::InputArgList &Args) {
+  if (auto *Arg = Args.getLastArg(OPT_rsp_quoting)) {
+    StringRef S = Arg->getValue();
+    if (S != "windows" && S != "posix")
+      error("invalid response file quoting: " + S);
+    if (S == "windows")
+      return cl::TokenizeWindowsCommandLine;
+    return cl::TokenizeGNUCommandLine;
+  }
+  // The COFF linker always defaults to Windows quoting.
+  return cl::TokenizeWindowsCommandLine;
+}
 
+// Parses a given list of options.
+opt::InputArgList ArgParser::parse(ArrayRef<const char *> Argv) {
   // Make InputArgList from string vectors.
   unsigned MissingIndex;
   unsigned MissingCount;
-  opt::InputArgList Args = Table.ParseArgs(Argv, MissingIndex, MissingCount);
+  SmallVector<const char *, 256> Vec(Argv.data(), Argv.data() + Argv.size());
+
+  // We need to get the quoting style for response files before parsing all
+  // options so we parse here before and ignore all the options but
+  // --rsp-quoting.
+  opt::InputArgList Args = Table.ParseArgs(Vec, MissingIndex, MissingCount);
+
+  // Expand response files (arguments in the form of @<filename>)
+  // and then parse the argument again.
+  cl::ExpandResponseFiles(Saver, getQuotingStyle(Args), Vec);
+  Args = Table.ParseArgs(Vec, MissingIndex, MissingCount);
 
   // Print the real command line if response files are expanded.
-  if (Args.hasArg(OPT_verbose) && ArgsArr.size() != Argv.size()) {
+  if (Args.hasArg(OPT_verbose) && Argv.size() != Vec.size()) {
     std::string Msg = "Command line:";
-    for (const char *S : Argv)
+    for (const char *S : Vec)
       Msg += " " + std::string(S);
     message(Msg);
   }
@@ -746,17 +764,17 @@ opt::InputArgList ArgParser::parse(Array
 // link.exe has an interesting feature. If LINK or _LINK_ environment
 // variables exist, their contents are handled as command line strings.
 // So you can pass extra arguments using them.
-opt::InputArgList ArgParser::parseLINK(std::vector<const char *> Args) {
+opt::InputArgList ArgParser::parseLINK(std::vector<const char *> Argv) {
   // Concatenate LINK env and command line arguments, and then parse them.
   if (Optional<std::string> S = Process::GetEnv("LINK")) {
     std::vector<const char *> V = tokenize(*S);
-    Args.insert(Args.begin(), V.begin(), V.end());
+    Argv.insert(Argv.begin(), V.begin(), V.end());
   }
   if (Optional<std::string> S = Process::GetEnv("_LINK_")) {
     std::vector<const char *> V = tokenize(*S);
-    Args.insert(Args.begin(), V.begin(), V.end());
+    Argv.insert(Argv.begin(), V.begin(), V.end());
   }
-  return parse(Args);
+  return parse(Argv);
 }
 
 std::vector<const char *> ArgParser::tokenize(StringRef S) {
@@ -765,15 +783,6 @@ std::vector<const char *> ArgParser::tok
   return std::vector<const char *>(Tokens.begin(), Tokens.end());
 }
 
-// Creates a new command line by replacing options starting with '@'
-// character. '@<filename>' is replaced by the file's contents.
-std::vector<const char *>
-ArgParser::replaceResponseFiles(std::vector<const char *> Argv) {
-  SmallVector<const char *, 256> Tokens(Argv.data(), Argv.data() + Argv.size());
-  ExpandResponseFiles(Saver, TokenizeWindowsCommandLine, Tokens);
-  return std::vector<const char *>(Tokens.begin(), Tokens.end());
-}
-
 void printHelp(const char *Argv0) {
   COFFOptTable Table;
   Table.PrintHelp(outs(), Argv0, "LLVM Linker", false);

Modified: lld/trunk/COFF/Options.td
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Options.td?rev=312594&r1=312593&r2=312594&view=diff
==============================================================================
--- lld/trunk/COFF/Options.td (original)
+++ lld/trunk/COFF/Options.td Tue Sep  5 16:46:45 2017
@@ -101,6 +101,8 @@ def help_q : Flag<["/?", "-?"], "">, Ali
 def nopdb : F<"nopdb">, HelpText<"Disable PDB generation for DWARF users">;
 def nosymtab : F<"nosymtab">;
 def msvclto : F<"msvclto">;
+def rsp_quoting : Joined<["--"], "rsp-quoting=">,
+  HelpText<"Quoting style for response files, 'windows' (default) or 'posix'">;
 
 // Flags for debugging
 def lldmap : F<"lldmap">;

Modified: lld/trunk/test/COFF/responsefile.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/responsefile.test?rev=312594&r1=312593&r2=312594&view=diff
==============================================================================
--- lld/trunk/test/COFF/responsefile.test (original)
+++ lld/trunk/test/COFF/responsefile.test Tue Sep  5 16:46:45 2017
@@ -3,5 +3,23 @@
 # RUN: echo /out:%t.exe /entry:main %t.obj > %t.rsp
 # RUN: lld-link @%t.rsp /heap:0x3000
 # RUN: llvm-readobj -file-headers %t.exe | FileCheck %s
-
 CHECK: SizeOfHeapReserve: 12288
+
+# RUN: not lld-link --rsp-quoting=foobar @%t.rsp 2>&1 | \
+# RUN:     FileCheck --check-prefix=INVRSP %s
+INVRSP: invalid response file quoting: foobar
+
+# RUN: echo "blah\foo" > %t.rsp
+# RUN: not lld-link @%t.rsp 2>&1 | \
+# RUN:     FileCheck --check-prefix=DEFRSP %s
+DEFRSP: error: could not open blah\foo
+
+# RUN: echo "blah\foo" > %t.rsp
+# RUN: not lld-link --rsp-quoting=windows @%t.rsp 2>&1 | \
+# RUN:     FileCheck --check-prefix=WINRSP %s
+WINRSP: error: could not open blah\foo
+
+# RUN: echo "blah\foo" > %t.rsp
+# RUN: not lld-link --rsp-quoting=posix @%t.rsp 2>&1 | \
+# RUN:     FileCheck --check-prefix=POSRSP %s
+POSRSP: error: could not open blahfoo




More information about the llvm-commits mailing list