Add new edge property combinator: weight.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@50765 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Mikhail Glushenkov 2008-05-06 18:18:20 +00:00
parent 6a6cd729aa
commit 29063554d0
3 changed files with 100 additions and 60 deletions

View File

@ -53,6 +53,7 @@ def element_in_list;
def if_input_languages_contain; def if_input_languages_contain;
// Edge property combinators. // Edge property combinators.
def weight;
def and; def and;
def or; def or;
@ -77,8 +78,8 @@ class EdgeBase<Tool t1, Tool t2, list<dag> lst> {
class Edge<Tool t1, Tool t2> : EdgeBase<t1, t2, []>; class Edge<Tool t1, Tool t2> : EdgeBase<t1, t2, []>;
// Edge and DefaultEdge are synonyms. // Edge and SimpleEdge are synonyms.
class DefaultEdge<Tool t1, Tool t2> : EdgeBase<t1, t2, []>; class SimpleEdge<Tool t1, Tool t2> : EdgeBase<t1, t2, []>;
// Optionally enabled edge. // Optionally enabled edge.
class OptionalEdge<Tool t1, Tool t2, list<dag> lst> : EdgeBase<t1, t2, lst>; class OptionalEdge<Tool t1, Tool t2, list<dag> lst> : EdgeBase<t1, t2, lst>;

View File

@ -120,11 +120,20 @@ specify one default edge *per language*).
language belongs to the current input language set. language belongs to the current input language set.
- ``and`` - Edge property combinator. Returns true if all of its - ``and`` - Edge property combinator. Returns true if all of its
arguments return true. Used like this: (and arguments return true. Used like this: ``(and (prop1), (prop2),
(prop1), (prop2), ... (propN)). Nesting not allowed. ... (propN))``. Nesting is allowed, but not encouraged.
- ``or`` - Edge property combinator that returns true if any one of its - ``or`` - Edge property combinator that returns true if any one of its
arguments returns true. Example: (or (prop1), (prop2), ... (propN)) arguments returns true. Example: ``(or (prop1), (prop2), ... (propN))``.
- ``weight`` - Makes it possible to explicitly specify the quantity
added to the edge weight if this edge property matches. Used like
this: ``(weight N, (prop))``. The inner property can include
``and`` and ``or`` combinators. When N is equal to 2, equivalent
to ``(prop)``.
Example: ``(weight 8, (and (switch_on "a"), (switch_on "b")))``.
To get a visual representation of the compilation graph (useful for To get a visual representation of the compilation graph (useful for
debugging), run ``llvmc2 --view-graph``. You will need ``dot`` and debugging), run ``llvmc2 --view-graph``. You will need ``dot`` and

View File

