diff options
Diffstat (limited to 'utils/TableGen/LLVMCConfigurationEmitter.cpp')
| -rw-r--r-- | utils/TableGen/LLVMCConfigurationEmitter.cpp | 502 | 
1 files changed, 318 insertions, 184 deletions
diff --git a/utils/TableGen/LLVMCConfigurationEmitter.cpp b/utils/TableGen/LLVMCConfigurationEmitter.cpp index fc182ce5af8e..06afaf73a02e 100644 --- a/utils/TableGen/LLVMCConfigurationEmitter.cpp +++ b/utils/TableGen/LLVMCConfigurationEmitter.cpp @@ -39,10 +39,11 @@ typedef std::vector<std::string> StrVector;  //===----------------------------------------------------------------------===//  /// Constants -// Indentation strings. -const char * Indent1 = "    "; -const char * Indent2 = "        "; -const char * Indent3 = "            "; +// Indentation. +unsigned TabWidth = 4; +unsigned Indent1  = TabWidth*1; +unsigned Indent2  = TabWidth*2; +unsigned Indent3  = TabWidth*3;  // Default help string.  const char * DefaultHelpString = "NO HELP MESSAGE PROVIDED"; @@ -81,16 +82,15 @@ const DagInit& InitPtrToDag(const Init* ptr) {  }  // checkNumberOfArguments - Ensure that the number of args in d is -// less than or equal to min_arguments, otherwise throw an exception. +// greater than or equal to min_arguments, otherwise throw an exception.  void checkNumberOfArguments (const DagInit* d, unsigned min_arguments) {    if (!d || d->getNumArgs() < min_arguments) -    throw d->getOperator()->getAsString() -      + ": too few arguments!"; +    throw d->getOperator()->getAsString() + ": too few arguments!";  }  // isDagEmpty - is this DAG marked with an empty marker?  bool isDagEmpty (const DagInit* d) { -  return d->getOperator()->getAsString() == "empty"; +  return d->getOperator()->getAsString() == "empty_dag_marker";  }  // EscapeVariableName - Escape commas and other symbols not allowed @@ -139,20 +139,21 @@ void checkedIncrement(I& P, I E, S ErrorString) {  /// OptionType - One of six different option types. See the  /// documentation for detailed description of differences.  namespace OptionType { +    enum OptionType { Alias, Switch, Parameter, ParameterList,                      Prefix, PrefixList}; -bool IsList (OptionType t) { -  return (t == ParameterList || t == PrefixList); -} +  bool IsList (OptionType t) { +    return (t == ParameterList || t == PrefixList); +  } -bool IsSwitch (OptionType t) { -  return (t == Switch); -} +  bool IsSwitch (OptionType t) { +    return (t == Switch); +  } -bool IsParameter (OptionType t) { -  return (t == Parameter || t == Prefix); -} +  bool IsParameter (OptionType t) { +    return (t == Parameter || t == Prefix); +  }  } @@ -187,11 +188,12 @@ struct OptionDescription {    unsigned Flags;    std::string Help;    unsigned MultiVal; +  Init* InitVal;    OptionDescription(OptionType::OptionType t = OptionType::Switch,                      const std::string& n = "",                      const std::string& h = DefaultHelpString) -    : Type(t), Name(n), Flags(0x0), Help(h), MultiVal(1) +    : Type(t), Name(n), Flags(0x0), Help(h), MultiVal(1), InitVal(0)    {}    /// GenTypeDeclaration - Returns the C++ variable type of this @@ -229,6 +231,15 @@ struct OptionDescription {    bool isReallyHidden() const;    void setReallyHidden(); +  bool isParameter() const +  { return OptionType::IsParameter(this->Type); } + +  bool isSwitch() const +  { return OptionType::IsSwitch(this->Type); } + +  bool isList() const +  { return OptionType::IsList(this->Type); } +  };  void OptionDescription::Merge (const OptionDescription& other) @@ -438,6 +449,7 @@ public:        AddHandler("extern", &CollectOptionProperties::onExtern);        AddHandler("help", &CollectOptionProperties::onHelp);        AddHandler("hidden", &CollectOptionProperties::onHidden); +      AddHandler("init", &CollectOptionProperties::onInit);        AddHandler("multi_val", &CollectOptionProperties::onMultiVal);        AddHandler("one_or_more", &CollectOptionProperties::onOneOrMore);        AddHandler("really_hidden", &CollectOptionProperties::onReallyHidden); @@ -481,6 +493,20 @@ private:      optDesc_.setRequired();    } +  void onInit (const DagInit* d) { +    checkNumberOfArguments(d, 1); +    Init* i = d->getArg(0); +    const std::string& str = i->getAsString(); + +    bool correct = optDesc_.isParameter() && dynamic_cast<StringInit*>(i); +    correct |= (optDesc_.isSwitch() && (str == "true" || str == "false")); + +    if (!correct) +      throw std::string("Incorrect usage of the 'init' option property!"); + +    optDesc_.InitVal = i; +  } +    void onOneOrMore (const DagInit* d) {      checkNumberOfArguments(d, 0);      if (optDesc_.isRequired() || optDesc_.isZeroOrOne()) @@ -950,8 +976,22 @@ void CheckForSuperfluousOptions (const RecordVector& Edges,    }  } -/// EmitCaseTest1Arg - Helper function used by -/// EmitCaseConstructHandler. +/// EmitCaseTest0Args - Helper function used by EmitCaseConstructHandler(). +bool EmitCaseTest0Args(const std::string& TestName, raw_ostream& O) { +  if (TestName == "single_input_file") { +    O << "InputFilenames.size() == 1"; +    return true; +  } +  else if (TestName == "multiple_input_files") { +    O << "InputFilenames.size() > 1"; +    return true; +  } + +  return false; +} + + +/// EmitCaseTest1Arg - Helper function used by EmitCaseConstructHandler().  bool EmitCaseTest1Arg(const std::string& TestName,                        const DagInit& d,                        const OptionDescriptions& OptDescs, @@ -961,7 +1001,7 @@ bool EmitCaseTest1Arg(const std::string& TestName,    if (TestName == "switch_on") {      const OptionDescription& OptDesc = OptDescs.FindOption(OptName); -    if (!OptionType::IsSwitch(OptDesc.Type)) +    if (!OptDesc.isSwitch())        throw OptName + ": incorrect option type - should be a switch!";      O << OptDesc.GenVariableName();      return true; @@ -984,7 +1024,7 @@ bool EmitCaseTest1Arg(const std::string& TestName,      }      else {        const OptionDescription& OptDesc = OptDescs.FindOption(OptName); -      if (OptionType::IsSwitch(OptDesc.Type)) +      if (OptDesc.isSwitch())          throw OptName            + ": incorrect option type - should be a list or parameter!";        O << Test << OptDesc.GenVariableName() << ".empty()"; @@ -995,11 +1035,10 @@ bool EmitCaseTest1Arg(const std::string& TestName,    return false;  } -/// EmitCaseTest2Args - Helper function used by -/// EmitCaseConstructHandler. +/// EmitCaseTest2Args - Helper function used by EmitCaseConstructHandler().  bool EmitCaseTest2Args(const std::string& TestName,                         const DagInit& d, -                       const char* IndentLevel, +                       unsigned IndentLevel,                         const OptionDescriptions& OptDescs,                         raw_ostream& O) {    checkNumberOfArguments(&d, 2); @@ -1008,17 +1047,18 @@ bool EmitCaseTest2Args(const std::string& TestName,    const OptionDescription& OptDesc = OptDescs.FindOption(OptName);    if (TestName == "parameter_equals") { -    if (!OptionType::IsParameter(OptDesc.Type)) +    if (!OptDesc.isParameter())        throw OptName + ": incorrect option type - should be a parameter!";      O << OptDesc.GenVariableName() << " == \"" << OptArg << "\"";      return true;    }    else if (TestName == "element_in_list") { -    if (!OptionType::IsList(OptDesc.Type)) +    if (!OptDesc.isList())        throw OptName + ": incorrect option type - should be a list!";      const std::string& VarName = OptDesc.GenVariableName(); -    O << "std::find(" << VarName << ".begin(),\n" -      << IndentLevel << Indent1 << VarName << ".end(), \"" +    O << "std::find(" << VarName << ".begin(),\n"; +    O.indent(IndentLevel + Indent1) +      << VarName << ".end(), \""        << OptArg << "\") != " << VarName << ".end()";      return true;    } @@ -1028,29 +1068,42 @@ bool EmitCaseTest2Args(const std::string& TestName,  // Forward declaration.  // EmitLogicalOperationTest and EmitCaseTest are mutually recursive. -void EmitCaseTest(const DagInit& d, const char* IndentLevel, +void EmitCaseTest(const DagInit& d, unsigned IndentLevel,                    const OptionDescriptions& OptDescs,                    raw_ostream& O);  /// EmitLogicalOperationTest - Helper function used by  /// EmitCaseConstructHandler.  void EmitLogicalOperationTest(const DagInit& d, const char* LogicOp, -                              const char* IndentLevel, +                              unsigned IndentLevel,                                const OptionDescriptions& OptDescs,                                raw_ostream& O) {    O << '(';    for (unsigned j = 0, NumArgs = d.getNumArgs(); j < NumArgs; ++j) {      const DagInit& InnerTest = InitPtrToDag(d.getArg(j));      EmitCaseTest(InnerTest, IndentLevel, OptDescs, O); -    if (j != NumArgs - 1) -      O << ")\n" << IndentLevel << Indent1 << ' ' << LogicOp << " ("; -    else +    if (j != NumArgs - 1) { +      O << ")\n"; +      O.indent(IndentLevel + Indent1) << ' ' << LogicOp << " ("; +    } +    else {        O << ')'; +    }    }  } +void EmitLogicalNot(const DagInit& d, unsigned IndentLevel, +                    const OptionDescriptions& OptDescs, raw_ostream& O) +{ +  checkNumberOfArguments(&d, 1); +  const DagInit& InnerTest = InitPtrToDag(d.getArg(0)); +  O << "! ("; +  EmitCaseTest(InnerTest, IndentLevel, OptDescs, O); +  O << ")"; +} +  /// EmitCaseTest - Helper function used by EmitCaseConstructHandler. -void EmitCaseTest(const DagInit& d, const char* IndentLevel, +void EmitCaseTest(const DagInit& d, unsigned IndentLevel,                    const OptionDescriptions& OptDescs,                    raw_ostream& O) {    const std::string& TestName = d.getOperator()->getAsString(); @@ -1059,6 +1112,10 @@ void EmitCaseTest(const DagInit& d, const char* IndentLevel,      EmitLogicalOperationTest(d, "&&", IndentLevel, OptDescs, O);    else if (TestName == "or")      EmitLogicalOperationTest(d, "||", IndentLevel, OptDescs, O); +  else if (TestName == "not") +    EmitLogicalNot(d, IndentLevel, OptDescs, O); +  else if (EmitCaseTest0Args(TestName, O)) +    return;    else if (EmitCaseTest1Arg(TestName, d, OptDescs, O))      return;    else if (EmitCaseTest2Args(TestName, d, IndentLevel, OptDescs, O)) @@ -1070,9 +1127,9 @@ void EmitCaseTest(const DagInit& d, const char* IndentLevel,  // Emit code that handles the 'case' construct.  // Takes a function object that should emit code for every case clause.  // Callback's type is -// void F(Init* Statement, const char* IndentLevel, raw_ostream& O). +// void F(Init* Statement, unsigned IndentLevel, raw_ostream& O).  template <typename F> -void EmitCaseConstructHandler(const Init* Dag, const char* IndentLevel, +void EmitCaseConstructHandler(const Init* Dag, unsigned IndentLevel,                                F Callback, bool EmitElseIf,                                const OptionDescriptions& OptDescs,                                raw_ostream& O) { @@ -1094,10 +1151,10 @@ void EmitCaseConstructHandler(const Init* Dag, const char* IndentLevel,        if (i+2 != numArgs)          throw std::string("The 'default' clause should be the last in the"                            "'case' construct!"); -      O << IndentLevel << "else {\n"; +      O.indent(IndentLevel) << "else {\n";      }      else { -      O << IndentLevel << ((i != 0 && EmitElseIf) ? "else if (" : "if ("); +      O.indent(IndentLevel) << ((i != 0 && EmitElseIf) ? "else if (" : "if (");        EmitCaseTest(Test, IndentLevel, OptDescs, O);        O << ") {\n";      } @@ -1112,13 +1169,13 @@ void EmitCaseConstructHandler(const Init* Dag, const char* IndentLevel,      const DagInit* nd = dynamic_cast<DagInit*>(arg);      if (nd && (nd->getOperator()->getAsString() == "case")) {        // Handle the nested 'case'. -      EmitCaseConstructHandler(nd, (std::string(IndentLevel) + Indent1).c_str(), +      EmitCaseConstructHandler(nd, (IndentLevel + Indent1),                                 Callback, EmitElseIf, OptDescs, O);      }      else { -      Callback(arg, (std::string(IndentLevel) + Indent1).c_str(), O); +      Callback(arg, (IndentLevel + Indent1), O);      } -    O << IndentLevel << "}\n"; +    O.indent(IndentLevel) << "}\n";    }  } @@ -1272,7 +1329,7 @@ StrVector::const_iterator SubstituteSpecialCommands  /// EmitCmdLineVecFill - Emit code that fills in the command line  /// vector. Helper function used by EmitGenerateActionMethod().  void EmitCmdLineVecFill(const Init* CmdLine, const std::string& ToolName, -                        bool IsJoin, const char* IndentLevel, +                        bool IsJoin, unsigned IndentLevel,                          raw_ostream& O) {    StrVector StrVec;    TokenizeCmdline(InitPtrToString(CmdLine), StrVec); @@ -1295,22 +1352,28 @@ void EmitCmdLineVecFill(const Init* CmdLine, const std::string& ToolName,      ++I;    } +  bool hasINFILE = false; +    for (; I != E; ++I) {      const std::string& cmd = *I;      assert(!cmd.empty()); -    O << IndentLevel; +    O.indent(IndentLevel);      if (cmd.at(0) == '$') {        if (cmd == "$INFILE") { -        if (IsJoin) +        hasINFILE = true; +        if (IsJoin) {            O << "for (PathVector::const_iterator B = inFiles.begin()" -            << ", E = inFiles.end();\n" -            << IndentLevel << "B != E; ++B)\n" -            << IndentLevel << Indent1 << "vec.push_back(B->toString());\n"; -        else -          O << "vec.push_back(inFile.toString());\n"; +            << ", 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(out_file);\n"; +        O << "vec.push_back(\"\");\n"; +        O.indent(IndentLevel) << "out_file_index = vec.size()-1;\n";        }        else {          O << "vec.push_back("; @@ -1322,8 +1385,10 @@ void EmitCmdLineVecFill(const Init* CmdLine, const std::string& ToolName,        O << "vec.push_back(\"" << cmd << "\");\n";      }    } -  O << IndentLevel << "cmd = "; +  if (!hasINFILE) +    throw "Tool '" + ToolName + "' doesn't take any input!"; +  O.indent(IndentLevel) << "cmd = ";    if (StrVec[0][0] == '$')      SubstituteSpecialCommands(StrVec.begin(), StrVec.end(), O);    else @@ -1341,11 +1406,10 @@ class EmitCmdLineVecFillCallback {    EmitCmdLineVecFillCallback(bool J, const std::string& TN)      : IsJoin(J), ToolName(TN) {} -  void operator()(const Init* Statement, const char* IndentLevel, +  void operator()(const Init* Statement, unsigned IndentLevel,                    raw_ostream& O) const    { -    EmitCmdLineVecFill(Statement, ToolName, IsJoin, -                       IndentLevel, O); +    EmitCmdLineVecFill(Statement, ToolName, IsJoin, IndentLevel, O);    }  }; @@ -1353,53 +1417,56 @@ class EmitCmdLineVecFillCallback {  /// implement EmitActionHandler. Emits code for  /// handling the (forward) and (forward_as) option properties.  void EmitForwardOptionPropertyHandlingCode (const OptionDescription& D, -                                            const char* Indent, +                                            unsigned IndentLevel,                                              const std::string& NewName,                                              raw_ostream& O) {    const std::string& Name = NewName.empty()      ? ("-" + D.Name)      : NewName; +  unsigned IndentLevel1 = IndentLevel + Indent1;    switch (D.Type) {    case OptionType::Switch: -    O << Indent << "vec.push_back(\"" << Name << "\");\n"; +    O.indent(IndentLevel) << "vec.push_back(\"" << Name << "\");\n";      break;    case OptionType::Parameter: -    O << Indent << "vec.push_back(\"" << Name << "\");\n"; -    O << Indent << "vec.push_back(" << D.GenVariableName() << ");\n"; +    O.indent(IndentLevel) << "vec.push_back(\"" << Name << "\");\n"; +    O.indent(IndentLevel) << "vec.push_back(" << D.GenVariableName() << ");\n";      break;    case OptionType::Prefix: -    O << Indent << "vec.push_back(\"" << Name << "\" + " -      << D.GenVariableName() << ");\n"; +    O.indent(IndentLevel) << "vec.push_back(\"" << Name << "\" + " +                          << D.GenVariableName() << ");\n";      break;    case OptionType::PrefixList: -    O << Indent << "for (" << D.GenTypeDeclaration() -      << "::iterator B = " << D.GenVariableName() << ".begin(),\n" -      << Indent << "E = " << D.GenVariableName() << ".end(); B != E;) {\n" -      << Indent << Indent1 << "vec.push_back(\"" << Name << "\" + " -      << "*B);\n" -      << Indent << Indent1 << "++B;\n"; +    O.indent(IndentLevel) +      << "for (" << D.GenTypeDeclaration() +      << "::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) << "++B;\n";      for (int i = 1, j = D.MultiVal; i < j; ++i) { -      O << Indent << Indent1 << "vec.push_back(*B);\n" -        << Indent << Indent1 << "++B;\n"; +      O.indent(IndentLevel1) << "vec.push_back(*B);\n"; +      O.indent(IndentLevel1) << "++B;\n";      } -    O << Indent << "}\n"; +    O.indent(IndentLevel) << "}\n";      break;    case OptionType::ParameterList: -    O << Indent << "for (" << D.GenTypeDeclaration() -      << "::iterator B = " << D.GenVariableName() << ".begin(),\n" -      << Indent << "E = " << D.GenVariableName() -      << ".end() ; B != E;) {\n" -      << Indent << Indent1 << "vec.push_back(\"" << Name << "\");\n"; +    O.indent(IndentLevel) +      << "for (" << D.GenTypeDeclaration() << "::iterator B = " +      << D.GenVariableName() << ".begin(),\n"; +    O.indent(IndentLevel) << "E = " << D.GenVariableName() +                          << ".end() ; B != E;) {\n"; +    O.indent(IndentLevel1) << "vec.push_back(\"" << Name << "\");\n";      for (int i = 0, j = D.MultiVal; i < j; ++i) { -      O << Indent << Indent1 << "vec.push_back(*B);\n" -        << Indent << Indent1 << "++B;\n"; +      O.indent(IndentLevel1) << "vec.push_back(*B);\n"; +      O.indent(IndentLevel1) << "++B;\n";      } -    O << Indent << "}\n"; +    O.indent(IndentLevel) << "}\n";      break;    case OptionType::Alias:    default: @@ -1413,7 +1480,7 @@ void EmitForwardOptionPropertyHandlingCode (const OptionDescription& D,  class EmitActionHandler {    const OptionDescriptions& OptDescs; -  void processActionDag(const Init* Statement, const char* IndentLevel, +  void processActionDag(const Init* Statement, unsigned IndentLevel,                          raw_ostream& O) const    {      const DagInit& Dag = InitPtrToDag(Statement); @@ -1427,10 +1494,10 @@ class EmitActionHandler {        for (StrVector::const_iterator B = Out.begin(), E = Out.end();             B != E; ++B) -        O << IndentLevel << "vec.push_back(\"" << *B << "\");\n"; +        O.indent(IndentLevel) << "vec.push_back(\"" << *B << "\");\n";      }      else if (ActionName == "error") { -      O << IndentLevel << "throw std::runtime_error(\"" << +      O.indent(IndentLevel) << "throw std::runtime_error(\"" <<          (Dag.getNumArgs() >= 1 ? InitPtrToString(Dag.getArg(0))           : "Unknown error!")          << "\");\n"; @@ -1451,10 +1518,10 @@ class EmitActionHandler {      else if (ActionName == "output_suffix") {        checkNumberOfArguments(&Dag, 1);        const std::string& OutSuf = InitPtrToString(Dag.getArg(0)); -      O << IndentLevel << "output_suffix = \"" << OutSuf << "\";\n"; +      O.indent(IndentLevel) << "output_suffix = \"" << OutSuf << "\";\n";      }      else if (ActionName == "stop_compilation") { -      O << IndentLevel << "stop_compilation = true;\n"; +      O.indent(IndentLevel) << "stop_compilation = true;\n";      }      else if (ActionName == "unpack_values") {        checkNumberOfArguments(&Dag, 1); @@ -1464,16 +1531,18 @@ class EmitActionHandler {        if (D.isMultiVal())          throw std::string("Can't use unpack_values with multi-valued options!"); -      if (OptionType::IsList(D.Type)) { -        O << IndentLevel << "for (" << D.GenTypeDeclaration() -          << "::iterator B = " << D.GenVariableName() << ".begin(),\n" -          << IndentLevel << "E = " << D.GenVariableName() -          << ".end(); B != E; ++B)\n" -          << IndentLevel << Indent1 << "llvm::SplitString(*B, vec, \",\");\n"; +      if (D.isList()) { +        O.indent(IndentLevel) +          << "for (" << D.GenTypeDeclaration() +          << "::iterator B = " << D.GenVariableName() << ".begin(),\n"; +        O.indent(IndentLevel) +          << "E = " << D.GenVariableName() << ".end(); B != E; ++B)\n"; +        O.indent(IndentLevel + Indent1) +          << "llvm::SplitString(*B, vec, \",\");\n";        } -      else if (OptionType::IsParameter(D.Type)){ -        O << Indent3 << "llvm::SplitString(" -          << D.GenVariableName() << ", vec, \",\");\n"; +      else if (D.isParameter()){ +        O.indent(IndentLevel) << "llvm::SplitString(" +                              << D.GenVariableName() << ", vec, \",\");\n";        }        else {          throw "Option '" + D.Name + @@ -1488,7 +1557,7 @@ class EmitActionHandler {    EmitActionHandler(const OptionDescriptions& OD)      : OptDescs(OD) {} -  void operator()(const Init* Statement, const char* IndentLevel, +  void operator()(const Init* Statement, unsigned IndentLevel,                    raw_ostream& O) const    {      if (typeid(*Statement) == typeid(ListInit)) { @@ -1503,56 +1572,111 @@ class EmitActionHandler {    }  }; -// EmitGenerateActionMethod - Emit one of two versions of the +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) { +    if (IsOutFileIndexCheckRequiredStr(CmdLine)) +      *ret_ = true; +  } +}; + +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); +} + +// EmitGenerateActionMethod - Emit either a normal or a "join" version of the  // Tool::GenerateAction() method.  void EmitGenerateActionMethod (const ToolDescription& D,                                 const OptionDescriptions& OptDescs,                                 bool IsJoin, raw_ostream& O) {    if (IsJoin) -    O << Indent1 << "Action GenerateAction(const PathVector& inFiles,\n"; +    O.indent(Indent1) << "Action GenerateAction(const PathVector& inFiles,\n";    else -    O << Indent1 << "Action GenerateAction(const sys::Path& inFile,\n"; - -  O << Indent2 << "bool HasChildren,\n" -    << Indent2 << "const llvm::sys::Path& TempDir,\n" -    << Indent2 << "const InputLanguagesSet& InLangs,\n" -    << Indent2 << "const LanguageMap& LangMap) const\n" -    << Indent1 << "{\n" -    << Indent2 << "std::string cmd;\n" -    << Indent2 << "std::vector<std::string> vec;\n" -    << Indent2 << "bool stop_compilation = !HasChildren;\n" -    << Indent2 << "const char* output_suffix = \"" << D.OutputSuffix << "\";\n" -    << Indent2 << "std::string out_file;\n\n"; - -  // For every understood option, emit handling code. -  if (D.Actions) -    EmitCaseConstructHandler(D.Actions, Indent2, EmitActionHandler(OptDescs), -                             false, OptDescs, O); - -  O << '\n' << Indent2 -    << "out_file = OutFilename(" << (IsJoin ? "sys::Path(),\n" : "inFile,\n") -    << Indent3 << "TempDir, stop_compilation, output_suffix).toString();\n\n"; +    O.indent(Indent1) << "Action GenerateAction(const sys::Path& inFile,\n"; + +  O.indent(Indent2) << "bool HasChildren,\n"; +  O.indent(Indent2) << "const llvm::sys::Path& TempDir,\n"; +  O.indent(Indent2) << "const InputLanguagesSet& InLangs,\n"; +  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) << "bool stop_compilation = !HasChildren;\n"; +  O.indent(Indent2) << "const char* output_suffix = \"" +                    << D.OutputSuffix << "\";\n"; -  // cmd_line is either a string or a 'case' construct.    if (!D.CmdLine)      throw "Tool " + D.Name + " has no cmd_line property!"; -  else if (typeid(*D.CmdLine) == typeid(StringInit)) + +  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); +  // For every understood option, emit handling code. +  if (D.Actions) +    EmitCaseConstructHandler(D.Actions, Indent2, EmitActionHandler(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"; +    // Handle the Sink property.    if (D.isSink()) { -    O << Indent2 << "if (!" << SinkOptionName << ".empty()) {\n" -      << Indent3 << "vec.insert(vec.end(), " -      << SinkOptionName << ".begin(), " << SinkOptionName << ".end());\n" -      << Indent2 << "}\n"; +    O.indent(Indent2) << "if (!" << SinkOptionName << ".empty()) {\n"; +    O.indent(Indent3) << "vec.insert(vec.end(), " +                      << SinkOptionName << ".begin(), " << SinkOptionName +                      << ".end());\n"; +    O.indent(Indent2) << "}\n";    } -  O << Indent2 << "return Action(cmd, vec, stop_compilation, out_file);\n" -    << Indent1 << "}\n\n"; +  O.indent(Indent2) << "return Action(cmd, vec, stop_compilation, out_file);\n"; +  O.indent(Indent1) << "}\n\n";  }  /// EmitGenerateActionMethods - Emit two GenerateAction() methods for @@ -1560,18 +1684,20 @@ void EmitGenerateActionMethod (const ToolDescription& D,  void EmitGenerateActionMethods (const ToolDescription& ToolDesc,                                  const OptionDescriptions& OptDescs,                                  raw_ostream& O) { -  if (!ToolDesc.isJoin()) -    O << Indent1 << "Action GenerateAction(const PathVector& inFiles,\n" -      << Indent2 << "bool HasChildren,\n" -      << Indent2 << "const llvm::sys::Path& TempDir,\n" -      << Indent2 << "const InputLanguagesSet& InLangs,\n" -      << Indent2 << "const LanguageMap& LangMap) const\n" -      << Indent1 << "{\n" -      << Indent2 << "throw std::runtime_error(\"" << ToolDesc.Name -      << " is not a Join tool!\");\n" -      << Indent1 << "}\n\n"; -  else +  if (!ToolDesc.isJoin()) { +    O.indent(Indent1) << "Action GenerateAction(const PathVector& inFiles,\n"; +    O.indent(Indent2) << "bool HasChildren,\n"; +    O.indent(Indent2) << "const llvm::sys::Path& TempDir,\n"; +    O.indent(Indent2) << "const InputLanguagesSet& InLangs,\n"; +    O.indent(Indent2) << "const LanguageMap& LangMap) const\n"; +    O.indent(Indent1) << "{\n"; +    O.indent(Indent2) << "throw std::runtime_error(\"" << ToolDesc.Name +                      << " is not a Join tool!\");\n"; +    O.indent(Indent1) << "}\n\n"; +  } +  else {      EmitGenerateActionMethod(ToolDesc, OptDescs, true, O); +  }    EmitGenerateActionMethod(ToolDesc, OptDescs, false, O);  } @@ -1579,34 +1705,34 @@ void EmitGenerateActionMethods (const ToolDescription& ToolDesc,  /// EmitInOutLanguageMethods - Emit the [Input,Output]Language()  /// methods for a given Tool class.  void EmitInOutLanguageMethods (const ToolDescription& D, raw_ostream& O) { -  O << Indent1 << "const char** InputLanguages() const {\n" -    << Indent2 << "return InputLanguages_;\n" -    << Indent1 << "}\n\n"; +  O.indent(Indent1) << "const char** InputLanguages() const {\n"; +  O.indent(Indent2) << "return InputLanguages_;\n"; +  O.indent(Indent1) << "}\n\n";    if (D.OutLanguage.empty())      throw "Tool " + D.Name + " has no 'out_language' property!"; -  O << Indent1 << "const char* OutputLanguage() const {\n" -    << Indent2 << "return \"" << D.OutLanguage << "\";\n" -    << Indent1 << "}\n\n"; +  O.indent(Indent1) << "const char* OutputLanguage() const {\n"; +  O.indent(Indent2) << "return \"" << D.OutLanguage << "\";\n"; +  O.indent(Indent1) << "}\n\n";  }  /// EmitNameMethod - Emit the Name() method for a given Tool class.  void EmitNameMethod (const ToolDescription& D, raw_ostream& O) { -  O << Indent1 << "const char* Name() const {\n" -    << Indent2 << "return \"" << D.Name << "\";\n" -    << Indent1 << "}\n\n"; +  O.indent(Indent1) << "const char* Name() const {\n"; +  O.indent(Indent2) << "return \"" << D.Name << "\";\n"; +  O.indent(Indent1) << "}\n\n";  }  /// EmitIsJoinMethod - Emit the IsJoin() method for a given Tool  /// class.  void EmitIsJoinMethod (const ToolDescription& D, raw_ostream& O) { -  O << Indent1 << "bool IsJoin() const {\n"; +  O.indent(Indent1) << "bool IsJoin() const {\n";    if (D.isJoin()) -    O << Indent2 << "return true;\n"; +    O.indent(Indent2) << "return true;\n";    else -    O << Indent2 << "return false;\n"; -  O << Indent1 << "}\n\n"; +    O.indent(Indent2) << "return false;\n"; +  O.indent(Indent1) << "}\n\n";  }  /// EmitStaticMemberDefinitions - Emit static member definitions for a @@ -1636,8 +1762,8 @@ void EmitToolClassDefinition (const ToolDescription& D,    else      O << "Tool"; -  O << "{\nprivate:\n" -    << Indent1 << "static const char* InputLanguages_[];\n\n"; +  O << "{\nprivate:\n"; +  O.indent(Indent1) << "static const char* InputLanguages_[];\n\n";    O << "public:\n";    EmitNameMethod(D, O); @@ -1687,15 +1813,15 @@ void EmitOptionDefinitions (const OptionDescriptions& descs,        O << ", cl::Prefix";      if (val.isRequired()) { -      if (OptionType::IsList(val.Type) && !val.isMultiVal()) +      if (val.isList() && !val.isMultiVal())          O << ", cl::OneOrMore";        else          O << ", cl::Required";      } -    else if (val.isOneOrMore() && OptionType::IsList(val.Type)) { +    else if (val.isOneOrMore() && val.isList()) {          O << ", cl::OneOrMore";      } -    else if (val.isZeroOrOne() && OptionType::IsList(val.Type)) { +    else if (val.isZeroOrOne() && val.isList()) {          O << ", cl::ZeroOrOne";      } @@ -1707,7 +1833,12 @@ void EmitOptionDefinitions (const OptionDescriptions& descs,      }      if (val.MultiVal > 1) -      O << ", cl::multi_val(" << val.MultiVal << ")"; +      O << ", cl::multi_val(" << val.MultiVal << ')'; + +    if (val.InitVal) { +      const std::string& str = val.InitVal->getAsString(); +      O << ", cl::init(" << str << ')'; +    }      if (!val.Help.empty())        O << ", cl::desc(\"" << val.Help << "\")"; @@ -1762,9 +1893,9 @@ void EmitPopulateLanguageMap (const RecordKeeper& Records, raw_ostream& O)        const ListInit* Suffixes = LangToSuffixes->getValueAsListInit("suffixes");        for (unsigned i = 0; i < Suffixes->size(); ++i) -        O << Indent1 << "langMap[\"" -          << InitPtrToString(Suffixes->getElement(i)) -          << "\"] = \"" << Lang << "\";\n"; +        O.indent(Indent1) << "langMap[\"" +                          << InitPtrToString(Suffixes->getElement(i)) +                          << "\"] = \"" << Lang << "\";\n";      }    } @@ -1773,21 +1904,22 @@ void EmitPopulateLanguageMap (const RecordKeeper& Records, raw_ostream& O)  /// IncDecWeight - Helper function passed to EmitCaseConstructHandler()  /// by EmitEdgeClass(). -void IncDecWeight (const Init* i, const char* IndentLevel, +void IncDecWeight (const Init* i, unsigned IndentLevel,                     raw_ostream& O) {    const DagInit& d = InitPtrToDag(i);    const std::string& OpName = d.getOperator()->getAsString();    if (OpName == "inc_weight") { -    O << IndentLevel << "ret += "; +    O.indent(IndentLevel) << "ret += ";    }    else if (OpName == "dec_weight") { -    O << IndentLevel << "ret -= "; +    O.indent(IndentLevel) << "ret -= ";    }    else if (OpName == "error") { -    O << IndentLevel << "throw std::runtime_error(\"" << -        (d.getNumArgs() >= 1 ? InitPtrToString(d.getArg(0)) -         : "Unknown error!") +    O.indent(IndentLevel) +      << "throw std::runtime_error(\"" << +      (d.getNumArgs() >= 1 ? InitPtrToString(d.getArg(0)) +       : "Unknown error!")        << "\");\n";      return;    } @@ -1810,19 +1942,20 @@ void EmitEdgeClass (unsigned N, const std::string& Target,    // Class constructor.    O << "class Edge" << N << ": public Edge {\n" -    << "public:\n" -    << Indent1 << "Edge" << N << "() : Edge(\"" << Target -    << "\") {}\n\n" +    << "public:\n"; +  O.indent(Indent1) << "Edge" << N << "() : Edge(\"" << Target +                    << "\") {}\n\n";    // Function Weight(). -    << Indent1 << "unsigned Weight(const InputLanguagesSet& InLangs) const {\n" -    << Indent2 << "unsigned ret = 0;\n"; +  O.indent(Indent1) +    << "unsigned Weight(const InputLanguagesSet& InLangs) const {\n"; +  O.indent(Indent2) << "unsigned ret = 0;\n";    // Handle the 'case' construct.    EmitCaseConstructHandler(Case, Indent2, IncDecWeight, false, OptDescs, O); -  O << Indent2 << "return ret;\n" -    << Indent1 << "};\n\n};\n\n"; +  O.indent(Indent2) << "return ret;\n"; +  O.indent(Indent1) << "};\n\n};\n\n";  }  /// EmitEdgeClasses - Emit Edge* classes that represent graph edges. @@ -1852,7 +1985,7 @@ void EmitPopulateCompilationGraph (const RecordVector& EdgeVector,    for (ToolDescriptions::const_iterator B = ToolDescs.begin(),           E = ToolDescs.end(); B != E; ++B) -    O << Indent1 << "G.insertNode(new " << (*B)->Name << "());\n"; +    O.indent(Indent1) << "G.insertNode(new " << (*B)->Name << "());\n";    O << '\n'; @@ -1866,7 +1999,7 @@ void EmitPopulateCompilationGraph (const RecordVector& EdgeVector,      const std::string& NodeB = Edge->getValueAsString("b");      DagInit* Weight = Edge->getValueAsDag("weight"); -    O << Indent1 << "G.insertEdge(\"" << NodeA << "\", "; +    O.indent(Indent1) << "G.insertEdge(\"" << NodeA << "\", ";      if (isDagEmpty(Weight))        O << "new SimpleEdge(\"" << NodeB << "\")"; @@ -1955,7 +2088,7 @@ void EmitHookDeclarations(const ToolDescriptions& ToolDescs, raw_ostream& O) {    O << "namespace hooks {\n";    for (StringMap<unsigned>::const_iterator B = HookNames.begin(),           E = HookNames.end(); B != E; ++B) { -    O << Indent1 << "std::string " << B->first() << "("; +    O.indent(Indent1) << "std::string " << B->first() << "(";      for (unsigned i = 0, j = B->second; i < j; ++i) {        O << "const char* Arg" << i << (i+1 == j ? "" : ", "); @@ -1968,22 +2101,23 @@ void EmitHookDeclarations(const ToolDescriptions& ToolDescs, raw_ostream& O) {  /// EmitRegisterPlugin - Emit code to register this plugin.  void EmitRegisterPlugin(int Priority, raw_ostream& O) { -  O << "struct Plugin : public llvmc::BasePlugin {\n\n" -    << Indent1 << "int Priority() const { return " << Priority << "; }\n\n" -    << Indent1 << "void PopulateLanguageMap(LanguageMap& langMap) const\n" -    << Indent1 << "{ PopulateLanguageMapLocal(langMap); }\n\n" -    << Indent1 -    << "void PopulateCompilationGraph(CompilationGraph& graph) const\n" -    << Indent1 << "{ PopulateCompilationGraphLocal(graph); }\n" -    << "};\n\n" - -    << "static llvmc::RegisterPlugin<Plugin> RP;\n\n"; +  O << "struct Plugin : public llvmc::BasePlugin {\n\n"; +  O.indent(Indent1) << "int Priority() const { return " +                    << Priority << "; }\n\n"; +  O.indent(Indent1) << "void PopulateLanguageMap(LanguageMap& langMap) const\n"; +  O.indent(Indent1) << "{ PopulateLanguageMapLocal(langMap); }\n\n"; +  O.indent(Indent1) +    << "void PopulateCompilationGraph(CompilationGraph& graph) const\n"; +  O.indent(Indent1) << "{ PopulateCompilationGraphLocal(graph); }\n" +                    << "};\n\n" +                    << "static llvmc::RegisterPlugin<Plugin> RP;\n\n";  }  /// EmitIncludes - Emit necessary #include directives and some  /// additional declarations.  void EmitIncludes(raw_ostream& O) { -  O << "#include \"llvm/CompilerDriver/CompilationGraph.h\"\n" +  O << "#include \"llvm/CompilerDriver/BuiltinOptions.h\"\n" +    << "#include \"llvm/CompilerDriver/CompilationGraph.h\"\n"      << "#include \"llvm/CompilerDriver/ForceLinkageMacros.h\"\n"      << "#include \"llvm/CompilerDriver/Plugin.h\"\n"      << "#include \"llvm/CompilerDriver/Tool.h\"\n\n"  | 
