[llvm-commits] [llvm] r84728 - /llvm/trunk/utils/TableGen/LLVMCConfigurationEmitter.cpp

Mikhail Glushenkov foldr at codedgers.com
Tue Oct 20 19:13:14 PDT 2009


Author: foldr
Date: Tue Oct 20 21:13:13 2009
New Revision: 84728

URL: http://llvm.org/viewvc/llvm-project?rev=84728&view=rev
Log:
Implement any_[not_]empty and list versions of switch_on and [not_]empty.

Useful for OptionPreprocessor.

Modified:
    llvm/trunk/utils/TableGen/LLVMCConfigurationEmitter.cpp

Modified: llvm/trunk/utils/TableGen/LLVMCConfigurationEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/LLVMCConfigurationEmitter.cpp?rev=84728&r1=84727&r2=84728&view=diff

==============================================================================
--- llvm/trunk/utils/TableGen/LLVMCConfigurationEmitter.cpp (original)
+++ llvm/trunk/utils/TableGen/LLVMCConfigurationEmitter.cpp Tue Oct 20 21:13:13 2009
@@ -146,6 +146,18 @@
     throw ErrorString;
 }
 
+// apply is needed because C++'s syntax doesn't let us construct a function
+// object and call it in the same statement.
+template<typename F, typename T0>
+void apply(F Fun, T0& Arg0) {
+  return Fun(Arg0);
+}
+
+template<typename F, typename T0, typename T1>
+void apply(F Fun, T0& Arg0, T1& Arg1) {
+  return Fun(Arg0, Arg1);
+}
+
 //===----------------------------------------------------------------------===//
 /// Back-end specific code
 
@@ -157,6 +169,10 @@
   enum OptionType { Alias, Switch, Parameter, ParameterList,
                     Prefix, PrefixList};
 
+  bool IsAlias(OptionType t) {
+    return (t == Alias);
+  }
+
   bool IsList (OptionType t) {
     return (t == ParameterList || t == PrefixList);
   }
@@ -245,12 +261,12 @@
   bool isReallyHidden() const;
   void setReallyHidden();
 
-  bool isParameter() const
-  { return OptionType::IsParameter(this->Type); }
-
   bool isSwitch() const
   { return OptionType::IsSwitch(this->Type); }
 
+  bool isParameter() const
+  { return OptionType::IsParameter(this->Type); }
+
   bool isList() const
   { return OptionType::IsList(this->Type); }
 
@@ -272,7 +288,7 @@
 }
 
 bool OptionDescription::isAlias() const {
-  return Type == OptionType::Alias;
+  return OptionType::IsAlias(this->Type);
 }
 
 bool OptionDescription::isMultiVal() const {
@@ -365,9 +381,14 @@
 public:
   /// FindOption - exception-throwing wrapper for find().
   const OptionDescription& FindOption(const std::string& OptName) const;
-  /// FindSwitch - wrapper for FindOption that throws in case the option is not
-  /// a switch.
+
+  // Wrappers for FindOption that throw an exception in case the option has a
+  // wrong type.
   const OptionDescription& FindSwitch(const std::string& OptName) const;
+  const OptionDescription& FindParameter(const std::string& OptName) const;
+  const OptionDescription& FindList(const std::string& OptName) const;
+  const OptionDescription&
+  FindListOrParameter(const std::string& OptName) const;
 
   /// insertDescription - Insert new OptionDescription into
   /// OptionDescriptions list
@@ -380,8 +401,7 @@
 };
 
 const OptionDescription&
