Merge pull request #153 from neonichu/update-scheme

[Xcode] Update llbuild scheme.
diff --git a/include/llbuild/BuildSystem/BuildFile.h b/include/llbuild/BuildSystem/BuildFile.h
index d935a21..fced059 100644
--- a/include/llbuild/BuildSystem/BuildFile.h
+++ b/include/llbuild/BuildSystem/BuildFile.h
@@ -65,6 +65,8 @@
   BuildFileToken at;
 
 public:
+  BuildFileDelegate& getDelegate() const { return delegate; }
+
   void error(const Twine& message) const;
 };
 
@@ -72,6 +74,9 @@
 public:
   virtual ~BuildFileDelegate();
 
+  /// Get an interned string.
+  virtual StringRef getInternedString(StringRef value) = 0;
+  
   /// Get the file system to use for access.
   virtual basic::FileSystem& getFileSystem() = 0;
   
diff --git a/lib/BuildSystem/BuildSystem.cpp b/lib/BuildSystem/BuildSystem.cpp
index dbcb16d..8cdeb54 100644
--- a/lib/BuildSystem/BuildSystem.cpp
+++ b/lib/BuildSystem/BuildSystem.cpp
@@ -68,6 +68,9 @@
 class BuildSystemFileDelegate : public BuildFileDelegate {
   BuildSystemImpl& system;
 
+  /// FIXME: It would be nice to have a StringSet.
+  llvm::StringMap<bool> internedStrings;
+
 public:
   BuildSystemFileDelegate(BuildSystemImpl& system)
       : BuildFileDelegate(), system(system) {}
@@ -77,6 +80,11 @@
   /// @name Delegate Implementation
   /// @{
 
+  virtual StringRef getInternedString(StringRef value) override {
+    auto entry = internedStrings.insert(std::make_pair(value, true));
+    return entry.first->getKey();
+  }
+
   virtual FileSystem& getFileSystem() override {
     return getSystemDelegate().getFileSystem();
   }
@@ -1332,10 +1340,10 @@
   };
   
   /// The command line arguments.
-  std::vector<std::string> args;
+  std::vector<StringRef> args;
 
   /// The environment to use. If empty, the environment will be inherited.
-  llvm::StringMap<std::string> env;
+  SmallVector<std::pair<StringRef, StringRef>, 1> env;
   
   /// The path to the dependency output file, if used.
   SmallVector<std::string, 1> depsPaths{};
@@ -1361,8 +1369,8 @@
       code = hash_combine(code, arg);
     }
     for (const auto& entry: env) {
-      code = hash_combine(code, entry.getKey());
-      code = hash_combine(code, entry.getValue());
+      code = hash_combine(code, entry.first);
+      code = hash_combine(code, entry.second);
     }
     for (const auto& path: depsPaths) {
       code = hash_combine(code, path);
@@ -1531,9 +1539,9 @@
       // When provided as a scalar string, we default to executing using the
       // shell.
       args.clear();
-      args.push_back("/bin/sh");
-      args.push_back("-c");
-      args.push_back(value);
+      args.push_back(ctx.getDelegate().getInternedString("/bin/sh"));
+      args.push_back(ctx.getDelegate().getInternedString("-c"));
+      args.push_back(ctx.getDelegate().getInternedString(value));
     } else if (name == "deps") {
       depsPaths.clear();
       depsPaths.emplace_back(value);
@@ -1569,8 +1577,12 @@
         ctx.error("invalid arguments for command '" + getName() + "'");
         return false;
       }
