[lld] r203875 - [PECOFF] Support response files.

Rui Ueyama ruiu at google.com
Thu Mar 13 17:36:30 PDT 2014


Author: ruiu
Date: Thu Mar 13 19:36:30 2014
New Revision: 203875

URL: http://llvm.org/viewvc/llvm-project?rev=203875&view=rev
Log:
[PECOFF] Support response files.

If the driver finds a command line option in the form of "@filename", the
option will be replaced with the content of the given file. It's an error
if a response file cannot be read.

Added:
    lld/trunk/test/pecoff/Inputs/responsefile.txt
    lld/trunk/test/pecoff/responsefile.test
Modified:
    lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h
    lld/trunk/lib/Driver/WinLinkDriver.cpp

Modified: lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h?rev=203875&r1=203874&r2=203875&view=diff
==============================================================================
--- lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h (original)
+++ lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h Thu Mar 13 19:36:30 2014
@@ -247,6 +247,10 @@ public:
     return ArrayRef<uint8_t>(p, p + array.size());
   }
 
+  template <typename T> T &allocateCopy(const T &x) const {
+    return *new (_allocator) T(x);
+  }
+
   virtual bool hasInputGraph() { return !!_inputGraph; }
 
   void setLibraryGroup(Group *group) { _libraryGroup = group; }

Modified: lld/trunk/lib/Driver/WinLinkDriver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/WinLinkDriver.cpp?rev=203875&r1=203874&r2=203875&view=diff
==============================================================================
--- lld/trunk/lib/Driver/WinLinkDriver.cpp (original)
+++ lld/trunk/lib/Driver/WinLinkDriver.cpp Thu Mar 13 19:36:30 2014
@@ -24,6 +24,7 @@
 #include "llvm/ADT/StringSwitch.h"
 #include "llvm/Option/Arg.h"
 #include "llvm/Option/Option.h"
+#include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/Process.h"
@@ -35,6 +36,7 @@
 #include <map>
 #include <memory>
 #include <sstream>
+#include <tuple>
 
 namespace lld {
 
@@ -607,11 +609,71 @@ static StringRef getDefaultEntrySymbolNa
   return "";
 }
 
+namespace {
+class DriverStringSaver : public llvm::cl::StringSaver {
+public:
+  DriverStringSaver(PECOFFLinkingContext &ctx) : _ctx(ctx) {}
+
+  const char *SaveString(const char *s) override {
+    return _ctx.allocate(StringRef(s)).data();
+  }
+
+private:
+  PECOFFLinkingContext &_ctx;
+};
+}
+
+// Tokenize command line options in a given file and add them to result.
+static bool readResponseFile(StringRef path, PECOFFLinkingContext &ctx,
+                             std::vector<const char *> &result) {
+  ArrayRef<uint8_t> contents;
+  if (!readFile(ctx, path, contents))
+    return false;
+  StringRef contentsStr(reinterpret_cast<const char *>(contents.data()));
+  DriverStringSaver saver(ctx);
+  SmallVector<const char *, 0> args;
+  llvm::cl::TokenizeWindowsCommandLine(contentsStr, saver, args);
+  for (const char *s : args)
+    result.push_back(s);
+  return true;
+}
+
+// Expand arguments starting with "@". It's an error if a specified file does
+// not exist. Returns true on success.
+static bool expandResponseFiles(int &argc, const char **&argv,
+                                PECOFFLinkingContext &ctx,
+                                raw_ostream &diagnostics) {
+  std::vector<const char *> newArgv;
+  bool expanded = false;
+  for (int i = 0; i < argc; ++i) {
+    if (argv[i][0] != '@') {
+      newArgv.push_back(argv[i]);
+      continue;
+    }
+    StringRef filename = StringRef(argv[i] + 1);
+    if (!readResponseFile(filename, ctx, newArgv)) {
+      diagnostics << "error: cannot read response file: " << filename << "\n";
+      return false;
+    }
+    expanded = true;
+  }
+  if (!expanded)
+    return true;
+  argc = newArgv.size();
+  newArgv.push_back(nullptr);
+  argv = &ctx.allocateCopy(newArgv)[0];
+  return true;
+}
+
 // Parses the given command line options and returns the result. Returns NULL if
 // there's an error in the options.
 static std::unique_ptr<llvm::opt::InputArgList>
-parseArgs(int argc, const char *argv[], raw_ostream &diagnostics,
-          bool isReadingDirectiveSection) {
+parseArgs(int argc, const char **argv, PECOFFLinkingContext &ctx,
+          raw_ostream &diagnostics, bool isReadingDirectiveSection) {
+  // Expand arguments starting with "@".
+  if (!expandResponseFiles(argc, argv, ctx, diagnostics))
+    return nullptr;
+
   // Parse command line options using WinLinkOptions.td
   std::unique_ptr<llvm::opt::InputArgList> parsedArgs;
   WinLinkOptTable table;
@@ -685,8 +747,8 @@ WinLinkDriver::parse(int argc, const cha
                      raw_ostream &diagnostics, bool isReadingDirectiveSection) {
   std::map<StringRef, StringRef> failIfMismatchMap;
   // Parse the options.
-  std::unique_ptr<llvm::opt::InputArgList> parsedArgs = parseArgs(
-      argc, argv, diagnostics, isReadingDirectiveSection);
+  std::unique_ptr<llvm::opt::InputArgList> parsedArgs =
+      parseArgs(argc, argv, ctx, diagnostics, isReadingDirectiveSection);
   if (!parsedArgs)
     return false;
 

Added: lld/trunk/test/pecoff/Inputs/responsefile.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/pecoff/Inputs/responsefile.txt?rev=203875&view=auto
==============================================================================
--- lld/trunk/test/pecoff/Inputs/responsefile.txt (added)
+++ lld/trunk/test/pecoff/Inputs/responsefile.txt Thu Mar 13 19:36:30 2014
@@ -0,0 +1 @@
+-foo

Added: lld/trunk/test/pecoff/responsefile.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/pecoff/responsefile.test?rev=203875&view=auto
==============================================================================
--- lld/trunk/test/pecoff/responsefile.test (added)
+++ lld/trunk/test/pecoff/responsefile.test Thu Mar 13 19:36:30 2014
@@ -0,0 +1,5 @@
+# RUN: yaml2obj %p/Inputs/hello.obj.yaml > %t.obj
+# RUN: not lld -flavor link @%p/Inputs/responsefile.txt >& %t.log
+# RUN: FileCheck %s < %t.log
+
+CHECK: warning: ignoring unknown argument: -foo





More information about the llvm-commits mailing list