From 545f96814bd881d57d961aa51465e977f9172b2d Mon Sep 17 00:00:00 2001 From: Mikhail Glushenkov Date: Tue, 15 Dec 2009 07:20:50 +0000 Subject: [PATCH] Support hook invocation from 'append_cmd'. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@91419 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/LLVMC/AppendCmdHook.td | 28 +++++ test/LLVMC/OutputSuffixHook.td | 24 ++++ utils/TableGen/LLVMCConfigurationEmitter.cpp | 117 +++++++++++-------- 3 files changed, 123 insertions(+), 46 deletions(-) create mode 100644 test/LLVMC/AppendCmdHook.td create mode 100644 test/LLVMC/OutputSuffixHook.td diff --git a/test/LLVMC/AppendCmdHook.td b/test/LLVMC/AppendCmdHook.td new file mode 100644 index 00000000000..888d6869999 --- /dev/null +++ b/test/LLVMC/AppendCmdHook.td @@ -0,0 +1,28 @@ +// Check that hooks can be invoked from 'append_cmd'. +// RUN: tblgen -I %p/../../include --gen-llvmc %s -o %t +// RUN: FileCheck -input-file=%t %s +// RUN: %compile_cxx -fexceptions -x c++ %t + +include "llvm/CompilerDriver/Common.td" + +// CHECK: std::string MyHook() + +def OptList : OptionList<[ +(switch_option "dummy1", (help "none")), +(switch_option "dummy2", (help "none")) +]>; + +def dummy_tool : Tool<[ +(cmd_line "dummy_cmd $INFILE"), +(in_language "dummy_lang"), +(out_language "dummy_lang"), +(actions (case + // CHECK: push_back("-arg1") + // CHECK: push_back("-arg2") + (switch_on "dummy1"), (append_cmd "-arg1 -arg2"), + // CHECK: push_back("-arg3") + // CHECK: hooks::MyHook() + (switch_on "dummy2"), (append_cmd "-arg3 $CALL(MyHook)"))) +]>; + +def DummyGraph : CompilationGraph<[SimpleEdge<"root", "dummy_tool">]>; diff --git a/test/LLVMC/OutputSuffixHook.td b/test/LLVMC/OutputSuffixHook.td new file mode 100644 index 00000000000..d1f9999b15c --- /dev/null +++ b/test/LLVMC/OutputSuffixHook.td @@ -0,0 +1,24 @@ +// Check that hooks can be invoked from 'output_suffix'. +// RUN: tblgen -I %p/../../include --gen-llvmc %s -o %t +// RUN: FileCheck -input-file=%t %s +// RUN: %compile_cxx -fexceptions -x c++ %t +// XFAIL: * + +include "llvm/CompilerDriver/Common.td" + +// CHECK: std::string MyHook() + +def OptList : OptionList<[ +(switch_option "dummy1", (help "none")) +]>; + +def dummy_tool : Tool<[ +(cmd_line "dummy_cmd $INFILE"), +(in_language "dummy_lang"), +(out_language "dummy_lang"), +(actions (case + // CHECK: hooks::MyHook() + (switch_on "dummy1"), (output_suffix "$CALL(MyHook)"))) +]>; + +def DummyGraph : CompilationGraph<[SimpleEdge<"root", "dummy_tool">]>; diff --git a/utils/TableGen/LLVMCConfigurationEmitter.cpp b/utils/TableGen/LLVMCConfigurationEmitter.cpp index 69001dd2759..6217f5c1d34 100644 --- a/utils/TableGen/LLVMCConfigurationEmitter.cpp +++ b/utils/TableGen/LLVMCConfigurationEmitter.cpp @@ -15,8 +15,6 @@ #include "Record.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringSet.h" #include @@ -1454,9 +1452,9 @@ void EmitCaseConstructHandler(const Init* Case, unsigned IndentLevel, EmitCaseStatementCallback(Callback, O), IndentLevel); } -/// TokenizeCmdline - converts from "$CALL(HookName, 'Arg1', 'Arg2')/path" to -/// ["$CALL(", "HookName", "Arg1", "Arg2", ")/path"] . -/// Helper function used by EmitCmdLineVecFill and. +/// TokenizeCmdline - converts from +/// "$CALL(HookName, 'Arg1', 'Arg2')/path -arg1 -arg2" to +/// ["$CALL(", "HookName", "Arg1", "Arg2", ")/path", "-arg1", "-arg2"]. void TokenizeCmdline(const std::string& CmdLine, StrVector& Out) { const char* Delimiters = " \t\n\v\f\r"; enum TokenizerState @@ -1823,17 +1821,36 @@ class EmitActionHandlersCallback const OptionDescriptions& OptDescs; typedef EmitActionHandlersCallbackHandler Handler; + /// EmitHookInvocation - Common code for hook invocation from actions. Used by + /// onAppendCmd and onOutputSuffix. + void EmitHookInvocation(const std::string& Str, + const char* BlockOpen, const char* BlockClose, + unsigned IndentLevel, raw_ostream& O) const + { + StrVector Out; + TokenizeCmdline(Str, Out); + + for (StrVector::const_iterator B = Out.begin(), E = Out.end(); + B != E; ++B) { + const std::string& cmd = *B; + + O.indent(IndentLevel) << BlockOpen; + + if (cmd.at(0) == '$') + B = SubstituteSpecialCommands(B, E, /* IsJoin = */ true, O); + else + O << '"' << cmd << '"'; + + O << BlockClose; + } + } + void onAppendCmd (const DagInit& Dag, unsigned IndentLevel, raw_ostream& O) const { checkNumberOfArguments(&Dag, 1); - const std::string& Cmd = InitPtrToString(Dag.getArg(0)); - StrVector Out; - llvm::SplitString(Cmd, Out); - - for (StrVector::const_iterator B = Out.begin(), E = Out.end(); - B != E; ++B) - O.indent(IndentLevel) << "vec.push_back(\"" << *B << "\");\n"; + this->EmitHookInvocation(InitPtrToString(Dag.getArg(0)), + "vec.push_back(", ");\n", IndentLevel, O); } void onForward (const DagInit& Dag, @@ -1886,13 +1903,12 @@ class EmitActionHandlersCallback << (D.isParameter() ? ".c_str()" : "") << "));\n"; } - void onOutputSuffix (const DagInit& Dag, unsigned IndentLevel, raw_ostream& O) const { checkNumberOfArguments(&Dag, 1); - const std::string& OutSuf = InitPtrToString(Dag.getArg(0)); - O.indent(IndentLevel) << "output_suffix = \"" << OutSuf << "\";\n"; + this->EmitHookInvocation(InitPtrToString(Dag.getArg(0)), + "output_suffix = ", ";\n", IndentLevel, O); } void onStopCompilation (const DagInit& Dag, @@ -2521,7 +2537,9 @@ public: {} void onAction (const DagInit& Dag) { - if (GetOperatorName(Dag) == "forward_transformed_value") { + const std::string& Name = GetOperatorName(Dag); + + if (Name == "forward_transformed_value") { checkNumberOfArguments(Dag, 2); const std::string& OptName = InitPtrToString(Dag.getArg(0)); const std::string& HookName = InitPtrToString(Dag.getArg(1)); @@ -2530,6 +2548,42 @@ public: HookNames_[HookName] = HookInfo(D.isList() ? HookInfo::ListHook : HookInfo::ArgHook); } + else if (Name == "append_cmd" || Name == "output_suffix") { + checkNumberOfArguments(Dag, 1); + this->onCmdLine(InitPtrToString(Dag.getArg(0))); + } + } + + void onCmdLine(const std::string& Cmd) { + StrVector cmds; + TokenizeCmdline(Cmd, cmds); + + for (StrVector::const_iterator B = cmds.begin(), E = cmds.end(); + B != E; ++B) { + const std::string& cmd = *B; + + if (cmd == "$CALL") { + unsigned NumArgs = 0; + checkedIncrement(B, E, "Syntax error in $CALL invocation!"); + const std::string& HookName = *B; + + if (HookName.at(0) == ')') + throw "$CALL invoked with no arguments!"; + + while (++B != E && B->at(0) != ')') { + ++NumArgs; + } + + HookInfoMap::const_iterator H = HookNames_.find(HookName); + + 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] = HookInfo(NumArgs); + } + } } void operator()(const Init* Arg) { @@ -2551,36 +2605,7 @@ public: } // 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; - - if (cmd == "$CALL") { - unsigned NumArgs = 0; - checkedIncrement(B, E, "Syntax error in $CALL invocation!"); - const std::string& HookName = *B; - - - if (HookName.at(0) == ')') - throw "$CALL invoked with no arguments!"; - - while (++B != E && B->at(0) != ')') { - ++NumArgs; - } - - HookInfoMap::const_iterator H = HookNames_.find(HookName); - - 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] = HookInfo(NumArgs); - - } - } + this->onCmdLine(InitPtrToString(Arg)); } void operator()(const DagInit* Test, unsigned, bool) {