llvm.org GIT mirror llvm / 4f6e3a4
Make ChooseEdge more generic and use it to choose between different toolchains. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@50741 91177308-0d34-0410-b5e6-96231b3b80d8 Mikhail Glushenkov 12 years ago
2 changed file(s) with 58 addition(s) and 40 deletion(s). Raw diff Collapse all Expand all
2424 extern cl::list InputFilenames;
2525 extern cl::opt OutputFilename;
2626
27 // Choose one of the edges based on command-line options.
28 const Edge* Node::ChooseEdge() const {
29 const Edge* DefaultEdge = 0;
30 for (const_iterator B = EdgesBegin(), E = EdgesEnd();
31 B != E; ++B) {
32 const Edge* E = (*B).getPtr();
33 if (E->isDefault())
34 if (!DefaultEdge)
35 DefaultEdge = E;
36 else
37 throw std::runtime_error("Node " + Name() +
38 ": multiple default edges found!"
39 "Most probably a specification error.");
40 if (E->isEnabled())
41 return E;
42 }
43
44 if (DefaultEdge)
45 return DefaultEdge;
46 else
47 throw std::runtime_error("Node " + Name() +
48 ": no suitable edge found! "
49 "Most probably a specification error.");
27 namespace {
28
29 // Choose edge that returns
30 template
31 const Edge* ChooseEdge(const C& EdgesContainer,
32 const std::string& NodeName = "root") {
33 const Edge* DefaultEdge = 0;
34
35 for (typename C::const_iterator B = EdgesContainer.begin(),
36 E = EdgesContainer.end(); B != E; ++B) {
37 const Edge* E = B->getPtr();
38
39 if (E->isDefault())
40 if (!DefaultEdge)
41 DefaultEdge = E;
42 else
43 throw std::runtime_error("Node " + NodeName
44 + ": multiple default outward edges found!"
45 "Most probably a specification error.");
46 if (E->isEnabled())
47 return E;
48 }
49
50 if (DefaultEdge)
51 return DefaultEdge;
52 else
53 throw std::runtime_error("Node " + NodeName
54 + ": no default outward edge found!"
55 "Most probably a specification error.");
56 }
57
5058 }
5159
5260 CompilationGraph::CompilationGraph() {
97105 Node& B = getNode(E->ToolName());
98106 if (A == "root") {
99107 const std::string& InputLanguage = B.ToolPtr->InputLanguage();
100 ToolsMap[InputLanguage].push_back(E->ToolName());
108 ToolsMap[InputLanguage].push_back(IntrusiveRefCntPtr(E));
101109 NodesMap["root"].AddEdge(E);
102110 }
103111 else {
112120 // a node that says that it is the last.
113121 const JoinTool*
114122 CompilationGraph::PassThroughGraph (sys::Path& In,
123 const Node* StartNode,
115124 const sys::Path& TempDir) const {
116125 bool Last = false;
126 const Node* CurNode = StartNode;
117127 JoinTool* ret = 0;
118
119 // Get to the head of the toolchain.
120 const tools_vector_type& TV = getToolsVector(getLanguage(In));
121 if (TV.empty())
122 throw std::runtime_error("Tool names vector is empty!");
123 const Node* N = &getNode(*TV.begin());
124128
125129 while(!Last) {
126130 sys::Path Out;
127 Tool* CurTool = N->ToolPtr.getPtr();
131 Tool* CurTool = CurNode->ToolPtr.getPtr();
128132
129133 if (CurTool->IsJoin()) {
130134 ret = &dynamic_cast(*CurTool);
133137 }
134138
135139 // Is this the last tool?
136 if (!N->HasChildren() || CurTool->IsLast()) {
140 if (!CurNode->HasChildren() || CurTool->IsLast()) {
137141 // Check if the first tool is also the last
138142 if (Out.empty())
139143 Out.set(In.getBasename());
153157 if (CurTool->GenerateAction(In, Out).Execute() != 0)
154158 throw std::runtime_error("Tool returned error code!");
155159
156 N = &getNode(N->ChooseEdge()->ToolName());
160 CurNode = &getNode(ChooseEdge(CurNode->OutEdges,
161 CurNode->Name())->ToolName());
157162 In = Out; Out.clear();
158163 }
159164
163168 int CompilationGraph::Build (const sys::Path& TempDir) const {
164169 const JoinTool* JT = 0;
165170
166 // For each input file
171 // For each input file:
167172 for (cl::list::const_iterator B = InputFilenames.begin(),
168173 E = InputFilenames.end(); B != E; ++B) {
169174 sys::Path In = sys::Path(*B);
170175
171 const JoinTool* NewJoin = PassThroughGraph(In, TempDir);
176 // Get to the head of the toolchain.
177 const std::string& InLanguage = getLanguage(In);
178 const tools_vector_type& TV = getToolsVector(InLanguage);
179 if (TV.empty())
180 throw std::runtime_error("No toolchain corresponding to language"
181 + InLanguage + " found!");
182 const Node* N = &getNode(ChooseEdge(TV)->ToolName());
183
184 // Pass it through the chain starting at head.
185 const JoinTool* NewJoin = PassThroughGraph(In, N, TempDir);
172186 if (JT && NewJoin && JT != NewJoin)
173187 throw std::runtime_error("Graphs with multiple Join nodes"
174188 "are not yet supported!");
176190 JT = NewJoin;
177191 }
178192
193 // For all join nodes in topological order:
194 // TOFIX: implement.
179195 if (JT) {
180196 sys::Path Out;
181197 // If the final output name is empty, set it to "a.out"
6767 const_iterator EdgesBegin() const { return OutEdges.begin(); }
6868 iterator EdgesEnd() { return OutEdges.end(); }
6969 const_iterator EdgesEnd() const { return OutEdges.end(); }
70
71 // Choose one of the outward edges based on command-line options.
72 const Edge* ChooseEdge() const;
7370
7471 // Add an outward edge. Takes ownership of the Edge object.
7572 void AddEdge(Edge* E)
9491 class NodesIterator;
9592
9693 class CompilationGraph {
97 typedef llvm::SmallVector tools_vector_type;
94 // Main data structure.
95 typedef llvm::StringMap nodes_map_type;
96 // These are used to map from language names-> tools. (We can have
97 // several tools associated with each language name.)
98 typedef
99 llvm::SmallVector, 3> tools_vector_type;
98100 typedef llvm::StringMap tools_map_type;
99 typedef llvm::StringMap nodes_map_type;
100101
101102 // Map from file extensions to language names.
102103 LanguageMap ExtsToLangs;
153154
154155 // Pass the input file through the toolchain.
155156 const JoinTool* PassThroughGraph (llvm::sys::Path& In,
157 const Node* StartNode,
156158 const llvm::sys::Path& TempDir) const;
157159
158160 };