-      
-      args = std::vector<std::string>(values.begin(), values.end());
+
+      args.clear();
+      args.reserve(values.size());
+      for (auto arg: values) {
+        args.emplace_back(ctx.getDelegate().getInternedString(arg));
+      }
     } else if (name == "deps") {
       depsPaths.clear();
       depsPaths.insert(depsPaths.begin(), values.begin(), values.end());
@@ -1586,8 +1598,12 @@
       ArrayRef<std::pair<StringRef, StringRef>> values) override {
     if (name == "env") {
       env.clear();
+      env.reserve(values.size());
       for (const auto& entry: values) {
-        env[entry.first] = entry.second;
+        env.emplace_back(
+            std::make_pair(
+                ctx.getDelegate().getInternedString(entry.first),
+                ctx.getDelegate().getInternedString(entry.second)));
       }
     } else {
       return ExternalCommand::configureAttribute(ctx, name, values);
@@ -1599,14 +1615,10 @@
   virtual CommandResult executeExternalCommand(BuildSystemCommandInterface& bsci,
                                                Task* task,
                                                QueueJobContext* context) override {
-    std::vector<std::pair<StringRef, StringRef>> environment;
-    for (const auto& it: env) {
-      environment.push_back({ it.getKey(), it.getValue() });
-    }
-    
     // Execute the command.
-    auto result = bsci.getExecutionQueue().executeProcess(context, std::vector<StringRef>(args.begin(), args.end()),
-                                                          environment, /*inheritEnvironment=*/inheritEnv);
+    auto result = bsci.getExecutionQueue().executeProcess(
+        context, args,
+        env, /*inheritEnvironment=*/inheritEnv);
 
     if (result != CommandResult::Succeeded) {
       // If the command failed, there is no need to gather dependencies.
@@ -1659,7 +1671,7 @@
 
 class ClangShellCommand : public ExternalCommand {
   /// The compiler command to invoke.
-  std::vector<std::string> args;
+  std::vector<StringRef> args;
   
   /// The path to the dependency output file, if used.
   std::string depsPath;
@@ -1746,9 +1758,9 @@
       // When provided as a scalar string, we default to executing using the
       // shell.
       args.clear();
-      args.push_back("/bin/sh");
-      args.push_back("-c");
-      args.push_back(value);
+      args.push_back(ctx.getDelegate().getInternedString("/bin/sh"));
+      args.push_back(ctx.getDelegate().getInternedString("-c"));
+      args.push_back(ctx.getDelegate().getInternedString(value));
     } else if (name == "deps") {
       depsPath = value;
     } else {
@@ -1760,7 +1772,11 @@
   virtual bool configureAttribute(const ConfigureContext& ctx, StringRef name,
                                   ArrayRef<StringRef> values) override {
     if (name == "args") {
-      args = std::vector<std::string>(values.begin(), values.end());
+      args.clear();
+      args.reserve(values.size());
+      for (auto arg: values) {
+        args.emplace_back(ctx.getDelegate().getInternedString(arg));
+      }
     } else {
         return ExternalCommand::configureAttribute(ctx, name, values);
     }
@@ -1776,13 +1792,8 @@
   virtual CommandResult executeExternalCommand(BuildSystemCommandInterface& bsci,
                                                Task* task,
                                                QueueJobContext* context) override {
-    std::vector<StringRef> commandLine;
-    for (const auto& arg: args) {
-      commandLine.push_back(arg);
-    }
-
     // Execute the command.
-    auto result = bsci.getExecutionQueue().executeProcess(context, commandLine);
+    auto result = bsci.getExecutionQueue().executeProcess(context, args);
 
     if (result != CommandResult::Succeeded) {
       // If the command failed, there is no need to gather dependencies.
@@ -2188,7 +2199,8 @@
 
     // Create archive
     auto args = getArgs();
-    return bsci.getExecutionQueue().executeProcess(context, std::vector<StringRef>(args.begin(), args.end()));
+    return bsci.getExecutionQueue().executeProcess(
+        context, std::vector<StringRef>(args.begin(), args.end()));
   }
 
   virtual void getShortDescription(SmallVectorImpl<char> &result) override {
diff --git a/lib/Commands/BuildSystemCommand.cpp b/lib/Commands/BuildSystemCommand.cpp
index b16098a..e13f04b 100644
--- a/lib/Commands/BuildSystemCommand.cpp
+++ b/lib/Commands/BuildSystemCommand.cpp
@@ -23,6 +23,7 @@
 
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringMap.h"
 #include "llvm/Support/SourceMgr.h"
 #include "llvm/Support/raw_ostream.h"
 
@@ -47,6 +48,7 @@
   bool showOutput;
   StringRef bufferBeingParsed;
   std::unique_ptr<basic::FileSystem> fileSystem;
+  llvm::StringMap<bool> internedStrings;
   
 public:
   ParseBuildFileDelegate(bool showOutput)
@@ -56,6 +58,11 @@
 
   virtual bool shouldShowOutput() { return showOutput; }
 
+  virtual StringRef getInternedString(StringRef value) override {
+    auto entry = internedStrings.insert(std::make_pair(value, true));
+    return entry.first->getKey();
+  }
+  
   virtual basic::FileSystem& getFileSystem() override { return *fileSystem; }
   
   virtual void setFileContentsBeingParsed(StringRef buffer) override;