From: Mikhail Glushenkov Date: Mon, 7 Dec 2009 17:03:05 +0000 (+0000) Subject: Implement 'forward_value' and 'forward_transformed_value'. X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=8245a1dd530083f6b6bfebd0f42ade1942ad871f;p=oota-llvm.git Implement 'forward_value' and 'forward_transformed_value'. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@90770 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/CompilerDriver/Common.td b/include/llvm/CompilerDriver/Common.td index 79edb0260a3..06983724bca 100644 --- a/include/llvm/CompilerDriver/Common.td +++ b/include/llvm/CompilerDriver/Common.td @@ -77,6 +77,8 @@ def any_empty; def append_cmd; def forward; def forward_as; +def forward_value; +def forward_transformed_value; def stop_compilation; def unpack_values; def warning; diff --git a/test/LLVMC/ForwardTransformedValue.td b/test/LLVMC/ForwardTransformedValue.td new file mode 100644 index 00000000000..478d1267282 --- /dev/null +++ b/test/LLVMC/ForwardTransformedValue.td @@ -0,0 +1,21 @@ +// Check that forward_transformed_value works. +// The dummy tool and graph are required to silence warnings. +// RUN: tblgen -I %p/../../include --gen-llvmc %s -o %t +// RUN: grep HookA %t +// RUN: grep HookB %t + +include "llvm/CompilerDriver/Common.td" + +def OptList : OptionList<[(parameter_option "a", (extern)), + (prefix_list_option "b", (extern))]>; + +def dummy_tool : Tool<[ +(cmd_line "dummy_cmd $INFILE"), +(in_language "dummy"), +(out_language "dummy"), +(actions (case + (not_empty "a"), (forward_transformed_value "a", "HookA"), + (not_empty "b"), (forward_transformed_value "b", "HookB"))) +]>; + +def DummyGraph : CompilationGraph<[SimpleEdge<"root", "dummy_tool">]>; diff --git a/test/LLVMC/ForwardValue.td b/test/LLVMC/ForwardValue.td new file mode 100644 index 00000000000..aebb198fd15 --- /dev/null +++ b/test/LLVMC/ForwardValue.td @@ -0,0 +1,21 @@ +// Check that forward_value works. +// The dummy tool and graph are required to silence warnings. +// RUN: tblgen -I %p/../../include --gen-llvmc %s -o %t +// RUN: grep {vec.push_back\(AutoGeneratedParameter_a\)} %t +// RUN: grep {std::copy\(AutoGeneratedList_b.begin\(\)} %t + +include "llvm/CompilerDriver/Common.td" + +def OptList : OptionList<[(parameter_option "a", (extern)), + (prefix_list_option "b", (extern))]>; + +def dummy_tool : Tool<[ +(cmd_line "dummy_cmd $INFILE"), +(in_language "dummy"), +(out_language "dummy"), +(actions (case + (not_empty "a"), (forward_value "a"), + (not_empty "b"), (forward_value "b"))) +]>; + +def DummyGraph : CompilationGraph<[SimpleEdge<"root", "dummy_tool">]>; diff --git a/utils/TableGen/LLVMCConfigurationEmitter.cpp b/utils/TableGen/LLVMCConfigurationEmitter.cpp index a3b54a90559..a5867b4a7fa 100644 --- a/utils/TableGen/LLVMCConfigurationEmitter.cpp +++ b/utils/TableGen/LLVMCConfigurationEmitter.cpp @@ -98,10 +98,13 @@ const std::string GetOperatorName(const DagInit& 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) +void checkNumberOfArguments (const DagInit* d, unsigned minArgs) { + if (!d || d->getNumArgs() < minArgs) throw GetOperatorName(d) + ": too few arguments!"; } +void checkNumberOfArguments (const DagInit& d, unsigned minArgs) { + checkNumberOfArguments(&d, minArgs); +} // isDagEmpty - is this DAG marked with an empty marker? bool isDagEmpty (const DagInit* d) { @@ -1043,6 +1046,8 @@ class ExtractOptionNames { const DagInit& Stmt = InitPtrToDag(Statement); const std::string& ActionName = GetOperatorName(Stmt); if (ActionName == "forward" || ActionName == "forward_as" || + ActionName == "forward_value" || + ActionName == "forward_transformed_value" || ActionName == "unpack_values" || ActionName == "switch_on" || ActionName == "parameter_equals" || ActionName == "element_in_list" || ActionName == "not_empty" || ActionName == "empty") { @@ -1796,6 +1801,45 @@ class EmitActionHandlersCallback IndentLevel, NewName, O); } + void onForwardValue (const DagInit& Dag, + unsigned IndentLevel, raw_ostream& O) const + { + checkNumberOfArguments(&Dag, 1); + const std::string& Name = InitPtrToString(Dag.getArg(0)); + const OptionDescription& D = OptDescs.FindOption(Name); + + if (D.isParameter()) { + O.indent(IndentLevel) << "vec.push_back(" + << D.GenVariableName() << ");\n"; + } + else if (D.isList()) { + O.indent(IndentLevel) << "std::copy(" << D.GenVariableName() + << ".begin(), " << D.GenVariableName() + << ".end(), std::back_inserter(vec));\n"; + } + else { + throw "'forward_value' used with a switch or an alias!"; + } + } + + void onForwardTransformedValue (const DagInit& Dag, + unsigned IndentLevel, raw_ostream& O) const + { + checkNumberOfArguments(&Dag, 2); + const std::string& Name = InitPtrToString(Dag.getArg(0)); + const std::string& Hook = InitPtrToString(Dag.getArg(1)); + const OptionDescription& D = OptDescs.FindOption(Name); + + if (D.isParameter() || D.isList()) { + O.indent(IndentLevel) << "vec.push_back(" << "hooks::" + << Hook << "(" << D.GenVariableName() << "));\n"; + } + else { + throw "'forward_transformed_value' used with a switch or an alias!"; + } + } + + void onOutputSuffix (const DagInit& Dag, unsigned IndentLevel, raw_ostream& O) const { @@ -1819,7 +1863,7 @@ class EmitActionHandlersCallback const OptionDescription& D = OptDescs.FindOption(Name); if (D.isMultiVal()) - throw std::string("Can't use unpack_values with multi-valued options!"); + throw "Can't use unpack_values with multi-valued options!"; if (D.isList()) { O.indent(IndentLevel) @@ -1851,6 +1895,9 @@ class EmitActionHandlersCallback AddHandler("append_cmd", &EmitActionHandlersCallback::onAppendCmd); AddHandler("forward", &EmitActionHandlersCallback::onForward); AddHandler("forward_as", &EmitActionHandlersCallback::onForwardAs); + AddHandler("forward_value", &EmitActionHandlersCallback::onForwardValue); + AddHandler("forward_transformed_value", + &EmitActionHandlersCallback::onForwardTransformedValue); AddHandler("output_suffix", &EmitActionHandlersCallback::onOutputSuffix); AddHandler("stop_compilation", &EmitActionHandlersCallback::onStopCompilation); @@ -2208,7 +2255,7 @@ class EmitPreprocessOptionsCallback : ActionHandlingCallbackBase { O.indent(IndentLevel) << OptDesc.GenVariableName() << ".clear();\n"; } else { - throw "Can't apply 'unset_option' to alias option '" + OptName + "'"; + throw "Can't apply 'unset_option' to alias option '" + OptName + "'!"; } } @@ -2414,23 +2461,72 @@ void EmitPopulateCompilationGraph (const RecordVector& EdgeVector, O << "}\n\n"; } +/// HookInfo - Information about the hook type and number of arguments. +struct HookInfo { + + // A hook can either have a single parameter of type std::vector, + // or NumArgs parameters of type const char*. + enum HookType { ListHook, ArgHook }; + + HookType Type; + unsigned NumArgs; + + HookInfo() : Type(ArgHook), NumArgs(1) + {} + + HookInfo(HookType T) : Type(T), NumArgs(1) + {} + + HookInfo(unsigned N) : Type(ArgHook), NumArgs(N) + {} +}; + +typedef llvm::StringMap HookInfoMap; + /// ExtractHookNames - Extract the hook names from all instances of -/// $CALL(HookName) in the provided command line string. Helper +/// $CALL(HookName) in the provided command line string/action. Helper /// function used by FillInHookNames(). class ExtractHookNames { - llvm::StringMap& HookNames_; + HookInfoMap& HookNames_; + const OptionDescriptions& OptDescs_; public: - ExtractHookNames(llvm::StringMap& HookNames) - : HookNames_(HookNames) {} + ExtractHookNames(HookInfoMap& HookNames, const OptionDescriptions& OptDescs) + : HookNames_(HookNames), OptDescs_(OptDescs) + {} - void operator()(const Init* CmdLine) { - StrVector cmds; + void onAction (const DagInit& Dag) { + if (GetOperatorName(Dag) == "forward_transformed_value") { + checkNumberOfArguments(Dag, 2); + const std::string& OptName = InitPtrToString(Dag.getArg(0)); + const std::string& HookName = InitPtrToString(Dag.getArg(1)); + const OptionDescription& D = OptDescs_.FindOption(OptName); - // Ignore nested 'case' DAG. - if (typeid(*CmdLine) == typeid(DagInit)) + HookNames_[HookName] = HookInfo(D.isList() ? HookInfo::ListHook + : HookInfo::ArgHook); + } + } + + void operator()(const Init* Arg) { + + // We're invoked on an action (either a dag or a dag list). + if (typeid(*Arg) == typeid(DagInit)) { + const DagInit& Dag = InitPtrToDag(Arg); + this->onAction(Dag); return; + } + else if (typeid(*Arg) == typeid(ListInit)) { + const ListInit& List = InitPtrToList(Arg); + for (ListInit::const_iterator B = List.begin(), E = List.end(); B != E; + ++B) { + const DagInit& Dag = InitPtrToDag(*B); + this->onAction(Dag); + } + return; + } - TokenizeCmdline(InitPtrToString(CmdLine), cmds); + // We're invoked on a command line. + StrVector cmds; + TokenizeCmdline(InitPtrToString(Arg), cmds); for (StrVector::const_iterator B = cmds.begin(), E = cmds.end(); B != E; ++B) { const std::string& cmd = *B; @@ -2448,13 +2544,14 @@ public: ++NumArgs; } - StringMap::const_iterator H = HookNames_.find(HookName); + HookInfoMap::const_iterator H = HookNames_.find(HookName); - if (H != HookNames_.end() && H->second != NumArgs) + if (H != HookNames_.end() && H->second.NumArgs != NumArgs && + H->second.Type != HookInfo::ArgHook) throw "Overloading of hooks is not allowed. Overloaded hook: " + HookName; else - HookNames_[HookName] = NumArgs; + HookNames_[HookName] = HookInfo(NumArgs); } } @@ -2471,40 +2568,56 @@ public: /// FillInHookNames - Actually extract the hook names from all command /// line strings. Helper function used by EmitHookDeclarations(). void FillInHookNames(const ToolDescriptions& ToolDescs, - llvm::StringMap& HookNames) + const OptionDescriptions& OptDescs, + HookInfoMap& HookNames) { - // For all command lines: + // For all tool descriptions: for (ToolDescriptions::const_iterator B = ToolDescs.begin(), E = ToolDescs.end(); B != E; ++B) { const ToolDescription& D = *(*B); + + // Look for 'forward_transformed_value' in 'actions'. + if (D.Actions) + WalkCase(D.Actions, Id(), ExtractHookNames(HookNames, OptDescs)); + + // Look for hook invocations in 'cmd_line'. if (!D.CmdLine) continue; if (dynamic_cast(D.CmdLine)) // This is a string. - ExtractHookNames(HookNames).operator()(D.CmdLine); + ExtractHookNames(HookNames, OptDescs).operator()(D.CmdLine); else // This is a 'case' construct. - WalkCase(D.CmdLine, Id(), ExtractHookNames(HookNames)); + WalkCase(D.CmdLine, Id(), ExtractHookNames(HookNames, OptDescs)); } } /// EmitHookDeclarations - Parse CmdLine fields of all the tool /// property records and emit hook function declaration for each /// instance of $CALL(HookName). -void EmitHookDeclarations(const ToolDescriptions& ToolDescs, raw_ostream& O) { - llvm::StringMap HookNames; +void EmitHookDeclarations(const ToolDescriptions& ToolDescs, + const OptionDescriptions& OptDescs, raw_ostream& O) { + HookInfoMap HookNames; - FillInHookNames(ToolDescs, HookNames); + FillInHookNames(ToolDescs, OptDescs, HookNames); if (HookNames.empty()) return; O << "namespace hooks {\n"; - for (StringMap::const_iterator B = HookNames.begin(), + for (HookInfoMap::const_iterator B = HookNames.begin(), E = HookNames.end(); B != E; ++B) { - O.indent(Indent1) << "std::string " << B->first() << "("; + const char* HookName = B->first(); + const HookInfo& Info = B->second; + + O.indent(Indent1) << "std::string " << HookName << "("; - for (unsigned i = 0, j = B->second; i < j; ++i) { - O << "const char* Arg" << i << (i+1 == j ? "" : ", "); + if (Info.Type == HookInfo::ArgHook) { + for (unsigned i = 0, j = Info.NumArgs; i < j; ++i) { + O << "const char* Arg" << i << (i+1 == j ? "" : ", "); + } + } + else { + O << "const std::vector& Arg"; } O <<");\n"; @@ -2541,7 +2654,9 @@ void EmitIncludes(raw_ostream& O) { << "#include \"llvm/Support/CommandLine.h\"\n" << "#include \"llvm/Support/raw_ostream.h\"\n\n" + << "#include \n" << "#include \n" + << "#include \n" << "#include \n\n" << "using namespace llvm;\n" @@ -2635,7 +2750,7 @@ void EmitPluginCode(const PluginData& Data, raw_ostream& O) { EmitOptionDefinitions(Data.OptDescs, Data.HasSink, Data.HasExterns, O); // Emit hook declarations. - EmitHookDeclarations(Data.ToolDescs, O); + EmitHookDeclarations(Data.ToolDescs, Data.OptDescs, O); O << "namespace {\n\n";