Refactoring, no functionality change.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@84450 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Mikhail Glushenkov 2009-10-18 22:51:30 +00:00
parent 38bdfc69cb
commit 4d21ae7cf4

View File

@ -56,8 +56,14 @@ const char * SinkOptionName = "AutoGeneratedSinkOption";
/// Id - An 'identity' function object.
struct Id {
template<typename T>
void operator()(const T&) const {
template<typename T0>
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;
}
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
// greater than or equal to min_arguments, otherwise throw an exception.
void checkNumberOfArguments (const DagInit* d, unsigned 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?
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
@ -421,7 +435,7 @@ public:
/// handler.
void operator() (Init* 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);
if (method != Handlers_.end()) {
@ -570,7 +584,7 @@ public:
checkNumberOfArguments(&d, 1);
const OptionType::OptionType Type =
stringToOptionType(d.getOperator()->getAsString());
stringToOptionType(GetOperatorName(d));
const std::string& Name = InitPtrToString(d.getArg(0));
OptionDescription OD(Type, Name);
@ -690,7 +704,7 @@ private:
checkNumberOfArguments(d, 1);
Init* Case = d->getArg(0);
if (typeid(*Case) != typeid(DagInit) ||
static_cast<DagInit*>(Case)->getOperator()->getAsString() != "case")
GetOperatorName(static_cast<DagInit*>(Case)) != "case")
throw
std::string("The argument to (actions) should be a 'case' construct!");
toolDesc_.Actions = Case;
@ -892,22 +906,60 @@ void TypecheckGraph (const RecordVector& EdgeVector,
/// WalkCase - Walks the 'case' expression DAG and invokes
/// TestCallback on every test, and StatementCallback on every
/// statement. Handles 'case' nesting, but not the 'and' and 'or'
/// combinators.
// TODO: Re-implement EmitCaseConstructHandler on top of this function?
/// combinators (that is, they are passed directly to TestCallback).
/// 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>
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);
// 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;
const unsigned numArgs = d.getNumArgs();
unsigned i = 1;
for (DagInit::const_arg_iterator B = d.arg_begin(), E = d.arg_end();
B != E; ++B) {
Init* arg = *B;
if (even && dynamic_cast<DagInit*>(arg)
&& static_cast<DagInit*>(arg)->getOperator()->getAsString() == "case")
WalkCase(arg, TestCallback, StatementCallback);
else if (!even)
TestCallback(arg);
if (!even)
{
// Handle test.
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
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;
}
}
@ -919,7 +971,7 @@ class ExtractOptionNames {
void processDag(const Init* 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" ||
ActionName == "unpack_values" || ActionName == "switch_on" ||
ActionName == "parameter_equals" || ActionName == "element_in_list" ||
@ -950,6 +1002,13 @@ public:
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
@ -1164,7 +1223,7 @@ void EmitLogicalNot(const DagInit& d, unsigned IndentLevel,
void EmitCaseTest(const DagInit& d, unsigned IndentLevel,
const OptionDescriptions& OptDescs,
raw_ostream& O) {
const std::string& TestName = d.getOperator()->getAsString();
const std::string& TestName = GetOperatorName(d);
if (TestName == "and")
EmitLogicalOperationTest(d, "&&", IndentLevel, OptDescs, O);
@ -1182,63 +1241,70 @@ void EmitCaseTest(const DagInit& d, unsigned IndentLevel,
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'
/// 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,
/// raw_ostream& O).
/// 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>
void EmitCaseConstructHandler(const Init* Dag, unsigned IndentLevel,
void EmitCaseConstructHandler(const Init* Case, unsigned IndentLevel,
F Callback, bool EmitElseIf,
const OptionDescriptions& OptDescs,
raw_ostream& O) {
const DagInit* d = &InitPtrToDag(Dag);
if (d->getOperator()->getAsString() != "case")
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";
}
WalkCase(Case, EmitCaseTestCallback(EmitElseIf, OptDescs, O),
EmitCaseStatementCallback<F>(Callback, O), IndentLevel);
}
/// TokenizeCmdline - converts from "$CALL(HookName, 'Arg1', 'Arg2')/path" to
@ -1546,7 +1612,7 @@ class EmitActionHandler {
raw_ostream& O) const
{
const DagInit& Dag = InitPtrToDag(Statement);
const std::string& ActionName = Dag.getOperator()->getAsString();
const std::string& ActionName = GetOperatorName(Dag);
if (ActionName == "append_cmd") {
checkNumberOfArguments(&Dag, 1);
@ -1655,9 +1721,20 @@ public:
{}
void operator()(const Init* CmdLine) {
// Ignore nested 'case' DAG.
if (typeid(*CmdLine) == typeid(DagInit))
return;
if (IsOutFileIndexCheckRequiredStr(CmdLine))
*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) {
@ -1958,7 +2035,7 @@ class PreprocessOptionsCallback {
void processDag(const Init* I, unsigned IndentLevel, raw_ostream& O)
{
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
// EmitActionHandler.
@ -2067,7 +2144,7 @@ void EmitPopulateLanguageMap (const RecordKeeper& Records, raw_ostream& O)
void IncDecWeight (const Init* i, unsigned IndentLevel,
raw_ostream& O) {
const DagInit& d = InitPtrToDag(i);
const std::string& OpName = d.getOperator()->getAsString();
const std::string& OpName = GetOperatorName(d);
if (OpName == "inc_weight") {
O.indent(IndentLevel) << "ret += ";
@ -2183,6 +2260,11 @@ public:
void operator()(const Init* CmdLine) {
StrVector cmds;
// Ignore nested 'case' DAG.
if (typeid(*CmdLine) == typeid(DagInit))
return;
TokenizeCmdline(InitPtrToString(CmdLine), cmds);
for (StrVector::const_iterator B = cmds.begin(), E = cmds.end();
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