summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMikhail Glushenkov <foldr@codedgers.com>2008-05-30 06:08:50 +0000
committerMikhail Glushenkov <foldr@codedgers.com>2008-05-30 06:08:50 +0000
commite5557f4da417388d54c102ad7dd046237487bce3 (patch)
tree5de78ed8167e5dc7fbdd0b2875ec95bf95a1ff2d
parent61435195cecae519e1539747540a6563ed23b678 (diff)
downloadllvm-e5557f4da417388d54c102ad7dd046237487bce3.tar.gz
llvm-e5557f4da417388d54c102ad7dd046237487bce3.tar.bz2
llvm-e5557f4da417388d54c102ad7dd046237487bce3.tar.xz
Add a generalised 'case' construct.
Besides assigning edge weights, it will also be used by the cmd_line tool property. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@51727 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--tools/llvmc2/Common.td27
-rw-r--r--tools/llvmc2/Graph.td20
-rw-r--r--tools/llvmc2/Makefile10
-rw-r--r--utils/TableGen/LLVMCConfigurationEmitter.cpp178
4 files changed, 139 insertions, 96 deletions
diff --git a/tools/llvmc2/Common.td b/tools/llvmc2/Common.td
index b04596fb76..2a6b54eba8 100644
--- a/tools/llvmc2/Common.td
+++ b/tools/llvmc2/Common.td
@@ -45,19 +45,26 @@ def unpack_values;
def help;
def required;
-// Possible edge properties
+// Marker for an empty DAG.
+def empty;
-// 'Atomic' properties.
+// The 'case' construct.
+def case;
+
+// Primitive tests.
def switch_on;
def parameter_equals;
def element_in_list;
-def if_input_languages_contain;
+def input_languages_contain;
-// Edge property combinators.
-def weight;
+// Boolean operators.
def and;
def or;
+// Increase/decrease the edge weight.
+def inc_weight;
+def dec_weight;
+
// Map from suffixes to language names
class LangToSuffixes<string str, list<string> lst> {
@@ -71,19 +78,19 @@ class LanguageMap<list<LangToSuffixes> lst> {
// Compilation graph
-class EdgeBase<Tool t1, Tool t2, list<dag> lst> {
+class EdgeBase<Tool t1, Tool t2, dag d> {
Tool a = t1;
Tool b = t2;
- list<dag> props = lst;
+ dag weight = d;
}
-class Edge<Tool t1, Tool t2> : EdgeBase<t1, t2, []>;
+class Edge<Tool t1, Tool t2> : EdgeBase<t1, t2, (empty)>;
// Edge and SimpleEdge are synonyms.
-class SimpleEdge<Tool t1, Tool t2> : EdgeBase<t1, t2, []>;
+class SimpleEdge<Tool t1, Tool t2> : EdgeBase<t1, t2, (empty)>;
// Optionally enabled edge.
-class OptionalEdge<Tool t1, Tool t2, list<dag> lst> : EdgeBase<t1, t2, lst>;
+class OptionalEdge<Tool t1, Tool t2, dag props> : EdgeBase<t1, t2, props>;
class CompilationGraph<list<EdgeBase> lst> {
list<EdgeBase> edges = lst;
diff --git a/tools/llvmc2/Graph.td b/tools/llvmc2/Graph.td
index 6fb998b28b..5c2902e288 100644
--- a/tools/llvmc2/Graph.td
+++ b/tools/llvmc2/Graph.td
@@ -26,22 +26,24 @@ def CompilationGraph : CompilationGraph<[
Edge<llvm_gcc_cpp, llc>,
Edge<llvm_as, llc>,
- OptionalEdge<llvm_gcc_c, opt, [(switch_on "opt")]>,
- OptionalEdge<llvm_gcc_cpp, opt, [(switch_on "opt")]>,
- OptionalEdge<llvm_as, opt, [(switch_on "opt")]>,
+ OptionalEdge<llvm_gcc_c, opt, (case (switch_on "opt"), (inc_weight))>,
+ OptionalEdge<llvm_gcc_cpp, opt, (case (switch_on "opt"), (inc_weight))>,
+ OptionalEdge<llvm_as, opt, (case (switch_on "opt"), (inc_weight))>,
Edge<opt, llc>,
Edge<llc, llvm_gcc_assembler>,
Edge<llvm_gcc_assembler, llvm_gcc_linker>,
OptionalEdge<llvm_gcc_assembler, llvm_gcc_cpp_linker,
- [(if_input_languages_contain "c++"),
- (or (parameter_equals "linker", "g++"),
- (parameter_equals "linker", "c++"))]>,
+ (case
+ (input_languages_contain "c++"), (inc_weight),
+ (or (parameter_equals "linker", "g++"),
+ (parameter_equals "linker", "c++")), (inc_weight))>,
Edge<root, llvm_gcc_linker>,
OptionalEdge<root, llvm_gcc_cpp_linker,
- [(if_input_languages_contain "c++"),
- (or (parameter_equals "linker", "g++"),
- (parameter_equals "linker", "c++"))]>
+ (case
+ (input_languages_contain "c++"), (inc_weight),
+ (or (parameter_equals "linker", "g++"),
+ (parameter_equals "linker", "c++")), (inc_weight))>
]>;
diff --git a/tools/llvmc2/Makefile b/tools/llvmc2/Makefile
index 0c4782b6e9..04cd954e53 100644
--- a/tools/llvmc2/Makefile
+++ b/tools/llvmc2/Makefile
@@ -14,15 +14,15 @@ REQUIRES_EH := 1
include $(LEVEL)/Makefile.common
-GRAPH = Graph.td
-TOOLS_SOURCE=$(GRAPH) Tools.td Common.td
+GRAPH=Graph.td
+TOOLS=Tools.td
+TOOLS_SOURCE=$(GRAPH) $(TOOLS) Common.td
# TOFIX: integrate this part into Makefile.rules?
# The degree of horrorshowness in that file is too much for me atm.
-$(ObjDir)/AutoGenerated.inc.tmp: $(TOOLS_SOURCE) $(ObjDir)/.dir
- $(Echo) "Building LLVMCC configuration library with tblgen"
+$(ObjDir)/AutoGenerated.inc.tmp: $(TOOLS_SOURCE) $(ObjDir)/.dir $(TBLGEN)
+ $(Echo) "Building LLVMC configuration library with tblgen"
$(Verb) $(TableGen) -gen-llvmc -o $(call SYSPATH, $@) $<
AutoGenerated.inc : $(ObjDir)/AutoGenerated.inc.tmp
$(Verb) $(CMP) -s $@ $< || $(CP) $< $@
-
diff --git a/utils/TableGen/LLVMCConfigurationEmitter.cpp b/utils/TableGen/LLVMCConfigurationEmitter.cpp
index 8e4d870f76..122424428e 100644
--- a/utils/TableGen/LLVMCConfigurationEmitter.cpp
+++ b/utils/TableGen/LLVMCConfigurationEmitter.cpp
@@ -68,15 +68,18 @@ const DagInit& InitPtrToDagInitRef(Init* ptr) {
return val;
}
-
// checkNumberOfArguments - Ensure that the number of args in d is
-// less than or equal to min_arguments, otherwise throw an exception .
+// less than or equal to min_arguments, otherwise throw an exception.
void checkNumberOfArguments (const DagInit* d, unsigned min_arguments) {
if (d->getNumArgs() < min_arguments)
throw "Property " + d->getOperator()->getAsString()
+ " has too few arguments!";
}
+// isDagEmpty - is this DAG marked with an empty marker?
+bool isDagEmpty (const DagInit* d) {
+ return d->getOperator()->getAsString() == "empty";
+}
//===----------------------------------------------------------------------===//
/// Back-end specific code
@@ -974,21 +977,21 @@ void TypecheckGraph (Record* CompilationGraph,
}
}
-/// EmitEdgePropertyTest1Arg - Helper function used by
-/// EmitEdgePropertyTest.
-bool EmitEdgePropertyTest1Arg(const std::string& PropName,
- const DagInit& Prop,
- const GlobalOptionDescriptions& OptDescs,
- std::ostream& O) {
- checkNumberOfArguments(&Prop, 1);
- const std::string& OptName = InitPtrToString(Prop.getArg(0));
- if (PropName == "switch_on") {
+/// EmitCaseTest1Arg - Helper function used by
+/// EmitCaseConstructHandler.
+bool EmitCaseTest1Arg(const std::string& TestName,
+ const DagInit& d,
+ const GlobalOptionDescriptions& OptDescs,
+ std::ostream& O) {
+ checkNumberOfArguments(&d, 1);
+ const std::string& OptName = InitPtrToString(d.getArg(0));
+ if (TestName == "switch_on") {
const GlobalOptionDescription& OptDesc = OptDescs.FindOption(OptName);
if (OptDesc.Type != OptionType::Switch)
throw OptName + ": incorrect option type!";
O << OptDesc.GenVariableName();
return true;
- } else if (PropName == "if_input_languages_contain") {
+ } else if (TestName == "input_languages_contain") {
O << "InLangs.count(\"" << OptName << "\") != 0";
return true;
}
@@ -996,31 +999,32 @@ bool EmitEdgePropertyTest1Arg(const std::string& PropName,
return false;
}
-/// EmitEdgePropertyTest2Args - Helper function used by
-/// EmitEdgePropertyTest.
-bool EmitEdgePropertyTest2Args(const std::string& PropName,
- const DagInit& Prop,
- const GlobalOptionDescriptions& OptDescs,
- std::ostream& O) {
- checkNumberOfArguments(&Prop, 2);
- const std::string& OptName = InitPtrToString(Prop.getArg(0));
- const std::string& OptArg = InitPtrToString(Prop.getArg(1));
+/// EmitCaseTest2Args - Helper function used by
+/// EmitCaseConstructHandler.
+bool EmitCaseTest2Args(const std::string& TestName,
+ const DagInit& d,
+ const char* IndentLevel,
+ const GlobalOptionDescriptions& OptDescs,
+ std::ostream& O) {
+ checkNumberOfArguments(&d, 2);
+ const std::string& OptName = InitPtrToString(d.getArg(0));
+ const std::string& OptArg = InitPtrToString(d.getArg(1));
const GlobalOptionDescription& OptDesc = OptDescs.FindOption(OptName);
- if (PropName == "parameter_equals") {
+ if (TestName == "parameter_equals") {
if (OptDesc.Type != OptionType::Parameter
&& OptDesc.Type != OptionType::Prefix)
throw OptName + ": incorrect option type!";
O << OptDesc.GenVariableName() << " == \"" << OptArg << "\"";
return true;
}
- else if (PropName == "element_in_list") {
+ else if (TestName == "element_in_list") {
if (OptDesc.Type != OptionType::ParameterList
&& OptDesc.Type != OptionType::PrefixList)
throw OptName + ": incorrect option type!";
const std::string& VarName = OptDesc.GenVariableName();
O << "std::find(" << VarName << ".begin(),\n"
- << Indent3 << VarName << ".end(), \""
+ << IndentLevel << Indent1 << VarName << ".end(), \""
<< OptArg << "\") != " << VarName << ".end()";
return true;
}
@@ -1029,47 +1033,95 @@ bool EmitEdgePropertyTest2Args(const std::string& PropName,
}
// Forward declaration.
-void EmitEdgePropertyTest(const DagInit& Prop,
- const GlobalOptionDescriptions& OptDescs,
- std::ostream& O);
+// EmitLogicalOperationTest and EmitCaseTest are mutually recursive.
+void EmitCaseTest(const DagInit& d, const char* IndentLevel,
+ const GlobalOptionDescriptions& OptDescs,
+ std::ostream& O);
/// EmitLogicalOperationTest - Helper function used by
-/// EmitEdgePropertyTest.
-void EmitLogicalOperationTest(const DagInit& Prop, const char* LogicOp,
+/// EmitCaseConstructHandler.
+void EmitLogicalOperationTest(const DagInit& d, const char* LogicOp,
+ const char* IndentLevel,
const GlobalOptionDescriptions& OptDescs,
std::ostream& O) {
O << '(';
- for (unsigned j = 0, NumArgs = Prop.getNumArgs(); j < NumArgs; ++j) {
- const DagInit& InnerProp = InitPtrToDagInitRef(Prop.getArg(j));
- EmitEdgePropertyTest(InnerProp, OptDescs, O);
+ for (unsigned j = 0, NumArgs = d.getNumArgs(); j < NumArgs; ++j) {
+ const DagInit& InnerTest = InitPtrToDagInitRef(d.getArg(j));
+ EmitCaseTest(InnerTest, IndentLevel, OptDescs, O);
if (j != NumArgs - 1)
- O << ")\n" << Indent3 << ' ' << LogicOp << " (";
+ O << ")\n" << IndentLevel << Indent1 << ' ' << LogicOp << " (";
else
O << ')';
}
}
-/// EmitEdgePropertyTest - Helper function used by EmitEdgeClass.
-void EmitEdgePropertyTest(const DagInit& Prop,
- const GlobalOptionDescriptions& OptDescs,
- std::ostream& O) {
- const std::string& PropName = Prop.getOperator()->getAsString();
-
- if (PropName == "and")
- EmitLogicalOperationTest(Prop, "&&", OptDescs, O);
- else if (PropName == "or")
- EmitLogicalOperationTest(Prop, "||", OptDescs, O);
- else if (EmitEdgePropertyTest1Arg(PropName, Prop, OptDescs, O))
+/// EmitCaseTest - Helper function used by EmitCaseConstructHandler.
+void EmitCaseTest(const DagInit& d, const char* IndentLevel,
+ const GlobalOptionDescriptions& OptDescs,
+ std::ostream& O) {
+ const std::string& TestName = d.getOperator()->getAsString();
+
+ if (TestName == "and")
+ EmitLogicalOperationTest(d, "&&", IndentLevel, OptDescs, O);
+ else if (TestName == "or")
+ EmitLogicalOperationTest(d, "||", IndentLevel, OptDescs, O);
+ else if (EmitCaseTest1Arg(TestName, d, OptDescs, O))
return;
- else if (EmitEdgePropertyTest2Args(PropName, Prop, OptDescs, O))
+ else if (EmitCaseTest2Args(TestName, d, IndentLevel, OptDescs, O))
return;
else
- throw PropName + ": unknown edge property!";
+ throw TestName + ": unknown edge property!";
+}
+
+// Emit code that handles the 'case' construct.
+// Takes a function object that should emit code for every case clause.
+template <typename F>
+void EmitCaseConstructHandler(DagInit* d, const char* IndentLevel,
+ const F& Callback,
+ const GlobalOptionDescriptions& OptDescs,
+ std::ostream& O) {
+ assert(d->getOperator()->getAsString() == "case");
+
+ for (DagInit::arg_iterator B = d->arg_begin(), E = d->arg_end();
+ B != E; ++B) {
+ const DagInit& Test = InitPtrToDagInitRef(*B);
+ O << IndentLevel << "if (";
+ EmitCaseTest(Test, IndentLevel, OptDescs, O);
+ O << ") {\n";
+
+ ++B;
+ if (B == E)
+ throw "Case construct handler: no corresponding action "
+ "found for the test " + Test.getAsString() + '!';
+
+ const DagInit& Action = InitPtrToDagInitRef(*B);
+ Callback(IndentLevel, Action, O);
+ O << IndentLevel << "}\n";
+ }
+}
+
+// Helper function passed to EmitCaseConstructHandler by EmitEdgeClass.
+void IncDecWeight(const char* IndentLevel,
+ const DagInit& d, std::ostream& O) {
+ const std::string& OpName = d.getOperator()->getAsString();
+
+ if (OpName == "inc_weight")
+ O << IndentLevel << Indent1 << "ret += ";
+ else if (OpName == "dec_weight")
+ O << IndentLevel << Indent1 << "ret -= ";
+ else
+ throw "Unknown operator in edge properties list: " + OpName + '!';
+
+ if (d.getNumArgs() > 0)
+ O << InitPtrToInt(d.getArg(0)) << ";\n";
+ else
+ O << "2;\n";
+
}
/// EmitEdgeClass - Emit a single Edge# class.
void EmitEdgeClass(unsigned N, const std::string& Target,
- ListInit* Props, const GlobalOptionDescriptions& OptDescs,
+ DagInit* Case, const GlobalOptionDescriptions& OptDescs,
std::ostream& O) {
// Class constructor.
@@ -1082,26 +1134,8 @@ void EmitEdgeClass(unsigned N, const std::string& Target,
<< Indent1 << "unsigned Weight(const InputLanguagesSet& InLangs) const {\n"
<< Indent2 << "unsigned ret = 0;\n";
- // Emit tests for every edge property.
- for (size_t i = 0, PropsSize = Props->size(); i < PropsSize; ++i) {
- const DagInit& Prop = InitPtrToDagInitRef(Props->getElement(i));
- const std::string& PropName = Prop.getOperator()->getAsString();
- unsigned N = 2;
-
- O << Indent2 << "if (";
-
- if (PropName == "weight") {
- checkNumberOfArguments(&Prop, 2);
- N = InitPtrToInt(Prop.getArg(0));
- const DagInit& InnerProp = InitPtrToDagInitRef(Prop.getArg(1));
- EmitEdgePropertyTest(InnerProp, OptDescs, O);
- }
- else {
- EmitEdgePropertyTest(Prop, OptDescs, O);
- }
-
- O << ")\n" << Indent3 << "ret += " << N << ";\n";
- }
+ // Handle the 'case' construct.
+ EmitCaseConstructHandler(Case, Indent2, IncDecWeight, OptDescs, O);
O << Indent2 << "return ret;\n"
<< Indent1 << "};\n\n};\n\n";
@@ -1116,12 +1150,12 @@ void EmitEdgeClasses (Record* CompilationGraph,
for (unsigned i = 0; i < edges->size(); ++i) {
Record* Edge = edges->getElementAsRecord(i);
Record* B = Edge->getValueAsDef("b");
- ListInit* Props = Edge->getValueAsListInit("props");
+ DagInit* Weight = Edge->getValueAsDag("weight");
- if (Props->empty())
+ if (isDagEmpty(Weight))
continue;
- EmitEdgeClass(i, B->getName(), Props, OptDescs, O);
+ EmitEdgeClass(i, B->getName(), Weight, OptDescs, O);
}
}
@@ -1156,11 +1190,11 @@ void EmitPopulateCompilationGraph (Record* CompilationGraph,
Record* Edge = edges->getElementAsRecord(i);
Record* A = Edge->getValueAsDef("a");
Record* B = Edge->getValueAsDef("b");
- ListInit* Props = Edge->getValueAsListInit("props");
+ DagInit* Weight = Edge->getValueAsDag("weight");
O << Indent1 << "G.insertEdge(\"" << A->getName() << "\", ";
- if (Props->empty())
+ if (isDagEmpty(Weight))
O << "new SimpleEdge(\"" << B->getName() << "\")";
else
O << "new Edge" << i << "()";