llvmc: Add a new option type (switch_list).
[oota-llvm.git] / utils / TableGen / LLVMCConfigurationEmitter.cpp
index da2d54f5439b9e31f18d1090a07ac6e48d85bd93..fe14765d20059643edcec28f1146a54e8085ba4b 100644 (file)
@@ -188,21 +188,25 @@ void apply(F Fun, T0& Arg0, T1& Arg1) {
 /// documentation for detailed description of differences.
 namespace OptionType {
 
-  enum OptionType { Alias, Switch, Parameter, ParameterList,
-                    Prefix, PrefixList};
+  enum OptionType { Alias, Switch, SwitchList,
+                    Parameter, ParameterList, Prefix, PrefixList };
 
   bool IsAlias(OptionType t) {
     return (t == Alias);
   }
 
   bool IsList (OptionType t) {
-    return (t == ParameterList || t == PrefixList);
+    return (t == SwitchList || t == ParameterList || t == PrefixList);
   }
 
   bool IsSwitch (OptionType t) {
     return (t == Switch);
   }
 
+  bool IsSwitchList (OptionType t) {
+    return (t == SwitchList);
+  }
+
   bool IsParameter (OptionType t) {
     return (t == Parameter || t == Prefix);
   }
@@ -214,6 +218,8 @@ OptionType::OptionType stringToOptionType(const std::string& T) {
     return OptionType::Alias;
   else if (T == "switch_option")
     return OptionType::Switch;
+  else if (T == "switch_list_option")
+    return OptionType::SwitchList;
   else if (T == "parameter_option")
     return OptionType::Parameter;
   else if (T == "parameter_list_option")
@@ -300,6 +306,9 @@ struct OptionDescription {
   bool isSwitch() const
   { return OptionType::IsSwitch(this->Type); }
 
+  bool isSwitchList() const
+  { return OptionType::IsSwitchList(this->Type); }
+
   bool isParameter() const
   { return OptionType::IsParameter(this->Type); }
 
@@ -417,6 +426,8 @@ const char* OptionDescription::GenTypeDeclaration() const {
     return "cl::list<std::string>";
   case OptionType::Switch:
     return "cl::opt<bool>";
+  case OptionType::SwitchList:
+    return "cl::list<bool>";
   case OptionType::Parameter:
   case OptionType::Prefix:
   default:
@@ -434,6 +445,8 @@ std::string OptionDescription::GenVariableName() const {
     return "AutoGeneratedList_" + EscapedName;
   case OptionType::Switch:
     return "AutoGeneratedSwitch_" + EscapedName;
+  case OptionType::SwitchList:
+    return "AutoGeneratedSwitchList_" + EscapedName;
   case OptionType::Prefix:
   case OptionType::Parameter:
   default:
@@ -709,7 +722,7 @@ private:
   void onZeroOrMore (const DagInit& d) {
     CheckNumberOfArguments(d, 0);
 
-    if (OptionType::IsList(optDesc_.Type))
+    if (optDesc_.isList())
       llvm::errs() << "Warning: specifying the 'zero_or_more' property "
         "on a list option has no effect.\n";
 
@@ -720,7 +733,7 @@ private:
   void onOptional (const DagInit& d) {
     CheckNumberOfArguments(d, 0);
 
-    if (!OptionType::IsList(optDesc_.Type))
+    if (!optDesc_.isList())
       llvm::errs() << "Warning: specifying the 'optional' property"
         "on a non-list option has no effect.\n";
 
@@ -734,7 +747,7 @@ private:
     if (val < 2)
       throw "Error in the 'multi_val' property: "
         "the value must be greater than 1!";
-    if (!OptionType::IsList(optDesc_.Type))
+    if (!optDesc_.isList())
       throw "The multi_val property is valid only on list options!";
     optDesc_.MultiVal = val;
   }
@@ -1855,6 +1868,8 @@ void EmitForwardOptionPropertyHandlingCode (const OptionDescription& D,
                           << D.GenVariableName() << "));\n";
     break;
   case OptionType::PrefixList:
+    // TODO: remove duplication across PrefixList / ParameterList / SwitchList
+    // branches
     O.indent(IndentLevel)
       << "for (" << D.GenTypeDeclaration()
       << "::iterator B = " << D.GenVariableName() << ".begin(),\n";
@@ -1891,6 +1906,20 @@ void EmitForwardOptionPropertyHandlingCode (const OptionDescription& D,
       O.indent(IndentLevel1) << "++B;\n";
     }
 
+    O.indent(IndentLevel) << "}\n";
+    break;
+  case OptionType::SwitchList:
+        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) << "unsigned pos = " << D.GenVariableName()
+                           << ".getPosition(B - " << D.GenVariableName()
+                           << ".begin());\n";
+    O.indent(IndentLevel1) << "vec.push_back(std::make_pair(pos, \""
+                           << Name << "\"));\n";
+    O.indent(IndentLevel1) << "++B;\n";
     O.indent(IndentLevel) << "}\n";
     break;
   case OptionType::Alias:
@@ -1999,14 +2028,20 @@ class EmitActionHandlersCallback :
     const std::string& Name = InitPtrToString(Dag.getArg(0));
     const OptionDescription& D = OptDescs.FindListOrParameter(Name);
 
+    if (D.isSwitchList()) {
+      throw std::runtime_error
+        ("forward_value is not allowed with switch_list");
+    }
+
     if (D.isParameter()) {
       O.indent(IndentLevel) << "vec.push_back(std::make_pair("
                             << D.GenVariableName() << ".getPosition(), "
                             << D.GenVariableName() << "));\n";
     }
     else {
-      O.indent(IndentLevel) << "for (cl::list<std::string>::iterator B = "
-                            << D.GenVariableName() << ".begin(), \n";
+      O.indent(IndentLevel) << "for (" << D.GenTypeDeclaration()
+                            << "::iterator B = " << D.GenVariableName()
+                            << ".begin(), \n";
       O.indent(IndentLevel + Indent1) << " E = " << D.GenVariableName()
                                       << ".end(); B != E; ++B)\n";
       O.indent(IndentLevel) << "{\n";