Correct option forwarding: initial implementation.
authorMikhail Glushenkov <foldr@codedgers.com>
Tue, 23 Feb 2010 09:04:44 +0000 (09:04 +0000)
committerMikhail Glushenkov <foldr@codedgers.com>
Tue, 23 Feb 2010 09:04:44 +0000 (09:04 +0000)
Does not work, but the infrastructure changes are in place.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@96920 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/CompilerDriver/Common.td
include/llvm/CompilerDriver/Tool.h
lib/CompilerDriver/Tool.cpp
tools/llvmc/Makefile
tools/llvmc/plugins/Base/Base.td.in
tools/llvmc/plugins/Clang/Clang.td
utils/TableGen/LLVMCConfigurationEmitter.cpp

index aa15482cfae178a1da29bce0ecc027e6b9c7a27c..479bd6e12f0cd1cff5c98c08a9af5bd6116c1bb9 100644 (file)
@@ -20,7 +20,9 @@ class Tool<list<dag> l> {
 def in_language;
 def out_language;
 def output_suffix;
-def cmd_line;
+def command;
+def out_file_option;
+def in_file_option;
 def join;
 def sink;
 def works_on_empty;
@@ -83,6 +85,7 @@ def forward_as;
 def forward_value;
 def forward_transformed_value;
 def stop_compilation;
+def no_out_file;
 def unpack_values;
 def warning;
 def error;
index 6fc0ae63914ee6e290dd7abdcecf1b092500d624..85d1690bcfedecb41073b2f3d457fea949811f08 100644 (file)
 #include "llvm/ADT/StringSet.h"
 #include "llvm/System/Path.h"
 
+#include <string>
 #include <vector>
+#include <utility>
 
 namespace llvmc {
 
   class LanguageMap;
+  typedef std::vector<std::pair<unsigned, std::string> > ArgsVector;
   typedef std::vector<llvm::sys::Path> PathVector;
+  typedef std::vector<std::string> StrVector;
   typedef llvm::StringSet<> InputLanguagesSet;
 
   /// Tool - Represents a single tool.
@@ -59,6 +63,8 @@ namespace llvmc {
                                 const llvm::sys::Path& TempDir,
                                 bool StopCompilation,
                                 const char* OutputSuffix) const;
+
+    StrVector SortArgs(ArgsVector& Args) const;
   };
 
   /// JoinTool - A Tool that has an associated input file list.
index 9f4ab4956627afd5cfd3ba173105b917e7ec30a6..7be24147ce745e8f599aa580a96c90e6b67679c4 100644 (file)
@@ -71,3 +71,12 @@ sys::Path Tool::OutFilename(const sys::Path& In,
   }
   return Out;
 }
+
+StrVector Tool::SortArgs(ArgsVector& Args) const {
+  StrVector Out;
+
+  for (ArgsVector::iterator B = Args.begin(), E = Args.end(); B != E; ++B)
+    Out.push_back(B->second);
+
+  return Out;
+}
index 8f995265d2cf22a3eb7eb4611149bab8540d4517..d915934c5773c1549d17243b5728b51d0a6b4f79 100644 (file)
@@ -10,7 +10,7 @@
 LEVEL = ../..
 
 export LLVMC_BASED_DRIVER_NAME = llvmc
-export LLVMC_BUILTIN_PLUGINS = Base Clang
+export LLVMC_BUILTIN_PLUGINS = Base
 REQUIRES_RTTI = 1
 
 DIRS = plugins driver
