parent
131d599be8
commit
7d2019f9b3
|
@ -56,8 +56,14 @@ const char * SinkOptionName = "AutoGeneratedSinkOption";
|
||||||
|
|
||||||
/// Id - An 'identity' function object.
|
/// Id - An 'identity' function object.
|
||||||
struct Id {
|
struct Id {
|
||||||
template<typename T>
|
template<typename T0>
|
||||||
void operator()(const T&) const {
|
void operator()(const T0&) const {
|
||||||
|
}
|
||||||
|
template<typename T0, typename T1>
|
||||||
|
void operator()(const T0&, const T1&) const {
|
||||||
|
}
|
||||||
|
template<typename T0, typename T1, typename T2>
|
||||||
|
void operator()(const T0&, const T1&, const T2&) const {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -81,16 +87,24 @@ const DagInit& InitPtrToDag(const Init* ptr) {
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::string GetOperatorName(const DagInit* D) {
|
||||||
|
return D->getOperator()->getAsString();
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string GetOperatorName(const DagInit& D) {
|
||||||
|
return GetOperatorName(&D);
|
||||||
|
}
|
||||||
|
|
||||||
// checkNumberOfArguments - Ensure that the number of args in d is
|
// checkNumberOfArguments - Ensure that the number of args in d is
|
||||||
// greater than or equal to min_arguments, otherwise throw an exception.
|
// greater than or equal to min_arguments, otherwise throw an exception.
|
||||||
void checkNumberOfArguments (const DagInit* d, unsigned min_arguments) {
|
void checkNumberOfArguments (const DagInit* d, unsigned min_arguments) {
|
||||||
if (!d || d->getNumArgs() < min_arguments)
|
if (!d || d->getNumArgs() < min_arguments)
|
||||||
throw d->getOperator()->getAsString() + ": too few arguments!";
|
throw GetOperatorName(d) + ": too few arguments!";
|
||||||
}
|
}
|
||||||
|
|
||||||
// isDagEmpty - is this DAG marked with an empty marker?
|
// isDagEmpty - is this DAG marked with an empty marker?
|
||||||
bool isDagEmpty (const DagInit* d) {
|
bool isDagEmpty (const DagInit* d) {
|
||||||
return d->getOperator()->getAsString() == "empty_dag_marker";
|
return GetOperatorName(d) == "empty_dag_marker";
|
||||||
}
|
}
|
||||||
|
|
||||||
// EscapeVariableName - Escape commas and other symbols not allowed
|
// EscapeVariableName - Escape commas and other symbols not allowed
|
||||||
|
@ -421,7 +435,7 @@ public:
|
||||||
/// handler.
|
/// handler.
|
||||||
void operator() (Init* i) {
|
void operator() (Init* i) {
|
||||||
const DagInit& property = InitPtrToDag(i);
|
const DagInit& property = InitPtrToDag(i);
|
||||||
const std::string& property_name = property.getOperator()->getAsString();
|
const std::string& property_name = GetOperatorName(property);
|
||||||
typename HandlerMap::iterator method = Handlers_.find(property_name);
|
typename HandlerMap::iterator method = Handlers_.find(property_name);
|
||||||
|
|
||||||
if (method != Handlers_.end()) {
|
if (method != Handlers_.end()) {
|
||||||
|
@ -570,7 +584,7 @@ public:
|
||||||
checkNumberOfArguments(&d, 1);
|
checkNumberOfArguments(&d, 1);
|
||||||
|
|
||||||
const OptionType::OptionType Type =
|
const OptionType::OptionType Type =
|
||||||
stringToOptionType(d.getOperator()->getAsString());
|
stringToOptionType(GetOperatorName(d));
|
||||||
const std::string& Name = InitPtrToString(d.getArg(0));
|
const std::string& Name = InitPtrToString(d.getArg(0));
|
||||||
|
|
||||||
OptionDescription OD(Type, Name);
|
OptionDescription OD(Type, Name);
|
||||||
|
@ -690,7 +704,7 @@ private:
|
||||||
checkNumberOfArguments(d, 1);
|
checkNumberOfArguments(d, 1);
|
||||||
Init* Case = d->getArg(0);
|
Init* Case = d->getArg(0);
|
||||||
if (typeid(*Case) != typeid(DagInit) ||
|
if (typeid(*Case) != typeid(DagInit) ||
|
||||||
static_cast<DagInit*>(Case)->getOperator()->getAsString() != "case")
|
GetOperatorName(static_cast<DagInit*>(Case)) != "case")
|
||||||
throw
|
throw
|
||||||
std::string("The argument to (actions) should be a 'case' construct!");
|
std::string("The argument to (actions) should be a 'case' construct!");
|
||||||
toolDesc_.Actions = Case;
|
toolDesc_.Actions = Case;
|
||||||
|
@ -892,22 +906,60 @@ void TypecheckGraph (const RecordVector& EdgeVector,
|
||||||
/// WalkCase - Walks the 'case' expression DAG and invokes
|
/// WalkCase - Walks the 'case' expression DAG and invokes
|
||||||
/// TestCallback on every test, and StatementCallback on every
|
/// TestCallback on every test, and StatementCallback on every
|
||||||
/// statement. Handles 'case' nesting, but not the 'and' and 'or'
|
/// statement. Handles 'case' nesting, but not the 'and' and 'or'
|
||||||
/// combinators.
|
/// combinators (that is, they are passed directly to TestCallback).
|
||||||
// TODO: Re-implement EmitCaseConstructHandler on top of this function?
|
/// TestCallback must have type 'void TestCallback(const DagInit*, unsigned
|
||||||
|
/// IndentLevel, bool FirstTest)'.
|
||||||
|
/// StatementCallback must have type 'void StatementCallback(const Init*,
|
||||||
|
/// unsigned IndentLevel)'.
|
||||||
template <typename F1, typename F2>
|
template <typename F1, typename F2>
|
||||||
void WalkCase(Init* Case, F1 TestCallback, F2 StatementCallback) {
|
void WalkCase(const Init* Case, F1 TestCallback, F2 StatementCallback,
|
||||||
|
unsigned IndentLevel = 0)
|
||||||
|
{
|
||||||
const DagInit& d = InitPtrToDag(Case);
|
const DagInit& d = InitPtrToDag(Case);
|
||||||
|
|
||||||
|
// Error checks.
|
||||||
|
if (GetOperatorName(d) != "case")
|
||||||
|
throw std::string("WalkCase should be invoked only on 'case' expressions!");
|
||||||
|
|
||||||
|
if (d.getNumArgs() < 2)
|
||||||
|
throw "There should be at least one clause in the 'case' expression:\n"
|
||||||
|
+ d.getAsString();
|
||||||
|
|
||||||
|
// Main loop.
|
||||||
bool even = false;
|
bool even = false;
|
||||||
|
const unsigned numArgs = d.getNumArgs();
|
||||||
|
unsigned i = 1;
|
||||||
for (DagInit::const_arg_iterator B = d.arg_begin(), E = d.arg_end();
|
for (DagInit::const_arg_iterator B = d.arg_begin(), E = d.arg_end();
|
||||||
B != E; ++B) {
|
B != E; ++B) {
|
||||||
Init* arg = *B;
|
Init* arg = *B;
|
||||||
if (even && dynamic_cast<DagInit*>(arg)
|
|
||||||
&& static_cast<DagInit*>(arg)->getOperator()->getAsString() == "case")
|
if (!even)
|
||||||
WalkCase(arg, TestCallback, StatementCallback);
|
{
|
||||||
else if (!even)
|
// Handle test.
|
||||||
TestCallback(arg);
|
const DagInit& Test = InitPtrToDag(arg);
|
||||||
|
|
||||||
|
if (GetOperatorName(Test) == "default" && (i+1 != numArgs))
|
||||||
|
throw std::string("The 'default' clause should be the last in the"
|
||||||
|
"'case' construct!");
|
||||||
|
if (i == numArgs)
|
||||||
|
throw "Case construct handler: no corresponding action "
|
||||||
|
"found for the test " + Test.getAsString() + '!';
|
||||||
|
|
||||||
|
TestCallback(&Test, IndentLevel, (i == 1));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
StatementCallback(arg);
|
{
|
||||||
|
if (dynamic_cast<DagInit*>(arg)
|
||||||
|
&& GetOperatorName(static_cast<DagInit*>(arg)) == "case") {
|
||||||
|
// Nested 'case'.
|
||||||
|
WalkCase(arg, TestCallback, StatementCallback, IndentLevel + Indent1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle statement.
|
||||||
|
StatementCallback(arg, IndentLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
++i;
|
||||||
even = !even;
|
even = !even;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -919,7 +971,7 @@ class ExtractOptionNames {
|
||||||
|
|
||||||
void processDag(const Init* Statement) {
|
void processDag(const Init* Statement) {
|
||||||
const DagInit& Stmt = InitPtrToDag(Statement);
|
const DagInit& Stmt = InitPtrToDag(Statement);
|
||||||
const std::string& ActionName = Stmt.getOperator()->getAsString();
|
const std::string& ActionName = GetOperatorName(Stmt);
|
||||||
if (ActionName == "forward" || ActionName == "forward_as" ||
|
if (ActionName == "forward" || ActionName == "forward_as" ||
|
||||||
ActionName == "unpack_values" || ActionName == "switch_on" ||
|
ActionName == "unpack_values" || ActionName == "switch_on" ||
|
||||||
ActionName == "parameter_equals" || ActionName == "element_in_list" ||
|
ActionName == "parameter_equals" || ActionName == "element_in_list" ||
|
||||||
|
@ -950,6 +1002,13 @@ public:
|
||||||
this->processDag(Statement);
|
this->processDag(Statement);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void operator()(const DagInit* Test, unsigned, bool) {
|
||||||
|
this->operator()(Test);
|
||||||
|
}
|
||||||
|
void operator()(const Init* Statement, unsigned) {
|
||||||
|
this->operator()(Statement);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// CheckForSuperfluousOptions - Check that there are no side
|
/// CheckForSuperfluousOptions - Check that there are no side
|
||||||
|
@ -1164,7 +1223,7 @@ void EmitLogicalNot(const DagInit& d, unsigned IndentLevel,
|
||||||
void EmitCaseTest(const DagInit& d, unsigned IndentLevel,
|
void EmitCaseTest(const DagInit& d, unsigned IndentLevel,
|
||||||
const OptionDescriptions& OptDescs,
|
const OptionDescriptions& OptDescs,
|
||||||
raw_ostream& O) {
|
raw_ostream& O) {
|
||||||
const std::string& TestName = d.getOperator()->getAsString();
|
const std::string& TestName = GetOperatorName(d);
|
||||||
|
|
||||||
if (TestName == "and")
|
if (TestName == "and")
|
||||||
EmitLogicalOperationTest(d, "&&", IndentLevel, OptDescs, O);
|
EmitLogicalOperationTest(d, "&&", IndentLevel, OptDescs, O);
|
||||||
|
@ -1182,63 +1241,70 @@ void EmitCaseTest(const DagInit& d, unsigned IndentLevel,
|
||||||
throw TestName + ": unknown edge property!";
|
throw TestName + ": unknown edge property!";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// EmitCaseTestCallback - Callback used by EmitCaseConstructHandler.
|
||||||
|
class EmitCaseTestCallback {
|
||||||
|
bool EmitElseIf_;
|
||||||
|
const OptionDescriptions& OptDescs_;
|
||||||
|
raw_ostream& O_;
|
||||||
|
public:
|
||||||
|
|
||||||
|
EmitCaseTestCallback(bool EmitElseIf,
|
||||||
|
const OptionDescriptions& OptDescs, raw_ostream& O)
|
||||||
|
: EmitElseIf_(EmitElseIf), OptDescs_(OptDescs), O_(O)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void operator()(const DagInit* Test, unsigned IndentLevel, bool FirstTest)
|
||||||
|
{
|
||||||
|
if (GetOperatorName(Test) == "default") {
|
||||||
|
O_.indent(IndentLevel) << "else {\n";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
O_.indent(IndentLevel)
|
||||||
|
<< ((!FirstTest && EmitElseIf_) ? "else if (" : "if (");
|
||||||
|
EmitCaseTest(*Test, IndentLevel, OptDescs_, O_);
|
||||||
|
O_ << ") {\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/// EmitCaseStatementCallback - Callback used by EmitCaseConstructHandler.
|
||||||
|
template <typename F>
|
||||||
|
class EmitCaseStatementCallback {
|
||||||
|
F Callback_;
|
||||||
|
raw_ostream& O_;
|
||||||
|
public:
|
||||||
|
|
||||||
|
EmitCaseStatementCallback(F Callback, raw_ostream& O)
|
||||||
|
: Callback_(Callback), O_(O)
|
||||||
|
{}
|
||||||
|
|
||||||
|
// TODO: Handle lists here.
|
||||||
|
void operator() (const Init* Statement, unsigned IndentLevel) {
|
||||||
|
// Ignore nested 'case' DAG.
|
||||||
|
if (!(dynamic_cast<const DagInit*>(Statement) &&
|
||||||
|
GetOperatorName(static_cast<const DagInit*>(Statement)) == "case"))
|
||||||
|
Callback_(Statement, (IndentLevel + Indent1), O_);
|
||||||
|
O_.indent(IndentLevel) << "}\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
/// EmitCaseConstructHandler - Emit code that handles the 'case'
|
/// EmitCaseConstructHandler - Emit code that handles the 'case'
|
||||||
/// construct. Takes a function object that should emit code for every case
|
/// construct. Takes a function object that should emit code for every case
|
||||||
/// clause.
|
/// clause. Implemented on top of WalkCase.
|
||||||
/// Callback's type is void F(Init* Statement, unsigned IndentLevel,
|
/// Callback's type is void F(Init* Statement, unsigned IndentLevel,
|
||||||
/// raw_ostream& O).
|
/// raw_ostream& O).
|
||||||
/// EmitElseIf parameter controls the type of condition that is emitted ('if
|
/// EmitElseIf parameter controls the type of condition that is emitted ('if
|
||||||
/// (..) {...} else if (...) {} ... else {...}' vs. 'if (..) {...} if(...)
|
/// (..) {..} else if (..) {} .. else {..}' vs. 'if (..) {..} if(..) {..}
|
||||||
/// {...} ...').
|
/// .. else {..}').
|
||||||
template <typename F>
|
template <typename F>
|
||||||
void EmitCaseConstructHandler(const Init* Dag, unsigned IndentLevel,
|
void EmitCaseConstructHandler(const Init* Case, unsigned IndentLevel,
|
||||||
F Callback, bool EmitElseIf,
|
F Callback, bool EmitElseIf,
|
||||||
const OptionDescriptions& OptDescs,
|
const OptionDescriptions& OptDescs,
|
||||||
raw_ostream& O) {
|
raw_ostream& O) {
|
||||||
const DagInit* d = &InitPtrToDag(Dag);
|
WalkCase(Case, EmitCaseTestCallback(EmitElseIf, OptDescs, O),
|
||||||
if (d->getOperator()->getAsString() != "case")
|
EmitCaseStatementCallback<F>(Callback, O), IndentLevel);
|
||||||
throw std::string("EmitCaseConstructHandler should be invoked"
|
|
||||||
" only on 'case' expressions!");
|
|
||||||
|
|
||||||
unsigned numArgs = d->getNumArgs();
|
|
||||||
if (d->getNumArgs() < 2)
|
|
||||||
throw "There should be at least one clause in the 'case' expression:\n"
|
|
||||||
+ d->getAsString();
|
|
||||||
|
|
||||||
for (unsigned i = 0; i != numArgs; ++i) {
|
|
||||||
const DagInit& Test = InitPtrToDag(d->getArg(i));
|
|
||||||
|
|
||||||
// Emit the test.
|
|
||||||
if (Test.getOperator()->getAsString() == "default") {
|
|
||||||
if (i+2 != numArgs)
|
|
||||||
throw std::string("The 'default' clause should be the last in the"
|
|
||||||
"'case' construct!");
|
|
||||||
O.indent(IndentLevel) << "else {\n";
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
O.indent(IndentLevel) << ((i != 0 && EmitElseIf) ? "else if (" : "if (");
|
|
||||||
EmitCaseTest(Test, IndentLevel, OptDescs, O);
|
|
||||||
O << ") {\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Emit the corresponding statement.
|
|
||||||
++i;
|
|
||||||
if (i == numArgs)
|
|
||||||
throw "Case construct handler: no corresponding action "
|
|
||||||
"found for the test " + Test.getAsString() + '!';
|
|
||||||
|
|
||||||
Init* arg = d->getArg(i);
|
|
||||||
const DagInit* nd = dynamic_cast<DagInit*>(arg);
|
|
||||||
if (nd && (nd->getOperator()->getAsString() == "case")) {
|
|
||||||
// Handle the nested 'case'.
|
|
||||||
EmitCaseConstructHandler(nd, (IndentLevel + Indent1),
|
|
||||||
Callback, EmitElseIf, OptDescs, O);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Callback(arg, (IndentLevel + Indent1), O);
|
|
||||||
}
|
|
||||||
O.indent(IndentLevel) << "}\n";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TokenizeCmdline - converts from "$CALL(HookName, 'Arg1', 'Arg2')/path" to
|
/// TokenizeCmdline - converts from "$CALL(HookName, 'Arg1', 'Arg2')/path" to
|
||||||
|
@ -1546,7 +1612,7 @@ class EmitActionHandler {
|
||||||
raw_ostream& O) const
|
raw_ostream& O) const
|
||||||
{
|
{
|
||||||
const DagInit& Dag = InitPtrToDag(Statement);
|
const DagInit& Dag = InitPtrToDag(Statement);
|
||||||
const std::string& ActionName = Dag.getOperator()->getAsString();
|
const std::string& ActionName = GetOperatorName(Dag);
|
||||||
|
|
||||||
if (ActionName == "append_cmd") {
|
if (ActionName == "append_cmd") {
|
||||||
checkNumberOfArguments(&Dag, 1);
|
checkNumberOfArguments(&Dag, 1);
|
||||||
|
@ -1655,9 +1721,20 @@ public:
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void operator()(const Init* CmdLine) {
|
void operator()(const Init* CmdLine) {
|
||||||
|
// Ignore nested 'case' DAG.
|
||||||
|
if (typeid(*CmdLine) == typeid(DagInit))
|
||||||
|
return;
|
||||||
|
|
||||||
if (IsOutFileIndexCheckRequiredStr(CmdLine))
|
if (IsOutFileIndexCheckRequiredStr(CmdLine))
|
||||||
*ret_ = true;
|
*ret_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void operator()(const DagInit* Test, unsigned, bool) {
|
||||||
|
this->operator()(Test);
|
||||||
|
}
|
||||||
|
void operator()(const Init* Statement, unsigned) {
|
||||||
|
this->operator()(Statement);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
bool IsOutFileIndexCheckRequiredCase (Init* CmdLine) {
|
bool IsOutFileIndexCheckRequiredCase (Init* CmdLine) {
|
||||||
|
@ -1958,7 +2035,7 @@ class PreprocessOptionsCallback {
|
||||||
void processDag(const Init* I, unsigned IndentLevel, raw_ostream& O)
|
void processDag(const Init* I, unsigned IndentLevel, raw_ostream& O)
|
||||||
{
|
{
|
||||||
const DagInit& d = InitPtrToDag(I);
|
const DagInit& d = InitPtrToDag(I);
|
||||||
const std::string& OpName = d.getOperator()->getAsString();
|
const std::string& OpName = GetOperatorName(d);
|
||||||
|
|
||||||
// TOFIX: there is some duplication between this function and
|
// TOFIX: there is some duplication between this function and
|
||||||
// EmitActionHandler.
|
// EmitActionHandler.
|
||||||
|
@ -2067,7 +2144,7 @@ void EmitPopulateLanguageMap (const RecordKeeper& Records, raw_ostream& O)
|
||||||
void IncDecWeight (const Init* i, unsigned IndentLevel,
|
void IncDecWeight (const Init* i, unsigned IndentLevel,
|
||||||
raw_ostream& O) {
|
raw_ostream& O) {
|
||||||
const DagInit& d = InitPtrToDag(i);
|
const DagInit& d = InitPtrToDag(i);
|
||||||
const std::string& OpName = d.getOperator()->getAsString();
|
const std::string& OpName = GetOperatorName(d);
|
||||||
|
|
||||||
if (OpName == "inc_weight") {
|
if (OpName == "inc_weight") {
|
||||||
O.indent(IndentLevel) << "ret += ";
|
O.indent(IndentLevel) << "ret += ";
|
||||||
|
@ -2183,6 +2260,11 @@ public:
|
||||||
|
|
||||||
void operator()(const Init* CmdLine) {
|
void operator()(const Init* CmdLine) {
|
||||||
StrVector cmds;
|
StrVector cmds;
|
||||||
|
|
||||||
|
// Ignore nested 'case' DAG.
|
||||||
|
if (typeid(*CmdLine) == typeid(DagInit))
|
||||||
|
return;
|
||||||
|
|
||||||
TokenizeCmdline(InitPtrToString(CmdLine), cmds);
|
TokenizeCmdline(InitPtrToString(CmdLine), cmds);
|
||||||
for (StrVector::const_iterator B = cmds.begin(), E = cmds.end();
|
for (StrVector::const_iterator B = cmds.begin(), E = cmds.end();
|
||||||
B != E; ++B) {
|
B != E; ++B) {
|
||||||
|
@ -2212,6 +2294,13 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void operator()(const DagInit* Test, unsigned, bool) {
|
||||||
|
this->operator()(Test);
|
||||||
|
}
|
||||||
|
void operator()(const Init* Statement, unsigned) {
|
||||||
|
this->operator()(Statement);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// FillInHookNames - Actually extract the hook names from all command
|
/// FillInHookNames - Actually extract the hook names from all command
|
||||||
|
|
Loading…
Reference in New Issue