mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-05-20 05:38:50 +00:00
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:
parent
6a6cd729aa
commit
29063554d0
@ -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>;
|
||||||
|
@ -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
|
||||||
|
@ -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";
|
||||||
|
Loading…
x
Reference in New Issue
Block a user