From 7d2019f9b3dfd49584d4f59bd76ed6a6e117068e Mon Sep 17 00:00:00 2001 From: Mikhail Glushenkov Date: Sun, 18 Oct 2009 22:51:30 +0000 Subject: [PATCH] Refactoring, no functionality change. llvm-svn: 84450 --- .../TableGen/LLVMCConfigurationEmitter.cpp | 227 ++++++++++++------ 1 file changed, 158 insertions(+), 69 deletions(-) diff --git a/llvm/utils/TableGen/LLVMCConfigurationEmitter.cpp b/llvm/utils/TableGen/LLVMCConfigurationEmitter.cpp index a8eaa3a16a7b..f73c09acce7d 100644 --- a/llvm/utils/TableGen/LLVMCConfigurationEmitter.cpp +++ b/llvm/utils/TableGen/LLVMCConfigurationEmitter.cpp @@ -56,8 +56,14 @@ const char * SinkOptionName = "AutoGeneratedSinkOption"; /// Id - An 'identity' function object. struct Id { - template - void operator()(const T&) const { + template + void operator()(const T0&) const { + } + template + void operator()(const T0&, const T1&) const { + } + template + 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(Case)->getOperator()->getAsString() != "case") + GetOperatorName(static_cast(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 -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(arg) - && static_cast(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(arg) + && GetOperatorName(static_cast(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 +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(Statement) && + GetOperatorName(static_cast(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 -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(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(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