summaryrefslogtreecommitdiff
path: root/utils/TableGen/LLVMCConfigurationEmitter.cpp
diff options
context:
space:
mode:
authorMikhail Glushenkov <foldr@codedgers.com>2008-05-30 06:12:24 +0000
committerMikhail Glushenkov <foldr@codedgers.com>2008-05-30 06:12:24 +0000
commit08bd2e74dc542ab4e7484f1d61e22f6fd96c48ed (patch)
treea63cd3e3b53ababa63827911f79bd63aa1768b98 /utils/TableGen/LLVMCConfigurationEmitter.cpp
parent4eaa389519d3afa02db7e2e66c9544e17e2122e7 (diff)
downloadllvm-08bd2e74dc542ab4e7484f1d61e22f6fd96c48ed.tar.gz
llvm-08bd2e74dc542ab4e7484f1d61e22f6fd96c48ed.tar.bz2
llvm-08bd2e74dc542ab4e7484f1d61e22f6fd96c48ed.tar.xz
Add support for user-provided hooks and environment variable reads to the cmd_line tool property.
Used like this: (cmd_line "$CALL(MyHook) --option -o $ENV(VARIABLE) $CALL(AnotherHook)") Also works with case expressions. Hook declarations are auto-generated, the definitions should be provided by the user (just drop a .cpp file in the tools/llvmc2 directory). Hooks should live in the "hooks" namespace and have type std::string hooks::Hook(void). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@51732 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'utils/TableGen/LLVMCConfigurationEmitter.cpp')
-rw-r--r--utils/TableGen/LLVMCConfigurationEmitter.cpp129
1 files changed, 113 insertions, 16 deletions
diff --git a/utils/TableGen/LLVMCConfigurationEmitter.cpp b/utils/TableGen/LLVMCConfigurationEmitter.cpp
index 2bac7036e2..d160412cfa 100644
--- a/utils/TableGen/LLVMCConfigurationEmitter.cpp
+++ b/utils/TableGen/LLVMCConfigurationEmitter.cpp
@@ -845,12 +845,32 @@ void EmitOptionPropertyHandlingCode (const ToolOptionDescription& D,
O << Indent2 << "}\n";
}
+/// SubstituteSpecialCommands - Perform string substitution for $CALL
+/// and $ENV. Helper function used by EmitCmdLineVecFill().
+std::string SubstituteSpecialCommands(const std::string& cmd) {
+ if (cmd.find("$CALL(") == 0) {
+ if (cmd.size() == 6)
+ throw std::string("$CALL invocation: empty argument list!");
+ return std::string("hooks::") + (cmd.c_str() + 6) + "()";
+ }
+ else if (cmd.find("$ENV(") == 0) {
+ if (cmd.size() == 5)
+ throw std::string("$ENV invocation: empty argument list!");
+ return std::string("std::getenv(\"") + (cmd.c_str() + 5) + "\")";
+ }
+ else {
+ throw "Unknown special command: " + cmd;
+ }
+}
+
+/// EmitCmdLineVecFill - Emit code that fills in the command line
+/// vector. Helper function used by EmitGenerateActionMethod().
void EmitCmdLineVecFill(const Init* CmdLine, const std::string& ToolName,
bool Version, const char* IndentLevel,
std::ostream& O) {
StrVector StrVec;
- SplitString(InitPtrToString(CmdLine), StrVec);
- if (InitPtrToString(CmdLine).empty())
+ SplitString(InitPtrToString(CmdLine), StrVec, ") ");
+ if (StrVec.empty())
throw "Tool " + ToolName + " has empty command line!";
StrVector::const_iterator I = StrVec.begin();
@@ -858,25 +878,36 @@ void EmitCmdLineVecFill(const Init* CmdLine, const std::string& ToolName,
for (StrVector::const_iterator E = StrVec.end(); I != E; ++I) {
const std::string& cmd = *I;
O << IndentLevel;
- if (cmd == "$INFILE") {
- if (Version)
- O << "for (PathVector::const_iterator B = inFiles.begin()"
- << ", E = inFiles.end();\n"
- << IndentLevel << "B != E; ++B)\n"
- << IndentLevel << Indent1 << "vec.push_back(B->toString());\n";
- else
- O << "vec.push_back(inFile.toString());\n";
- }
- else if (cmd == "$OUTFILE") {
- O << "vec.push_back(outFile.toString());\n";
+ if (cmd.at(0) == '$') {
+ if (cmd == "$INFILE") {
+ if (Version)
+ O << "for (PathVector::const_iterator B = inFiles.begin()"
+ << ", E = inFiles.end();\n"
+ << IndentLevel << "B != E; ++B)\n"
+ << IndentLevel << Indent1 << "vec.push_back(B->toString());\n";
+ else
+ O << "vec.push_back(inFile.toString());\n";
+ }
+ else if (cmd == "$OUTFILE") {
+ O << "vec.push_back(outFile.toString());\n";
+ }
+ else {
+ O << "vec.push_back(" << SubstituteSpecialCommands(cmd) << ");\n";
+ }
}
else {
O << "vec.push_back(\"" << cmd << "\");\n";
}
}
- O << IndentLevel << "ret = Action(\"" << StrVec.at(0) << "\", vec);\n";
+ O << IndentLevel << "ret = Action("
+ << ((StrVec[0][0] == '$') ? SubstituteSpecialCommands(StrVec[0])
+ : "\"" + StrVec[0] + "\"")
+ << ", vec);\n";
}
+/// EmitCmdLineVecFillCallback - A function object wrapper around
+/// EmitCmdLineVecFill(). Used by EmitGenerateActionMethod() as an
+/// argument to EmitCaseConstructHandler().
class EmitCmdLineVecFillCallback {
bool Version;
const std::string& ToolName;
@@ -1150,7 +1181,8 @@ void TypecheckGraph (Record* CompilationGraph,
}
}
-// Helper function passed to EmitCaseConstructHandler by EmitEdgeClass.
+/// IncDecWeight - Helper function passed to EmitCaseConstructHandler()
+/// by EmitEdgeClass().
void IncDecWeight (const Init* i, const char* IndentLevel,
std::ostream& O) {
const DagInit& d = InitPtrToDagInitRef(i);
@@ -1192,7 +1224,7 @@ void EmitEdgeClass (unsigned N, const std::string& Target,
<< Indent1 << "};\n\n};\n\n";
}
-// Emit Edge* classes that represent graph edges.
+/// EmitEdgeClasses - Emit Edge* classes that represent graph edges.
void EmitEdgeClasses (Record* CompilationGraph,
const GlobalOptionDescriptions& OptDescs,
std::ostream& O) {
@@ -1256,6 +1288,68 @@ void EmitPopulateCompilationGraph (Record* CompilationGraph,
O << "}\n\n";
}
+/// ExtractHookNames - Extract the hook names from all instances of
+/// $CALL(HookName) in the provided command line string. Helper
+/// function used by FillInHookNames().
+void ExtractHookNames(const Init* CmdLine, StrVector& HookNames) {
+ StrVector cmds;
+ llvm::SplitString(InitPtrToString(CmdLine), cmds, ") ");
+ for (StrVector::const_iterator B = cmds.begin(), E = cmds.end();
+ B != E; ++B) {
+ const std::string& cmd = *B;
+ if (cmd.find("$CALL(") == 0) {
+ if (cmd.size() == 6)
+ throw std::string("$CALL invocation: empty argument list!");
+ HookNames.push_back(std::string(cmd.c_str() + 6));
+ }
+ }
+}
+
+/// FillInHookNames - Actually extract the hook names from all command
+/// line strings. Helper function used by EmitHookDeclarations().
+void FillInHookNames(const ToolPropertiesList& TPList,
+ StrVector& HookNames) {
+ for (ToolPropertiesList::const_iterator B = TPList.begin(),
+ E = TPList.end(); B != E; ++B) {
+ const ToolProperties& P = *(*B);
+ if (!P.CmdLine)
+ continue;
+ if (typeid(*P.CmdLine) == typeid(StringInit)) {
+ // This is a string.
+ ExtractHookNames(P.CmdLine, HookNames);
+ }
+ else {
+ // This is a 'case' construct.
+ const DagInit& d = InitPtrToDagInitRef(P.CmdLine);
+ bool even = false;
+ for (DagInit::const_arg_iterator B = d.arg_begin(), E = d.arg_end();
+ B != E; ++B) {
+ if (even)
+ ExtractHookNames(*B, HookNames);
+ even = !even;
+ }
+ }
+ }
+}
+
+/// EmitHookDeclarations - Parse CmdLine fields of all the tool
+/// property records and emit hook function declaration for each
+/// instance of $CALL(HookName).
+void EmitHookDeclarations(const ToolPropertiesList& ToolProps,
+ std::ostream& O) {
+ StrVector HookNames;
+ FillInHookNames(ToolProps, HookNames);
+ if (HookNames.empty())
+ return;
+ std::sort(HookNames.begin(), HookNames.end());
+ StrVector::const_iterator E = std::unique(HookNames.begin(), HookNames.end());
+
+ O << "namespace hooks {\n";
+ for (StrVector::const_iterator B = HookNames.begin(); B != E; ++B)
+ O << Indent1 << "std::string " << *B << "();\n";
+
+ O << "}\n\n";
+}
// End of anonymous namespace
}
@@ -1279,6 +1373,9 @@ void LLVMCConfigurationEmitter::run (std::ostream &O) {
// Emit global option registration code.
EmitOptionDescriptions(opt_descs, O);
+ // Emit hook declarations.
+ EmitHookDeclarations(tool_props, O);
+
// Emit PopulateLanguageMap() function
// (a language map maps from file extensions to language names).
EmitPopulateLanguageMap(Records, O);