+ bool operator()(const IntrusiveRefCntPtr<ToolDescription>& x) {
+ return (ToolsInGraph_.count(x->Name) == 0);
+ }
+};
+
+/// FilterNotInGraph - Filter out from ToolDescs all Tools not
+/// mentioned in the compilation graph definition.
+void FilterNotInGraph (const DagVector& EdgeVector,
+ ToolDescriptions& ToolDescs) {
+
+ // List all tools mentioned in the graph.
+ llvm::StringSet<> ToolsInGraph;
+
+ for (DagVector::const_iterator B = EdgeVector.begin(),
+ E = EdgeVector.end(); B != E; ++B) {
+
+ const DagInit* Edge = *B;
+ const std::string& NodeA = InitPtrToString(Edge->getArg(0));
+ const std::string& NodeB = InitPtrToString(Edge->getArg(1));
+
+ if (NodeA != "root")
+ ToolsInGraph.insert(NodeA);
+ ToolsInGraph.insert(NodeB);
+ }
+
+ // Filter ToolPropertiesList.
+ ToolDescriptions::iterator new_end =
+ std::remove_if(ToolDescs.begin(), ToolDescs.end(),
+ NotInGraph(ToolsInGraph));
+ ToolDescs.erase(new_end, ToolDescs.end());
+}
+
+/// FillInToolToLang - Fills in two tables that map tool names to
+/// input & output language names. Helper function used by TypecheckGraph().
+void FillInToolToLang (const ToolDescriptions& ToolDescs,
+ StringMap<StringSet<> >& ToolToInLang,
+ StringMap<StringSet<> >& ToolToOutLang) {
+ for (ToolDescriptions::const_iterator B = ToolDescs.begin(),
+ E = ToolDescs.end(); B != E; ++B) {
+ const ToolDescription& D = *(*B);
+ for (StrVector::const_iterator B = D.InLanguage.begin(),
+ E = D.InLanguage.end(); B != E; ++B)
+ ToolToInLang[D.Name].insert(*B);
+ for (StrVector::const_iterator B = D.OutLanguage.begin(),
+ E = D.OutLanguage.end(); B != E; ++B)
+ ToolToOutLang[D.Name].insert(*B);
+ }
+}
+
+/// Intersect - Is set intersection non-empty?
+bool Intersect (const StringSet<>& S1, const StringSet<>& S2) {
+ for (StringSet<>::const_iterator B = S1.begin(), E = S1.end(); B != E; ++B) {
+ if (S2.count(B->first()) != 0)
+ return true;
+ }
+ return false;
+}
+
+/// TypecheckGraph - Check that names for output and input languages
+/// on all edges do match.
+void TypecheckGraph (const DagVector& EdgeVector,
+ const ToolDescriptions& ToolDescs) {
+ StringMap<StringSet<> > ToolToInLang;
+ StringMap<StringSet<> > ToolToOutLang;
+
+ FillInToolToLang(ToolDescs, ToolToInLang, ToolToOutLang);
+
+ for (DagVector::const_iterator B = EdgeVector.begin(),
+ E = EdgeVector.end(); B != E; ++B) {
+ const DagInit* Edge = *B;
+ const std::string& NodeA = InitPtrToString(Edge->getArg(0));
+ const std::string& NodeB = InitPtrToString(Edge->getArg(1));
+ StringMap<StringSet<> >::iterator IA = ToolToOutLang.find(NodeA);
+ StringMap<StringSet<> >::iterator IB = ToolToInLang.find(NodeB);
+
+ if (NodeB == "root")
+ throw "Edges back to the root are not allowed!";
+
+ if (NodeA != "root") {
+ if (IA == ToolToOutLang.end())
+ throw NodeA + ": no output language defined!";
+ if (IB == ToolToInLang.end())
+ throw NodeB + ": no input language defined!";
+
+ if (!Intersect(IA->second, IB->second)) {
+ throw "Edge " + NodeA + "->" + NodeB
+ + ": output->input language mismatch";
+ }
+ }
+ }
+}
+
+/// WalkCase - Walks the 'case' expression DAG and invokes
+/// TestCallback on every test, and StatementCallback on every
+/// statement. Handles 'case' nesting, but not the 'and' and 'or'
+/// combinators (that is, they are passed directly to TestCallback).
+/// TestCallback must have type 'void TestCallback(const DagInit*, unsigned
+/// IndentLevel, bool FirstTest)'.
+/// StatementCallback must have type 'void StatementCallback(const Init*,
+/// unsigned IndentLevel)'.
+template <typename F1, typename F2>
+void WalkCase(const Init* Case, F1 TestCallback, F2 StatementCallback,
+ unsigned IndentLevel = 0)