@ -58,6 +58,17 @@ std::string InitPtrToString(Init* ptr) {
return val.getValue(); return val.getValue();
} }
int InitPtrToInt(Init* ptr) {
IntInit& val = dynamic_cast<IntInit&>(*ptr);
return val.getValue();
}
const DagInit& InitPtrToDagInitRef(Init* ptr) {
DagInit& val = dynamic_cast<DagInit&>(*ptr);
return val;
}
// Ensure that the number of args in d is <= min_arguments, // Ensure that the number of args in d is <= min_arguments,
// throw exception otherwise // throw exception otherwise
void checkNumberOfArguments (const DagInit* d, unsigned min_arguments) { void checkNumberOfArguments (const DagInit* d, unsigned min_arguments) {
@ -310,15 +321,15 @@ private:
// "Property handler" - a function that extracts information // "Property handler" - a function that extracts information
// about a given tool property from its DAG representation // about a given tool property from its DAG representation
typedef void (CollectProperties::*PropertyHandler)(DagInit*); typedef void (CollectProperties::*PropertyHandler)(const DagInit*);
// Map from property names -> property handlers // Map from property names -> property handlers
typedef StringMap<PropertyHandler> PropertyHandlerMap; typedef StringMap<PropertyHandler> PropertyHandlerMap;
// "Option property handler" - a function that extracts information // "Option property handler" - a function that extracts information
// about a given option property from its DAG representation // about a given option property from its DAG representation
typedef void (CollectProperties::* typedef void (CollectProperties::* OptionPropertyHandler)
OptionPropertyHandler)(DagInit*, GlobalOptionDescription &); (const DagInit*, GlobalOptionDescription &);
// Map from option property names -> option property handlers // Map from option property names -> option property handlers
typedef StringMap<OptionPropertyHandler> OptionPropertyHandlerMap; typedef StringMap<OptionPropertyHandler> OptionPropertyHandlerMap;
@ -375,7 +386,7 @@ public:
// Gets called for every tool property; // Gets called for every tool property;
// Just forwards to the corresponding property handler. // Just forwards to the corresponding property handler.
void operator() (Init* i) { void operator() (Init* i) {
DagInit& d = dynamic_cast<DagInit&>(*i); const DagInit& d = InitPtrToDagInitRef(i);
const std::string& property_name = d.getOperator()->getAsString(); const std::string& property_name = d.getOperator()->getAsString();
PropertyHandlerMap::iterator method PropertyHandlerMap::iterator method
= propertyHandlers_.find(property_name); = propertyHandlers_.find(property_name);
@ -395,81 +406,95 @@ private:
/// Functions that extract information about tool properties from /// Functions that extract information about tool properties from
/// DAG representation. /// DAG representation.
void onCmdLine (DagInit* d) { void onCmdLine (const DagInit* d) {
checkNumberOfArguments(d, 1); checkNumberOfArguments(d, 1);
SplitString(InitPtrToString(d->getArg(0)), toolProps_.CmdLine); SplitString(InitPtrToString(d->getArg(0)), toolProps_.CmdLine);
if (toolProps_.CmdLine.empty()) if (toolProps_.CmdLine.empty())
throw "Tool " + toolProps_.Name + " has empty command line!"; throw "Tool " + toolProps_.Name + " has empty command line!";
} }
void onInLanguage (DagInit* d) { void onInLanguage (const DagInit* d) {
checkNumberOfArguments(d, 1); checkNumberOfArguments(d, 1);
toolProps_.InLanguage = InitPtrToString(d->getArg(0)); toolProps_.InLanguage = InitPtrToString(d->getArg(0));
} }
void onJoin (DagInit* d) { void onJoin (const DagInit* d) {
checkNumberOfArguments(d, 0); checkNumberOfArguments(d, 0);
toolProps_.setJoin(); toolProps_.setJoin();
} }
void onOutLanguage (DagInit* d) { void onOutLanguage (const DagInit* d) {
checkNumberOfArguments(d, 1); checkNumberOfArguments(d, 1);
toolProps_.OutLanguage = InitPtrToString(d->getArg(0)); toolProps_.OutLanguage = InitPtrToString(d->getArg(0));
} }
void onOutputSuffix (DagInit* d) { void onOutputSuffix (const DagInit* d) {
checkNumberOfArguments(d, 1); checkNumberOfArguments(d, 1);
toolProps_.OutputSuffix = InitPtrToString(d->getArg(0)); toolProps_.OutputSuffix = InitPtrToString(d->getArg(0));
} }
void onSink (DagInit* d) { void onSink (const DagInit* d) {
checkNumberOfArguments(d, 0); checkNumberOfArguments(d, 0);
optDescs_.HasSink = true; optDescs_.HasSink = true;
toolProps_.setSink(); toolProps_.setSink();
} }
void onSwitch (DagInit* d) { addOption(d, OptionType::Switch); } void onSwitch (const DagInit* d) {
void onParameter (DagInit* d) { addOption(d, OptionType::Parameter); } addOption(d, OptionType::Switch);
void onParameterList (DagInit* d) { addOption(d, OptionType::ParameterList); } }
void onPrefix (DagInit* d) { addOption(d, OptionType::Prefix); }
void onPrefixList (DagInit* d) { addOption(d, OptionType::PrefixList); } void onParameter (const DagInit* d) {
addOption(d, OptionType::Parameter);
}
void onParameterList (const DagInit* d) {
addOption(d, OptionType::ParameterList);
}
void onPrefix (const DagInit* d) {
addOption(d, OptionType::Prefix);
}
void onPrefixList (const DagInit* d) {
addOption(d, OptionType::PrefixList);
}
/// Option property handlers -- /// Option property handlers --
/// Methods that handle properties that are common for all types of /// Methods that handle properties that are common for all types of
/// options (like append_cmd, stop_compilation) /// options (like append_cmd, stop_compilation)
void onAppendCmd (DagInit* d, GlobalOptionDescription& o) { void onAppendCmd (const DagInit* d, GlobalOptionDescription& o) {
checkNumberOfArguments(d, 1); checkNumberOfArguments(d, 1);
std::string const& cmd = InitPtrToString(d->getArg(0)); std::string const& cmd = InitPtrToString(d->getArg(0));
toolProps_.OptDescs[o.Name].AddProperty(OptionPropertyType::AppendCmd, cmd); toolProps_.OptDescs[o.Name].AddProperty(OptionPropertyType::AppendCmd, cmd);
} }
void onForward (DagInit* d, GlobalOptionDescription& o) { void onForward (const DagInit* d, GlobalOptionDescription& o) {
checkNumberOfArguments(d, 0); checkNumberOfArguments(d, 0);
toolProps_.OptDescs[o.Name].setForward(); toolProps_.OptDescs[o.Name].setForward();
} }
void onHelp (DagInit* d, GlobalOptionDescription& o) { void onHelp (const DagInit* d, GlobalOptionDescription& o) {
checkNumberOfArguments(d, 1); checkNumberOfArguments(d, 1);
const std::string& help_message = InitPtrToString(d->getArg(0)); const std::string& help_message = InitPtrToString(d->getArg(0));
o.Help = help_message; o.Help = help_message;
} }
void onRequired (DagInit* d, GlobalOptionDescription& o) { void onRequired (const DagInit* d, GlobalOptionDescription& o) {
checkNumberOfArguments(d, 0); checkNumberOfArguments(d, 0);
o.setRequired(); o.setRequired();
} }
void onStopCompilation (DagInit* d, GlobalOptionDescription& o) { void onStopCompilation (const DagInit* d, GlobalOptionDescription& o) {
checkNumberOfArguments(d, 0); checkNumberOfArguments(d, 0);
if (o.Type != OptionType::Switch) if (o.Type != OptionType::Switch)
throw std::string("Only options of type Switch can stop compilation!"); throw std::string("Only options of type Switch can stop compilation!");
toolProps_.OptDescs[o.Name].setStopCompilation(); toolProps_.OptDescs[o.Name].setStopCompilation();
} }
void onUnpackValues (DagInit* d, GlobalOptionDescription& o) { void onUnpackValues (const DagInit* d, GlobalOptionDescription& o) {
checkNumberOfArguments(d, 0); checkNumberOfArguments(d, 0);
toolProps_.OptDescs[o.Name].setUnpackValues(); toolProps_.OptDescs[o.Name].setUnpackValues();
} }
@ -477,7 +502,7 @@ private:
/// Helper functions /// Helper functions
// Add an option of type t // Add an option of type t
void addOption (DagInit* d, OptionType::OptionType t) { void addOption (const DagInit* d, OptionType::OptionType t) {
checkNumberOfArguments(d, 2); checkNumberOfArguments(d, 2);
const std::string& name = InitPtrToString(d->getArg(0)); const std::string& name = InitPtrToString(d->getArg(0));
@ -506,13 +531,13 @@ private:
// Parameters: // Parameters:
// name - option name // name - option name
// d - option property list // d - option property list
void processOptionProperties (DagInit* d, GlobalOptionDescription& o) { void processOptionProperties (const DagInit* d, GlobalOptionDescription& o) {
// First argument is option name // First argument is option name
checkNumberOfArguments(d, 2); checkNumberOfArguments(d, 2);
for (unsigned B = 1, E = d->getNumArgs(); B!=E; ++B) { for (unsigned B = 1, E = d->getNumArgs(); B!=E; ++B) {
DagInit& option_property const DagInit& option_property
= dynamic_cast<DagInit&>(*d->getArg(B)); = InitPtrToDagInitRef(d->getArg(B));
const std::string& option_property_name const std::string& option_property_name
= option_property.getOperator()->getAsString(); = option_property.getOperator()->getAsString();
OptionPropertyHandlerMap::iterator method OptionPropertyHandlerMap::iterator method
@ -963,18 +988,10 @@ bool EmitEdgePropertyTest2Args(const std::string& PropName,
return false; return false;
} }
// Helper function used by EmitEdgeClass. // Forward declaration.
void EmitEdgePropertyTest(const std::string& PropName, void EmitEdgePropertyTest(const DagInit& Prop,
const DagInit& Prop,
const GlobalOptionDescriptions& OptDescs, const GlobalOptionDescriptions& OptDescs,
std::ostream& O) { std::ostream& O);
if (EmitEdgePropertyTest1Arg(PropName, Prop, OptDescs, O))
return;
else if (EmitEdgePropertyTest2Args(PropName, Prop, OptDescs, O))
return;
else
throw PropName + ": unknown edge property!";
}
// Helper function used by EmitEdgeClass. // Helper function used by EmitEdgeClass.
void EmitLogicalOperationTest(const DagInit& Prop, const char* LogicOp, void EmitLogicalOperationTest(const DagInit& Prop, const char* LogicOp,
@ -982,10 +999,8 @@ void EmitLogicalOperationTest(const DagInit& Prop, const char* LogicOp,
std::ostream& O) { std::ostream& O) {
O << '('; O << '(';
for (unsigned j = 0, NumArgs = Prop.getNumArgs(); j < NumArgs; ++j) { for (unsigned j = 0, NumArgs = Prop.getNumArgs(); j < NumArgs; ++j) {
const DagInit& InnerProp = dynamic_cast<DagInit&>(*Prop.getArg(j)); const DagInit& InnerProp = InitPtrToDagInitRef(Prop.getArg(j));
const std::string& InnerPropName = EmitEdgePropertyTest(InnerProp, OptDescs, O);
InnerProp.getOperator()->getAsString();
EmitEdgePropertyTest(InnerPropName, InnerProp, OptDescs, O);
if (j != NumArgs - 1) if (j != NumArgs - 1)
O << ")\n" << Indent3 << ' ' << LogicOp << " ("; O << ")\n" << Indent3 << ' ' << LogicOp << " (";
else else
@ -993,11 +1008,28 @@ void EmitLogicalOperationTest(const DagInit& Prop, const char* LogicOp,
} }
} }
// 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))
return;
else if (EmitEdgePropertyTest2Args(PropName, Prop, OptDescs, O))
return;
else
throw PropName + ": unknown edge property!";
}
// Emit a single Edge* class. // Emit a single Edge* class.
void EmitEdgeClass(unsigned N, const std::string& Target, void EmitEdgeClass(unsigned N, const std::string& Target,
ListInit* Props, const GlobalOptionDescriptions& OptDescs, ListInit* Props, const GlobalOptionDescriptions& OptDescs,
std::ostream& O) { std::ostream& O) {
bool IsDefault = false;
// Class constructor. // Class constructor.
O << "class Edge" << N << ": public Edge {\n" O << "class Edge" << N << ": public Edge {\n"
@ -1009,28 +1041,26 @@ void EmitEdgeClass(unsigned N, const std::string& Target,
<< Indent1 << "unsigned Weight(const InputLanguagesSet& InLangs) const {\n" << Indent1 << "unsigned Weight(const InputLanguagesSet& InLangs) const {\n"
<< Indent2 << "unsigned ret = 0;\n"; << Indent2 << "unsigned ret = 0;\n";
// Emit tests for every edge property.
for (size_t i = 0, PropsSize = Props->size(); i < PropsSize; ++i) { for (size_t i = 0, PropsSize = Props->size(); i < PropsSize; ++i) {
const DagInit& Prop = dynamic_cast<DagInit&>(*Props->getElement(i)); const DagInit& Prop = InitPtrToDagInitRef(Props->getElement(i));
const std::string& PropName = Prop.getOperator()->getAsString(); const std::string& PropName = Prop.getOperator()->getAsString();
unsigned N = 2;
if (PropName == "default")
IsDefault = true;
O << Indent2 << "if ("; O << Indent2 << "if (";
if (PropName == "and") {
EmitLogicalOperationTest(Prop, "&&", OptDescs, O); if (PropName == "weight") {
} checkNumberOfArguments(&Prop, 2);
else if (PropName == "or") { N = InitPtrToInt(Prop.getArg(0));
EmitLogicalOperationTest(Prop, "||", OptDescs, O); const DagInit& InnerProp = InitPtrToDagInitRef(Prop.getArg(1));
EmitEdgePropertyTest(InnerProp, OptDescs, O);
} }
else { else {
EmitEdgePropertyTest(PropName, Prop, OptDescs, O); EmitEdgePropertyTest(Prop, OptDescs, O);
} }
O << ")\n" << Indent3 << "ret += 2;\n";
}
if (IsDefault) O << ")\n" << Indent3 << "ret += " << N << ";\n";
O << Indent2 << "ret += 1;\n"; }
O << Indent2 << "return ret;\n" O << Indent2 << "return ret;\n"
<< Indent1 << "};\n\n};\n\n"; << Indent1 << "};\n\n};\n\n";