Make it possible to have multiple input languages for a single tool.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@51742 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/utils/TableGen/LLVMCConfigurationEmitter.cpp b/utils/TableGen/LLVMCConfigurationEmitter.cpp
index d3ad22c..68548d6 100644
--- a/utils/TableGen/LLVMCConfigurationEmitter.cpp
+++ b/utils/TableGen/LLVMCConfigurationEmitter.cpp
@@ -18,6 +18,7 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringSet.h"
#include "llvm/Support/Streams.h"
#include <algorithm>
@@ -53,17 +54,22 @@
//===----------------------------------------------------------------------===//
/// Helper functions
-const std::string& InitPtrToString(const Init* ptr) {
- const StringInit& val = dynamic_cast<const StringInit&>(*ptr);
- return val.getValue();
-}
-
int InitPtrToInt(const Init* ptr) {
const IntInit& val = dynamic_cast<const IntInit&>(*ptr);
return val.getValue();
}
-const DagInit& InitPtrToDagInitRef(const Init* ptr) {
+const std::string& InitPtrToString(const Init* ptr) {
+ const StringInit& val = dynamic_cast<const StringInit&>(*ptr);
+ return val.getValue();
+}
+
+const ListInit& InitPtrToList(const Init* ptr) {
+ const ListInit& val = dynamic_cast<const ListInit&>(*ptr);
+ return val;
+}
+
+const DagInit& InitPtrToDag(const Init* ptr) {
const DagInit& val = dynamic_cast<const DagInit&>(*ptr);
return val;
}
@@ -308,7 +314,7 @@
struct ToolProperties : public RefCountedBase<ToolProperties> {
std::string Name;
Init* CmdLine;
- std::string InLanguage;
+ StrVector InLanguage;
std::string OutLanguage;
std::string OutputSuffix;
unsigned Flags;
@@ -412,7 +418,7 @@
/// operator() - Gets called for every tool property; Just forwards
/// to the corresponding property handler.
void operator() (Init* i) {
- const DagInit& d = InitPtrToDagInitRef(i);
+ const DagInit& d = InitPtrToDag(i);
const std::string& property_name = d.getOperator()->getAsString();
PropertyHandlerMap::iterator method
= propertyHandlers_.find(property_name);
@@ -439,7 +445,29 @@
void onInLanguage (const DagInit* d) {
checkNumberOfArguments(d, 1);
- toolProps_.InLanguage = InitPtrToString(d->getArg(0));
+ Init* arg = d->getArg(0);
+
+ // Find out the argument's type.
+ if (typeid(*arg) == typeid(StringInit)) {
+ // It's a string.
+ toolProps_.InLanguage.push_back(InitPtrToString(arg));
+ }
+ else {
+ // It's a list.
+ const ListInit& lst = InitPtrToList(arg);
+ StrVector& out = toolProps_.InLanguage;
+
+ // Copy strings to the output vector.
+ for (ListInit::const_iterator B = lst.begin(), E = lst.end();
+ B != E; ++B) {
+ out.push_back(InitPtrToString(*B));
+ }
+
+ // Remove duplicates.
+ std::sort(out.begin(), out.end());
+ StrVector::iterator newE = std::unique(out.begin(), out.end());
+ out.erase(newE, out.end());
+ }
}
void onJoin (const DagInit* d) {
@@ -573,7 +601,7 @@
for (unsigned B = 1, E = d->getNumArgs(); B!=E; ++B) {
const DagInit& option_property
- = InitPtrToDagInitRef(d->getArg(B));
+ = InitPtrToDag(d->getArg(B));
const std::string& option_property_name
= option_property.getOperator()->getAsString();
OptionPropertyHandlerMap::iterator method
@@ -691,7 +719,7 @@
std::ostream& O) {
O << '(';
for (unsigned j = 0, NumArgs = d.getNumArgs(); j < NumArgs; ++j) {
- const DagInit& InnerTest = InitPtrToDagInitRef(d.getArg(j));
+ const DagInit& InnerTest = InitPtrToDag(d.getArg(j));
EmitCaseTest(InnerTest, IndentLevel, OptDescs, O);
if (j != NumArgs - 1)
O << ")\n" << IndentLevel << Indent1 << ' ' << LogicOp << " (";
@@ -736,7 +764,7 @@
+ d->getAsString();
for (unsigned i = 0; i != numArgs; ++i) {
- const DagInit& Test = InitPtrToDagInitRef(d->getArg(i));
+ const DagInit& Test = InitPtrToDag(d->getArg(i));
// Emit the test.
if (Test.getOperator()->getAsString() == "default") {
@@ -996,7 +1024,7 @@
if (typeid(*P.CmdLine) == typeid(StringInit))
EmitCmdLineVecFill(P.CmdLine, P.Name, Version, Indent2, O);
else
- EmitCaseConstructHandler(&InitPtrToDagInitRef(P.CmdLine), Indent2,
+ EmitCaseConstructHandler(&InitPtrToDag(P.CmdLine), Indent2,
EmitCmdLineVecFillCallback(Version, P.Name),
true, OptDescs, O);
@@ -1061,8 +1089,15 @@
/// EmitInOutLanguageMethods - Emit the [Input,Output]Language()
/// methods for a given Tool class.
void EmitInOutLanguageMethods (const ToolProperties& P, std::ostream& O) {
- O << Indent1 << "const char* InputLanguage() const {\n"
- << Indent2 << "return \"" << P.InLanguage << "\";\n"
+ O << Indent1 << "StrVector InputLanguages() const {\n"
+ << Indent2 << "StrVector ret;\n";
+
+ for (StrVector::const_iterator B = P.InLanguage.begin(),
+ E = P.InLanguage.end(); B != E; ++B) {
+ O << Indent2 << "ret.push_back(\"" << *B << "\");\n";
+ }
+
+ O << Indent2 << "return ret;\n"
<< Indent1 << "}\n\n";
O << Indent1 << "const char* OutputLanguage() const {\n"
@@ -1207,41 +1242,47 @@
/// FillInToolToLang - Fills in two tables that map tool names to
/// (input, output) languages. Used by the typechecker.
void FillInToolToLang (const ToolPropertiesList& TPList,
- StringMap<std::string>& ToolToInLang,
+ StringMap<StringSet<> >& ToolToInLang,
StringMap<std::string>& ToolToOutLang) {
for (ToolPropertiesList::const_iterator B = TPList.begin(), E = TPList.end();
B != E; ++B) {
const ToolProperties& P = *(*B);
- ToolToInLang[P.Name] = P.InLanguage;
+ for (StrVector::const_iterator B = P.InLanguage.begin(),
+ E = P.InLanguage.end(); B != E; ++B)
+ ToolToInLang[P.Name].insert(*B);
ToolToOutLang[P.Name] = P.OutLanguage;
}
}
/// TypecheckGraph - Check that names for output and input languages
/// on all edges do match.
-// TOFIX: check for cycles.
-// TOFIX: check for multiple default edges.
+// TOFIX: It would be nice if this function also checked for cycles
+// and multiple default edges in the graph (better error
+// reporting). Unfortunately, it is awkward to do right now because
+// our intermediate representation is not sufficiently
+// sofisticated. Algorithms like these should be run on a real graph
+// instead of AST.
void TypecheckGraph (Record* CompilationGraph,
const ToolPropertiesList& TPList) {
- StringMap<std::string> ToolToInLang;
+ StringMap<StringSet<> > ToolToInLang;
StringMap<std::string> ToolToOutLang;
FillInToolToLang(TPList, ToolToInLang, ToolToOutLang);
ListInit* edges = CompilationGraph->getValueAsListInit("edges");
- StringMap<std::string>::iterator IAE = ToolToInLang.end();
- StringMap<std::string>::iterator IBE = ToolToOutLang.end();
+ StringMap<std::string>::iterator IAE = ToolToOutLang.end();
+ StringMap<StringSet<> >::iterator IBE = ToolToInLang.end();
for (unsigned i = 0; i < edges->size(); ++i) {
Record* Edge = edges->getElementAsRecord(i);
Record* A = Edge->getValueAsDef("a");
Record* B = Edge->getValueAsDef("b");
StringMap<std::string>::iterator IA = ToolToOutLang.find(A->getName());
- StringMap<std::string>::iterator IB = ToolToInLang.find(B->getName());
+ StringMap<StringSet<> >::iterator IB = ToolToInLang.find(B->getName());
if (IA == IAE)
throw A->getName() + ": no such tool!";
if (IB == IBE)
throw B->getName() + ": no such tool!";
- if (A->getName() != "root" && IA->second != IB->second)
+ if (A->getName() != "root" && IB->second.count(IA->second) == 0)
throw "Edge " + A->getName() + "->" + B->getName()
+ ": output->input language mismatch";
if (B->getName() == "root")
@@ -1253,7 +1294,7 @@
/// by EmitEdgeClass().
void IncDecWeight (const Init* i, const char* IndentLevel,
std::ostream& O) {
- const DagInit& d = InitPtrToDagInitRef(i);
+ const DagInit& d = InitPtrToDag(i);
const std::string& OpName = d.getOperator()->getAsString();
if (OpName == "inc_weight")
@@ -1389,7 +1430,7 @@
}
else {
// This is a 'case' construct.
- const DagInit& d = InitPtrToDagInitRef(P.CmdLine);
+ const DagInit& d = InitPtrToDag(P.CmdLine);
bool even = false;
for (DagInit::const_arg_iterator B = d.arg_begin(), E = d.arg_end();
B != E; ++B) {