forked from OSchip/llvm-project
Make it possible to have multiple input languages for a single tool.
llvm-svn: 51742
This commit is contained in:
parent
73d708b82c
commit
1f7a028929
|
@ -115,16 +115,18 @@ void CompilationGraph::insertNode(Tool* V) {
|
|||
}
|
||||
}
|
||||
|
||||
void CompilationGraph::insertEdge(const std::string& A, Edge* E) {
|
||||
Node& B = getNode(E->ToolName());
|
||||
void CompilationGraph::insertEdge(const std::string& A, Edge* Edg) {
|
||||
Node& B = getNode(Edg->ToolName());
|
||||
if (A == "root") {
|
||||
const std::string& InputLanguage = B.ToolPtr->InputLanguage();
|
||||
ToolsMap[InputLanguage].push_back(IntrusiveRefCntPtr<Edge>(E));
|
||||
NodesMap["root"].AddEdge(E);
|
||||
const StrVector& InputLanguages = B.ToolPtr->InputLanguages();
|
||||
for (StrVector::const_iterator B = InputLanguages.begin(),
|
||||
E = InputLanguages.end(); B != E; ++B)
|
||||
ToolsMap[*B].push_back(IntrusiveRefCntPtr<Edge>(Edg));
|
||||
NodesMap["root"].AddEdge(Edg);
|
||||
}
|
||||
else {
|
||||
Node& N = getNode(A);
|
||||
N.AddEdge(E);
|
||||
N.AddEdge(Edg);
|
||||
}
|
||||
// Increase the inward edge counter.
|
||||
B.IncrInEdges();
|
||||
|
@ -381,10 +383,23 @@ namespace llvm {
|
|||
|
||||
template<typename EdgeIter>
|
||||
static std::string getEdgeSourceLabel(const Node* N, EdgeIter I) {
|
||||
if (N->ToolPtr)
|
||||
if (N->ToolPtr) {
|
||||
return N->ToolPtr->OutputLanguage();
|
||||
}
|
||||
else {
|
||||
const StrVector& InputLanguages = I->ToolPtr->InputLanguages();
|
||||
std::string ret;
|
||||
|
||||
for (StrVector::const_iterator B = InputLanguages.begin(),
|
||||
E = InputLanguages.end(); B != E; ++B) {
|
||||
if (llvm::next(B) != E)
|
||||
ret += *B + ", ";
|
||||
else
|
||||
return I->ToolPtr->InputLanguage();
|
||||
ret += *B;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@ namespace llvmc {
|
|||
const InputLanguagesSet& InLangs) const = 0;
|
||||
|
||||
virtual const char* Name() const = 0;
|
||||
virtual const char* InputLanguage() const = 0;
|
||||
virtual StrVector InputLanguages() const = 0;
|
||||
virtual const char* OutputLanguage() const = 0;
|
||||
virtual const char* OutputSuffix() const = 0;
|
||||
|
||||
|
|
|
@ -4,12 +4,8 @@
|
|||
|
||||
include "Common.td"
|
||||
|
||||
// TOFIX: It should be possible to use a string list in the 'in_language'
|
||||
// tool property. There should be also an 'in_language' test in the
|
||||
// 'case' construct.
|
||||
|
||||
def clang : Tool<
|
||||
[(in_language "c"),
|
||||
[(in_language ["c", "c++", "objective-c"]),
|
||||
(out_language "llvm-bitcode"),
|
||||
(output_suffix "bc"),
|
||||
(cmd_line (case (switch_on "E"), "clang -E $INFILE -o $OUTFILE",
|
||||
|
|
|
@ -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 @@ const char * SinkOptionName = "AutoGeneratedSinkOption";
|
|||
//===----------------------------------------------------------------------===//
|
||||
/// 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 @@ namespace ToolFlags {
|
|||
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 @@ public:
|
|||
/// 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 @@ private:
|
|||
|
||||
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 @@ private:
|
|||
|
||||
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 @@ void EmitLogicalOperationTest(const DagInit& d, const char* LogicOp,
|
|||
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 @@ void EmitCaseConstructHandler(const DagInit* d, const char* IndentLevel,
|
|||
+ 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 @@ void EmitGenerateActionMethod (const ToolProperties& P,
|
|||
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 @@ void EmitIsLastMethod (const ToolProperties& P, std::ostream& O) {
|
|||
/// 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 @@ void EmitPopulateLanguageMap (const RecordKeeper& Records, std::ostream& O)
|
|||
/// 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 @@ void TypecheckGraph (Record* CompilationGraph,
|
|||
/// 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 @@ void FillInHookNames(const ToolPropertiesList& TPList,
|
|||
}
|
||||
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) {
|
||||
|
|
Loading…
Reference in New Issue