-OptionDescriptions::FindOption(const std::string& OptName) const
-{
+OptionDescriptions::FindOption(const std::string& OptName) const {
   const_iterator I = Descriptions.find(OptName);
   if (I != Descriptions.end())
     return I->second;
@@ -390,16 +410,39 @@
 }
 
 const OptionDescription&
-OptionDescriptions::FindSwitch(const std::string& OptName) const
-{
+OptionDescriptions::FindSwitch(const std::string& OptName) const {
   const OptionDescription& OptDesc = this->FindOption(OptName);
   if (!OptDesc.isSwitch())
     throw OptName + ": incorrect option type - should be a switch!";
   return OptDesc;
 }
 
-void OptionDescriptions::InsertDescription (const OptionDescription& o)
-{
+const OptionDescription&
+OptionDescriptions::FindList(const std::string& OptName) const {
+  const OptionDescription& OptDesc = this->FindOption(OptName);
+  if (!OptDesc.isList())
+    throw OptName + ": incorrect option type - should be a list!";
+  return OptDesc;
+}
+
+const OptionDescription&
+OptionDescriptions::FindParameter(const std::string& OptName) const {
+  const OptionDescription& OptDesc = this->FindOption(OptName);
+  if (!OptDesc.isParameter())
+    throw OptName + ": incorrect option type - should be a parameter!";
+  return OptDesc;
+}
+
+const OptionDescription&
+OptionDescriptions::FindListOrParameter(const std::string& OptName) const {
+  const OptionDescription& OptDesc = this->FindOption(OptName);
+  if (!OptDesc.isList() && !OptDesc.isParameter())
+    throw OptName
+      + ": incorrect option type - should be a list or parameter!";
+  return OptDesc;
+}
+
+void OptionDescriptions::InsertDescription (const OptionDescription& o) {
   container_type::iterator I = Descriptions.find(o.Name);
   if (I != Descriptions.end()) {
     OptionDescription& D = I->second;
@@ -1067,49 +1110,57 @@
   return false;
 }
 
-/// EmitCaseTest1ArgStr - Helper function used by EmitCaseTest1Arg();
-bool EmitCaseTest1ArgStr(const std::string& TestName,
-                         const DagInit& d,
-                         const OptionDescriptions& OptDescs,
-                         raw_ostream& O) {
-  const std::string& OptName = InitPtrToString(d.getArg(0));
+/// EmitListTest - Helper function used by EmitCaseTest1ArgList().
+template <typename F>
+void EmitListTest(const ListInit& L, const char* LogicOp,
+                  F Callback, raw_ostream& O)
+{
+  // This is a lot like EmitLogicalOperationTest, but works on ListInits instead
+  // of Dags...
+  bool isFirst = true;
+  for (ListInit::const_iterator B = L.begin(), E = L.end(); B != E; ++B) {
+    if (isFirst)
+      isFirst = false;
+    else
+      O << " || ";
+    Callback(InitPtrToString(*B), O);
+  }
+}
 
-  if (TestName == "switch_on") {
-    const OptionDescription& OptDesc = OptDescs.FindSwitch(OptName);
+// Callbacks for use with EmitListTest.
+
+class EmitSwitchOn {
+  const OptionDescriptions& OptDescs_;
+public:
+  EmitSwitchOn(const OptionDescriptions& OptDescs) : OptDescs_(OptDescs)
+  {}
+
+  void operator()(const std::string& OptName, raw_ostream& O) const {
+    const OptionDescription& OptDesc = OptDescs_.FindSwitch(OptName);
     O << OptDesc.GenVariableName();
-    return true;
-  }
-  else if (TestName == "input_languages_contain") {
-    O << "InLangs.count(\"" << OptName << "\") != 0";
-    return true;
   }
-  else if (TestName == "in_language") {
-    // This works only for single-argument Tool::GenerateAction. Join
-    // tools can process several files in different languages simultaneously.
+};
 
-    // TODO: make this work with Edge::Weight (if possible).
-    O << "LangMap.GetLanguage(inFile) == \"" << OptName << '\"';
-    return true;
-  }
-  else if (TestName == "not_empty" || TestName == "empty") {
-    const char* Test = (TestName == "empty") ? "" : "!";
+class EmitEmptyTest {
+  bool EmitNegate_;
+  const OptionDescriptions& OptDescs_;
+public:
+  EmitEmptyTest(bool EmitNegate, const OptionDescriptions& OptDescs)
+    : EmitNegate_(EmitNegate), OptDescs_(OptDescs)
+  {}
 
+  void operator()(const std::string& OptName, raw_ostream& O) const {
+    const char* Neg = (EmitNegate_ ? "!" : "");
     if (OptName == "o") {
-      O << Test << "OutputFilename.empty()";
-      return true;
+      O << Neg << "OutputFilename.empty()";
     }
     else {
-      const OptionDescription& OptDesc = OptDescs.FindOption(OptName);
-      if (OptDesc.isSwitch())
-        throw OptName
-          + ": incorrect option type - should be a list or parameter!";
-      O << Test << OptDesc.GenVariableName() << ".empty()";
-      return true;
+      const OptionDescription& OptDesc = OptDescs_.FindListOrParameter(OptName);
+      O << Neg << OptDesc.GenVariableName() << ".empty()";
     }
   }
+};
 
-  return false;
-}
 
 /// EmitCaseTest1ArgList - Helper function used by EmitCaseTest1Arg();
 bool EmitCaseTest1ArgList(const std::string& TestName,
@@ -1119,23 +1170,61 @@
   const ListInit& L = *static_cast<ListInit*>(d.getArg(0));
 
   if (TestName == "any_switch_on") {
-    bool isFirst = true;
+    EmitListTest(L, "||", EmitSwitchOn(OptDescs), O);
+    return true;
+  }
+  else if (TestName == "switch_on") {
+    EmitListTest(L, "&&", EmitSwitchOn(OptDescs), O);
+    return true;
+  }
+  else if (TestName == "any_not_empty") {
+    EmitListTest(L, "||", EmitEmptyTest(true, OptDescs), O);
+    return true;
+  }
+  else if (TestName == "any_empty") {
+    EmitListTest(L, "||", EmitEmptyTest(false, OptDescs), O);
+    return true;
+  }
+  else if (TestName == "not_empty") {
+    EmitListTest(L, "&&", EmitEmptyTest(true, OptDescs), O);
+    return true;
+  }
+  else if (TestName == "empty") {
+    EmitListTest(L, "&&", EmitEmptyTest(false, OptDescs), O);
+    return true;
+  }
 
-    for (ListInit::const_iterator B = L.begin(), E = L.end(); B != E; ++B) {
-      const std::string& OptName = InitPtrToString(*B);
-      const OptionDescription& OptDesc = OptDescs.FindSwitch(OptName);
+  return false;
+}
 
-      if (isFirst)
-        isFirst = false;
-      else
-        O << " || ";
-      O << OptDesc.GenVariableName();
-    }
+/// EmitCaseTest1ArgStr - Helper function used by EmitCaseTest1Arg();
+bool EmitCaseTest1ArgStr(const std::string& TestName,
+                         const DagInit& d,
+                         const OptionDescriptions& OptDescs,
+                         raw_ostream& O) {
+  const std::string& OptName = InitPtrToString(d.getArg(0));
 
+  if (TestName == "switch_on") {
+    apply(EmitSwitchOn(OptDescs), OptName, O);
+    return true;
+  }
+  else if (TestName == "input_languages_contain") {
+    O << "InLangs.count(\"" << OptName << "\") != 0";
     return true;
   }
+  else if (TestName == "in_language") {
+    // This works only for single-argument Tool::GenerateAction. Join
+    // tools can process several files in different languages simultaneously.
 
-  // TODO: implement any_not_empty, any_empty, switch_on [..], empty [..]
+    // TODO: make this work with Edge::Weight (if possible).
+    O << "LangMap.GetLanguage(inFile) == \"" << OptName << '\"';
+    return true;
+  }
+  else if (TestName == "not_empty" || TestName == "empty") {
+    bool EmitNegate = (TestName == "not_empty");
+    apply(EmitEmptyTest(EmitNegate, OptDescs), OptName, O);
+    return true;
+  }
 
   return false;
 }
@@ -1161,17 +1250,14 @@
   checkNumberOfArguments(&d, 2);
   const std::string& OptName = InitPtrToString(d.getArg(0));
   const std::string& OptArg = InitPtrToString(d.getArg(1));
-  const OptionDescription& OptDesc = OptDescs.FindOption(OptName);
 
   if (TestName == "parameter_equals") {
-    if (!OptDesc.isParameter())
-      throw OptName + ": incorrect option type - should be a parameter!";
+    const OptionDescription& OptDesc = OptDescs.FindParameter(OptName);
     O << OptDesc.GenVariableName() << " == \"" << OptArg << "\"";
     return true;
   }
   else if (TestName == "element_in_list") {
-    if (!OptDesc.isList())
-      throw OptName + ": incorrect option type - should be a list!";
+    const OptionDescription& OptDesc = OptDescs.FindList(OptName);
     const std::string& VarName = OptDesc.GenVariableName();
     O << "std::find(" << VarName << ".begin(),\n";
     O.indent(IndentLevel + Indent1)





More information about the llvm-commits mailing list