index 5f09664cefa704c35280a35154a376a930f26816..9dea5c03159a739b2aa112341ad99b25918e70fd 100644 (file)
@@ -134,28 +134,26 @@ class llvm_gcc_based <string cmd_prefix, string in_lang,
                       string E_ext, string out_lang> : Tool<
 [(in_language in_lang),
  (out_language "llvm-bitcode"),
- (output_suffix out_lang),
- (cmd_line (case
-            (switch_on "E"),
-              (case (not_empty "o"),
-                    !strconcat(cmd_prefix, " -E $INFILE -o $OUTFILE"),
-                    (default),
-                    !strconcat(cmd_prefix, " -E $INFILE")),
-            (switch_on "fsyntax-only"),
-              !strconcat(cmd_prefix, " -fsyntax-only $INFILE"),
-            (and (switch_on "S"), (switch_on "emit-llvm")),
-              !strconcat(cmd_prefix, " -S $INFILE -o $OUTFILE -emit-llvm"),
-            (default),
-              !strconcat(cmd_prefix, " -c $INFILE -o $OUTFILE -emit-llvm"))),
+ (output_suffix "bc"),
+ (command cmd_prefix),
  (actions
      (case
-         (and (multiple_input_files), (or (switch_on "S"), (switch_on "c"))),
+         (and (not_empty "o"),
+              (multiple_input_files), (or (switch_on "S"), (switch_on "c"))),
               (error "cannot specify -o with -c or -S with multiple files"),
-         (switch_on "E"), [(stop_compilation), (output_suffix E_ext)],
+         (switch_on "E"),
+              [(forward "E"), (stop_compilation), (output_suffix E_ext)],
+         (and (switch_on "E"), (empty "o")), (no_out_file),
          (switch_on ["emit-llvm", "S"]),
               [(output_suffix "ll"), (stop_compilation)],
          (switch_on ["emit-llvm", "c"]), (stop_compilation),
-         (switch_on "fsyntax-only"), (stop_compilation),
+         (switch_on "fsyntax-only"), [(forward "fsyntax-only"),
+                                      (no_out_file), (stop_compilation)],
+         (switch_on ["S", "emit-llvm"]), [(forward "S"), (forward "emit-llvm")],
+         (not (or (switch_on ["S", "emit-llvm"]), (switch_on "fsyntax-only"))),
+             [(append_cmd "-c"), (append_cmd "-emit-llvm")],
+
+         // Forwards
          (not_empty "include"), (forward "include"),
          (not_empty "iquote"), (forward "iquote"),
          (not_empty "save-temps"), (append_cmd "-save-temps"),
@@ -208,14 +206,14 @@ def opt : Tool<
                 (switch_on "O1"), (forward "O1"),
                 (switch_on "O2"), (forward "O2"),
                 (switch_on "O3"), (forward "O3"))),
- (cmd_line "opt -f $INFILE -o $OUTFILE")
+ (command "opt -f")
 ]>;
 
 def llvm_as : Tool<
 [(in_language "llvm-assembler"),
  (out_language "llvm-bitcode"),
  (output_suffix "bc"),
- (cmd_line "llvm-as $INFILE -o $OUTFILE"),
+ (command "llvm-as"),
  (actions (case (switch_on "emit-llvm"), (stop_compilation)))
 ]>;
 
