mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-09 13:33:17 +00:00
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
This commit is contained in:
parent
61435195ce
commit
e5557f4da4
@ -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;
|
||||
|
@ -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))>
|
||||
]>;
|
||||
|
@ -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) $< $@
|
||||
|
||||
|
@ -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();
|
||||
/// 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 (PropName == "and")
|
||||
EmitLogicalOperationTest(Prop, "&&", OptDescs, O);
|
||||
else if (PropName == "or")
|
||||
EmitLogicalOperationTest(Prop, "||", OptDescs, O);
|
||||
else if (EmitEdgePropertyTest1Arg(PropName, Prop, OptDescs, O))
|
||||
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 << "()";
|
||||
|
Loading…
x
Reference in New Issue
Block a user