aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/llvm/CompilerDriver/Common.td2
-rw-r--r--test/LLVMC/ForwardTransformedValue.td21
-rw-r--r--test/LLVMC/ForwardValue.td21
-rw-r--r--utils/TableGen/LLVMCConfigurationEmitter.cpp171
4 files changed, 187 insertions, 28 deletions
diff --git a/include/llvm/CompilerDriver/Common.td b/include/llvm/CompilerDriver/Common.td
index 79edb02..0698372 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 0000000..478d126
--- /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 0000000..aebb198
--- /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 a3b54a9..a5867b4 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<std::string>,
+ // 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<HookInfo> 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<unsigned>& HookNames_;
+ HookInfoMap& HookNames_;
+ const OptionDescriptions& OptDescs_;
public:
- ExtractHookNames(llvm::StringMap<unsigned>& 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<unsigned>::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<unsigned>& 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<StringInit*>(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<unsigned> 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<unsigned>::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<std::string>& 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 <algorithm>\n"
<< "#include <cstdlib>\n"
+ << "#include <iterator>\n"
<< "#include <stdexcept>\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";