@@ -223,7 +221,7 @@ def llvm_gcc_assembler : Tool<
 [(in_language "assembler"),
  (out_language "object-code"),
  (output_suffix "o"),
- (cmd_line "@LLVMGCCCOMMAND@ -c -x assembler $INFILE -o $OUTFILE"),
+ (command "@LLVMGCCCOMMAND@ -c -x assembler"),
  (actions (case
           (switch_on "c"), (stop_compilation),
           (not_empty "arch"), (forward "arch"),
@@ -234,7 +232,7 @@ def llc : Tool<
 [(in_language ["llvm-bitcode", "llvm-assembler"]),
  (out_language "assembler"),
  (output_suffix "s"),
- (cmd_line "llc -f $INFILE -o $OUTFILE"),
+ (command "llc -f"),
  (actions (case
           (switch_on "S"), (stop_compilation),
           (switch_on "O0"), (forward "O0"),
@@ -256,7 +254,7 @@ class llvm_gcc_based_linker <string cmd_prefix> : Tool<
 [(in_language "object-code"),
  (out_language "executable"),
  (output_suffix "out"),
- (cmd_line !strconcat(cmd_prefix, " $INFILE -o $OUTFILE")),
+ (command cmd_prefix),
  (works_on_empty (case (not_empty "filelist"), true,
                        (default), false)),
  (join),
index ac8ac15dff690880c9c1d39b0dab8c9b6682e410..cea2b5d974e48d135cc764a921b9abb14e9c5e78 100644 (file)
@@ -1,12 +1,3 @@
-// A replacement for the Clang's ccc script.
-// Depends on the Base plugin.
-// To compile, use this command:
-//
-//    cd $LLVMC2_DIR
-//    make DRIVER_NAME=ccc2 BUILTIN_PLUGINS=Clang
-//
-// Or just use the default llvmc, which now has this plugin enabled.
-
 include "llvm/CompilerDriver/Common.td"
 
 def Priority : PluginPriority<1>;
index 836a7750c71e788ceba19e341c2a183b11c82884..e5bd34a977ee077cef84ac3ed462c0b25c29b136 100644 (file)
@@ -43,6 +43,7 @@ const unsigned TabWidth = 4;
 const unsigned Indent1  = TabWidth*1;
 const unsigned Indent2  = TabWidth*2;
 const unsigned Indent3  = TabWidth*3;
+const unsigned Indent4  = TabWidth*4;
 
 // Default help string.
 const char * const DefaultHelpString = "NO HELP MESSAGE PROVIDED";
@@ -780,6 +781,8 @@ struct ToolDescription : public RefCountedBase<ToolDescription> {
   Init* CmdLine;
   Init* Actions;
   StrVector InLanguage;
+  std::string InFileOption;
+  std::string OutFileOption;
   std::string OutLanguage;
   std::string OutputSuffix;
   unsigned Flags;
@@ -793,9 +796,13 @@ struct ToolDescription : public RefCountedBase<ToolDescription> {
 
   // Default ctor here is needed because StringMap can only store
   // DefaultConstructible objects
-  ToolDescription() : CmdLine(0), Actions(0), Flags(0), OnEmpty(0) {}
+  ToolDescription ()
+    : CmdLine(0), Actions(0), OutFileOption("-o"), 
+      Flags(0), OnEmpty(0)
+  {}
   ToolDescription (const std::string& n)
-    : Name(n), CmdLine(0), Actions(0), Flags(0), OnEmpty(0)
+    : Name(n), CmdLine(0), Actions(0), OutFileOption("-o"),
+      Flags(0), OnEmpty(0)
   {}
 };
 
@@ -826,10 +833,14 @@ public:
     if (!staticMembersInitialized_) {
 
       AddHandler("actions", &CollectToolProperties::onActions);
-      AddHandler("cmd_line", &CollectToolProperties::onCmdLine);
+      AddHandler("command", &CollectToolProperties::onCommand);
       AddHandler("in_language", &CollectToolProperties::onInLanguage);
       AddHandler("join", &CollectToolProperties::onJoin);
       AddHandler("out_language", &CollectToolProperties::onOutLanguage);
+
+      AddHandler("out_file_option", &CollectToolProperties::onOutFileOption);
+      AddHandler("in_file_option", &CollectToolProperties::onInFileOption);
+
       AddHandler("output_suffix", &CollectToolProperties::onOutputSuffix);
       AddHandler("sink", &CollectToolProperties::onSink);
       AddHandler("works_on_empty", &CollectToolProperties::onWorksOnEmpty);
@@ -857,7 +868,7 @@ private:
     toolDesc_.Actions = Case;
   }
 
-  void onCmdLine (const DagInit& d) {
+  void onCommand (const DagInit& d) {
     CheckNumberOfArguments(d, 1);
     toolDesc_.CmdLine = d.getArg(0);
   }
@@ -899,6 +910,16 @@ private:
     toolDesc_.OutLanguage = InitPtrToString(d.getArg(0));
   }
 
+  void onOutFileOption (const DagInit& d) {
+    CheckNumberOfArguments(d, 1);
+    toolDesc_.OutFileOption = InitPtrToString(d.getArg(0));
+  }
+
+  void onInFileOption (const DagInit& d) {
+    CheckNumberOfArguments(d, 1);
+    toolDesc_.InFileOption = InitPtrToString(d.getArg(0));
+  }
+
   void onOutputSuffix (const DagInit& d) {
     CheckNumberOfArguments(d, 1);
     toolDesc_.OutputSuffix = InitPtrToString(d.getArg(0));
@@ -1724,82 +1745,41 @@ void EmitCmdLineVecFill(const Init* CmdLine, const std::string& ToolName,
   if (StrVec.empty())
     throw "Tool '" + ToolName + "' has empty command line!";
 
-  StrVector::const_iterator I = StrVec.begin(), E = StrVec.end();
+  StrVector::const_iterator B = StrVec.begin(), E = StrVec.end();
 
-  // If there is a hook invocation on the place of the first command, skip it.
+  // Emit the command itself.
   assert(!StrVec[0].empty());
+  O.indent(IndentLevel) << "cmd = ";
   if (StrVec[0][0] == '$') {
-    while (I != E && (*I)[0] != ')' )
-      ++I;
-
-    // Skip the ')' symbol.
-    ++I;
+    B = SubstituteSpecialCommands(B, E, IsJoin, O);
+    ++B;
   }
   else {
-    ++I;
+    O << '"' << StrVec[0] << '"';
+    ++B;
   }
+  O << ";\n";
 
-  bool hasINFILE = false;
+  // Go through the command arguments.
+  assert(B <= E);
+  for (; B != E; ++B) {
+    const std::string& cmd = *B;
 
-  for (; I != E; ++I) {
-    const std::string& cmd = *I;
     assert(!cmd.empty());
     O.indent(IndentLevel);
+
     if (cmd.at(0) == '$') {
-      if (cmd == "$INFILE") {
-        hasINFILE = true;
-        if (IsJoin) {
-          O << "for (PathVector::const_iterator B = inFiles.begin()"
-            << ", E = inFiles.end();\n";
-          O.indent(IndentLevel) << "B != E; ++B)\n";
-          O.indent(IndentLevel + Indent1) << "vec.push_back(B->str());\n";
-        }
-        else {
-          O << "vec.push_back(inFile.str());\n";
-        }
-      }
-      else if (cmd == "$OUTFILE") {
-        O << "vec.push_back(\"\");\n";
-        O.indent(IndentLevel) << "out_file_index = vec.size()-1;\n";
-      }
-      else {
-        O << "vec.push_back(";
-        I = SubstituteSpecialCommands(I, E, IsJoin, O);
-        O << ");\n";
-      }
+      O << "vec.push_back(std::make_pair(0, ";
+      B = SubstituteSpecialCommands(B, E, IsJoin, O);
+      O << "));\n";
     }
     else {
-      O << "vec.push_back(\"" << cmd << "\");\n";
+      O << "vec.push_back(std::make_pair(0, \"" << cmd << "\"));\n";
     }
   }
-  if (!hasINFILE)
-    throw "Tool '" + ToolName + "' doesn't take any input!";
 
-  O.indent(IndentLevel) << "cmd = ";
-  if (StrVec[0][0] == '$')
-    SubstituteSpecialCommands(StrVec.begin(), StrVec.end(), IsJoin, O);
-  else
-    O << '"' << StrVec[0] << '"';
-  O << ";\n";
 }
 
-/// EmitCmdLineVecFillCallback - A function object wrapper around
-/// EmitCmdLineVecFill(). Used by EmitGenerateActionMethod() as an
-/// argument to EmitCaseConstructHandler().
-class EmitCmdLineVecFillCallback {
-  bool IsJoin;
-  const std::string& ToolName;
- public:
-  EmitCmdLineVecFillCallback(bool J, const std::string& TN)
-    : IsJoin(J), ToolName(TN) {}
-
-  void operator()(const Init* Statement, unsigned IndentLevel,
-                  raw_ostream& O) const
-  {
-    EmitCmdLineVecFill(Statement, ToolName, IsJoin, IndentLevel, O);
-  }
-};
-
 /// EmitForwardOptionPropertyHandlingCode - Helper function used to
 /// implement EmitActionHandler. Emits code for
 /// handling the (forward) and (forward_as) option properties.
@@ -1814,23 +1794,25 @@ void EmitForwardOptionPropertyHandlingCode (const OptionDescription& D,
 
   switch (D.Type) {
   case OptionType::Switch:
-    O.indent(IndentLevel) << "vec.push_back(\"" << Name << "\");\n";
+    O.indent(IndentLevel)
+      << "vec.push_back(std::make_pair(0, \"" << Name << "\"));\n";
     break;
   case OptionType::Parameter:
-    O.indent(IndentLevel) << "vec.push_back(\"" << Name;
+    O.indent(IndentLevel) << "vec.push_back(std::make_pair(0, \"" << Name;
 
     if (!D.isForwardNotSplit()) {
-      O << "\");\n";
-      O.indent(IndentLevel) << "vec.push_back("
-                            << D.GenVariableName() << ");\n";
+      O << "\"));\n";
+      O.indent(IndentLevel) << "vec.push_back(std::make_pair(0, "
+                            << D.GenVariableName() << "));\n";
     }
     else {
-      O << "=\" + " << D.GenVariableName() << ");\n";
+      O << "=\" + " << D.GenVariableName() << "));\n";
     }
     break;
   case OptionType::Prefix:
-    O.indent(IndentLevel) << "vec.push_back(\"" << Name << "\" + "
-                          << D.GenVariableName() << ");\n";
+    O.indent(IndentLevel) << "vec.push_back(std::make_pair(0, \""
+                          << Name << "\" + "
+                          << D.GenVariableName() << "));\n";
     break;
   case OptionType::PrefixList:
     O.indent(IndentLevel)
@@ -1838,11 +1820,12 @@ void EmitForwardOptionPropertyHandlingCode (const OptionDescription& D,
       << "::iterator B = " << D.GenVariableName() << ".begin(),\n";
     O.indent(IndentLevel)
       << "E = " << D.GenVariableName() << ".end(); B != E;) {\n";
-    O.indent(IndentLevel1) << "vec.push_back(\"" << Name << "\" + " << "*B);\n";
+    O.indent(IndentLevel1) << "vec.push_back(std::make_pair(0, \""
+                           << Name << "\" + " << "*B));\n";
     O.indent(IndentLevel1) << "++B;\n";
 
     for (int i = 1, j = D.MultiVal; i < j; ++i) {
-      O.indent(IndentLevel1) << "vec.push_back(*B);\n";
+      O.indent(IndentLevel1) << "vec.push_back(std::make_pair(0, *B));\n";
       O.indent(IndentLevel1) << "++B;\n";
     }
 
@@ -1854,10 +1837,11 @@ void EmitForwardOptionPropertyHandlingCode (const OptionDescription& D,
       << D.GenVariableName() << ".begin(),\n";
     O.indent(IndentLevel) << "E = " << D.GenVariableName()
                           << ".end() ; B != E;) {\n";
-    O.indent(IndentLevel1) << "vec.push_back(\"" << Name << "\");\n";
+    O.indent(IndentLevel1) << "vec.push_back(std::make_pair(0, \""
+                           << Name << "\"));\n";
 
     for (int i = 0, j = D.MultiVal; i < j; ++i) {
-      O.indent(IndentLevel1) << "vec.push_back(*B);\n";
+      O.indent(IndentLevel1) << "vec.push_back(std::make_pair(0, *B));\n";
       O.indent(IndentLevel1) << "++B;\n";
     }
 
@@ -1939,7 +1923,8 @@ class EmitActionHandlersCallback :
   {
     CheckNumberOfArguments(Dag, 1);
     this->EmitHookInvocation(InitPtrToString(Dag.getArg(0)),
-                             "vec.push_back(", ");\n", IndentLevel, O);
+                             "vec.push_back(std::make_pair(0, ", "));\n",
+                             IndentLevel, O);
   }
 
   void onForward (const DagInit& Dag,
@@ -1969,13 +1954,18 @@ class EmitActionHandlersCallback :
     const OptionDescription& D = OptDescs.FindListOrParameter(Name);
 
     if (D.isParameter()) {
-      O.indent(IndentLevel) << "vec.push_back("
-                            << D.GenVariableName() << ");\n";
+      O.indent(IndentLevel) << "vec.push_back(std::make_pair(0, "
+                            << D.GenVariableName() << "));\n";
     }
     else {
-      O.indent(IndentLevel) << "std::copy(" << D.GenVariableName()
-                            << ".begin(), " << D.GenVariableName()
-                            << ".end(), std::back_inserter(vec));\n";
+      O.indent(IndentLevel) << "for (cl::list<std::string>::iterator B = "
+                            << D.GenVariableName() << ".begin(), \n";
+      O.indent(IndentLevel + Indent1) << " E = " << D.GenVariableName()
+                                      << ".end(); B != E; ++B)\n";
+      O.indent(IndentLevel) << "{\n";
+      O.indent(IndentLevel + Indent1)
+        << "vec.push_back(std::make_pair(0, *B));\n";
+      O.indent(IndentLevel) << "}\n";
     }
   }
 
@@ -1987,9 +1977,16 @@ class EmitActionHandlersCallback :
     const std::string& Hook = InitPtrToString(Dag.getArg(1));
     const OptionDescription& D = OptDescs.FindListOrParameter(Name);
 
-    O.indent(IndentLevel) << "vec.push_back(" << "hooks::"
+    O.indent(IndentLevel) << "vec.push_back(std::make_pair(0, " << "hooks::"
                           << Hook << "(" << D.GenVariableName()
-                          << (D.isParameter() ? ".c_str()" : "") << "));\n";
+                          << (D.isParameter() ? ".c_str()" : "") << ")));\n";
+  }
+
+  void onNoOutFile (const DagInit& Dag,
+                    unsigned IndentLevel, raw_ostream& O) const
+  {
+    CheckNumberOfArguments(Dag, 0);
+    O.indent(IndentLevel) << "no_out_file = true;\n";
   }
 
   void onOutputSuffix (const DagInit& Dag,
@@ -2028,12 +2025,15 @@ class EmitActionHandlersCallback :
       AddHandler("forward_value", &EmitActionHandlersCallback::onForwardValue);
       AddHandler("forward_transformed_value",
                  &EmitActionHandlersCallback::onForwardTransformedValue);
+      AddHandler("no_out_file",
+                 &EmitActionHandlersCallback::onNoOutFile);
       AddHandler("output_suffix", &EmitActionHandlersCallback::onOutputSuffix);
       AddHandler("stop_compilation",
                  &EmitActionHandlersCallback::onStopCompilation);
       AddHandler("unpack_values",
                  &EmitActionHandlersCallback::onUnpackValues);
 
+
       staticMembersInitialized_ = true;
     }
   }
@@ -2045,58 +2045,6 @@ class EmitActionHandlersCallback :
   }
 };
 
-bool IsOutFileIndexCheckRequiredStr (const Init* CmdLine) {
-  StrVector StrVec;
-  TokenizeCmdLine(InitPtrToString(CmdLine), StrVec);
-
-  for (StrVector::const_iterator I = StrVec.begin(), E = StrVec.end();
-       I != E; ++I) {
-    if (*I == "$OUTFILE")
-      return false;
-  }
-
-  return true;
-}
-
-class IsOutFileIndexCheckRequiredStrCallback {
-  bool* ret_;
-
-public:
-  IsOutFileIndexCheckRequiredStrCallback(bool* ret) : ret_(ret)
-  {}
-
-  void operator()(const Init* CmdLine) {
-    // Ignore nested 'case' DAG.
-    if (typeid(*CmdLine) == typeid(DagInit))
-      return;
-
-    if (IsOutFileIndexCheckRequiredStr(CmdLine))
-      *ret_ = true;
-  }
-
-  void operator()(const DagInit* Test, unsigned, bool) {
-    this->operator()(Test);
-  }
-  void operator()(const Init* Statement, unsigned) {
-    this->operator()(Statement);
-  }
-};
-
-bool IsOutFileIndexCheckRequiredCase (Init* CmdLine) {
-  bool ret = false;
-  WalkCase(CmdLine, Id(), IsOutFileIndexCheckRequiredStrCallback(&ret));
-  return ret;
-}
-
-/// IsOutFileIndexCheckRequired - Should we emit an "out_file_index != -1" check
-/// in EmitGenerateActionMethod() ?
-bool IsOutFileIndexCheckRequired (Init* CmdLine) {
-  if (typeid(*CmdLine) == typeid(StringInit))
-    return IsOutFileIndexCheckRequiredStr(CmdLine);
-  else
-    return IsOutFileIndexCheckRequiredCase(CmdLine);
-}
-
 void EmitGenerateActionMethodHeader(const ToolDescription& D,
                                     bool IsJoin, raw_ostream& O)
 {
@@ -2111,8 +2059,10 @@ void EmitGenerateActionMethodHeader(const ToolDescription& D,
   O.indent(Indent2) << "const LanguageMap& LangMap) const\n";
   O.indent(Indent1) << "{\n";
   O.indent(Indent2) << "std::string cmd;\n";
-  O.indent(Indent2) << "std::vector<std::string> vec;\n";
+  O.indent(Indent2) << "std::string out_file;\n";
+  O.indent(Indent2) << "std::vector<std::pair<unsigned, std::string> > vec;\n";
   O.indent(Indent2) << "bool stop_compilation = !HasChildren;\n";
+  O.indent(Indent2) << "bool no_out_file = false;\n";
   O.indent(Indent2) << "const char* output_suffix = \""
                     << D.OutputSuffix << "\";\n";
 }
@@ -2128,46 +2078,61 @@ void EmitGenerateActionMethod (const ToolDescription& D,
   if (!D.CmdLine)
     throw "Tool " + D.Name + " has no cmd_line property!";
 
-  bool IndexCheckRequired = IsOutFileIndexCheckRequired(D.CmdLine);
-  O.indent(Indent2) << "int out_file_index"
-                    << (IndexCheckRequired ? " = -1" : "")
-                    << ";\n\n";
-
-  // Process the cmd_line property.
-  if (typeid(*D.CmdLine) == typeid(StringInit))
-    EmitCmdLineVecFill(D.CmdLine, D.Name, IsJoin, Indent2, O);
-  else
-    EmitCaseConstructHandler(D.CmdLine, Indent2,
-                             EmitCmdLineVecFillCallback(IsJoin, D.Name),
-                             true, OptDescs, O);
+  // Process the 'command' property.
+  O << '\n';
+  EmitCmdLineVecFill(D.CmdLine, D.Name, IsJoin, Indent2, O);
+  O << '\n';
 
-  // For every understood option, emit handling code.
+  // Process the 'actions' list of this tool.
   if (D.Actions)
     EmitCaseConstructHandler(D.Actions, Indent2,
                              EmitActionHandlersCallback(OptDescs),
                              false, OptDescs, O);
-
   O << '\n';
-  O.indent(Indent2)
-    << "std::string out_file = OutFilename("
-    << (IsJoin ? "sys::Path(),\n" : "inFile,\n");
-  O.indent(Indent3) << "TempDir, stop_compilation, output_suffix).str();\n\n";
 
-  if (IndexCheckRequired)
-    O.indent(Indent2) << "if (out_file_index != -1)\n";
-  O.indent(IndexCheckRequired ? Indent3 : Indent2)
-    << "vec[out_file_index] = out_file;\n";
+  // Input file (s)
+  if (!D.InFileOption.empty()) {
+    O.indent(Indent2) << "vec.push_back(std::make_pair(0, \""
+                      << D.InFileOption << "\");\n";
+  }
+
+  if (IsJoin) {
+    O.indent(Indent2)
+      << "for (PathVector::const_iterator B = inFiles.begin(),\n";
+    O.indent(Indent3) << "E = inFiles.end(); B != E; ++B)\n";
+    O.indent(Indent2) << "{\n";
+    O.indent(Indent3) << "vec.push_back(std::make_pair(0, B->str()));\n";
+    O.indent(Indent2) << "}\n";
+  }
+  else {
+    O.indent(Indent2) << "vec.push_back(std::make_pair(0, inFile.str()));\n";
+  }
+
+  // Output file
+  O.indent(Indent2) << "if (!no_out_file) {\n";
+  if (!D.OutFileOption.empty())
+    O.indent(Indent3) << "vec.push_back(std::make_pair(0, \""
+                      << D.OutFileOption << "\"));\n";
+
+  O.indent(Indent3) << "out_file = this->OutFilename("
+                    << (IsJoin ? "sys::Path(),\n" : "inFile,\n");
+  O.indent(Indent4) << "TempDir, stop_compilation, output_suffix).str();\n\n";
+  O.indent(Indent3) << "vec.push_back(std::make_pair(0, out_file));\n";
+
+  O.indent(Indent2) << "}\n\n";
 
   // Handle the Sink property.
   if (D.isSink()) {
     O.indent(Indent2) << "if (!" << SinkOptionName << ".empty()) {\n";
-    O.indent(Indent3) << "vec.insert(vec.end(), "
-                      << SinkOptionName << ".begin(), " << SinkOptionName
-                      << ".end());\n";
+    O.indent(Indent3) << "for (cl::list<std::string>::iterator B = "
+                      << SinkOptionName << ".begin(), E = " << SinkOptionName
+                      << ".end(); B != E; ++B)\n";
+    O.indent(Indent4) << "vec.push_back(std::make_pair(0, *B));\n";
     O.indent(Indent2) << "}\n";
   }
 
-  O.indent(Indent2) << "return Action(cmd, vec, stop_compilation, out_file);\n";
+  O.indent(Indent2) << "return Action(cmd, this->SortArgs(vec), "
+                    << "stop_compilation, out_file);\n";
   O.indent(Indent1) << "}\n\n";
 }
 
@@ -3038,7 +3003,7 @@ void LLVMCConfigurationEmitter::run (raw_ostream &O) {
   CollectPluginData(Records, Data);
   CheckPluginData(Data);
 
-  EmitSourceFileHeader("LLVMC Configuration Library", O);
+  this->EmitSourceFileHeader("LLVMC Configuration Library", O);
   EmitPluginCode(Data, O);
 
   } catch (std::exception& Error) {