summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--test/LLVMC/false.c2
-rw-r--r--test/LLVMC/hello.cpp2
-rw-r--r--tools/llvmc2/Common.td4
-rw-r--r--tools/llvmc2/CompilationGraph.cpp32
-rw-r--r--tools/llvmc2/CompilationGraph.h12
-rw-r--r--tools/llvmc2/Example.td10
-rw-r--r--utils/TableGen/LLVMCConfigurationEmitter.cpp74
7 files changed, 94 insertions, 42 deletions
diff --git a/test/LLVMC/false.c b/test/LLVMC/false.c
index 8319036c36..69b400c59b 100644
--- a/test/LLVMC/false.c
+++ b/test/LLVMC/false.c
@@ -1,5 +1,5 @@
// Test that we can compile .c files as C++ and vice versa
-// RUN: llvmc2 --linker=c++ -x c++ %s -x c %p/false.cpp -x lisp -x whatnot -x none %p/false2.cpp -o %t
+// RUN: llvmc2 -x c++ %s -x c %p/false.cpp -x lisp -x whatnot -x none %p/false2.cpp -o %t
// RUN: ./%t | grep hello
#include <iostream>
diff --git a/test/LLVMC/hello.cpp b/test/LLVMC/hello.cpp
index 4b45ea945e..a3148c3c16 100644
--- a/test/LLVMC/hello.cpp
+++ b/test/LLVMC/hello.cpp
@@ -1,5 +1,5 @@
// Test that we can compile C++ code.
-// RUN: llvmc2 --linker=c++ %s -o %t
+// RUN: llvmc2 %s -o %t
// RUN: ./%t | grep hello
#include <iostream>
diff --git a/tools/llvmc2/Common.td b/tools/llvmc2/Common.td
index 5e25dcf2f9..db28841afb 100644
--- a/tools/llvmc2/Common.td
+++ b/tools/llvmc2/Common.td
@@ -50,7 +50,11 @@ def required;
def switch_on;
def parameter_equals;
def element_in_list;
+def if_input_languages_contain;
+
+// Edge property combinators.
def and;
+def or;
// Map from suffixes to language names
diff --git a/tools/llvmc2/CompilationGraph.cpp b/tools/llvmc2/CompilationGraph.cpp
index 310413b9f0..f5cefbf0a9 100644
--- a/tools/llvmc2/CompilationGraph.cpp
+++ b/tools/llvmc2/CompilationGraph.cpp
@@ -20,6 +20,7 @@
#include <algorithm>
#include <iterator>
+#include <iostream>
#include <limits>
#include <queue>
#include <stdexcept>
@@ -36,6 +37,7 @@ namespace {
// Return the edge with the maximum weight.
template <class C>
const Edge* ChooseEdge(const C& EdgesContainer,
+ const InputLanguagesSet& InLangs,
const std::string& NodeName = "root") {
const Edge* MaxEdge = 0;
unsigned MaxWeight = 0;
@@ -44,7 +46,7 @@ namespace {
for (typename C::const_iterator B = EdgesContainer.begin(),
E = EdgesContainer.end(); B != E; ++B) {
const Edge* E = B->getPtr();
- unsigned EW = E->Weight();
+ unsigned EW = E->Weight(InLangs);
if (EW > MaxWeight) {
MaxEdge = E;
MaxWeight = EW;
@@ -142,6 +144,7 @@ namespace {
// a node that says that it is the last.
void CompilationGraph::PassThroughGraph (const sys::Path& InFile,
const Node* StartNode,
+ const InputLanguagesSet& InLangs,
const sys::Path& TempDir) const {
bool Last = false;
sys::Path In = InFile;
@@ -180,6 +183,7 @@ void CompilationGraph::PassThroughGraph (const sys::Path& InFile,
return;
CurNode = &getNode(ChooseEdge(CurNode->OutEdges,
+ InLangs,
CurNode->Name())->ToolName());
In = Out; Out.clear();
}
@@ -221,21 +225,32 @@ TopologicalSortFilterJoinNodes(std::vector<const Node*>& Out) {
}
// Find head of the toolchain corresponding to the given file.
+// Also, insert an input language into InLangs.
const Node* CompilationGraph::
-FindToolChain(const sys::Path& In, const std::string* forceLanguage) const {
+FindToolChain(const sys::Path& In, const std::string* forceLanguage,
+ InputLanguagesSet& InLangs) const {
+
+ // Determine the input language.
const std::string& InLanguage =
forceLanguage ? *forceLanguage : getLanguage(In);
+
+ // Add the current input language to the input language set.
+ InLangs.insert(InLanguage);
+
+ // Find the toolchain for the input language.
const tools_vector_type& TV = getToolsVector(InLanguage);
if (TV.empty())
throw std::runtime_error("No toolchain corresponding to language"
+ InLanguage + " found!");
- return &getNode(ChooseEdge(TV)->ToolName());
+ return &getNode(ChooseEdge(TV, InLangs)->ToolName());
}
// Build the targets. Command-line options are passed through
// temporary variables.
int CompilationGraph::Build (const sys::Path& TempDir) {
+ InputLanguagesSet InLangs;
+
// This is related to -x option handling.
cl::list<std::string>::const_iterator xIter = Languages.begin(),
xBegin = xIter, xEnd = Languages.end();
@@ -284,9 +299,9 @@ int CompilationGraph::Build (const sys::Path& TempDir) {
}
// Find the toolchain corresponding to this file.
- const Node* N = FindToolChain(In, xLanguage);
+ const Node* N = FindToolChain(In, xLanguage, InLangs);
// Pass file through the chain starting at head.
- PassThroughGraph(In, N, TempDir);
+ PassThroughGraph(In, N, InLangs, TempDir);
}
std::vector<const Node*> JTV;
@@ -324,9 +339,10 @@ int CompilationGraph::Build (const sys::Path& TempDir) {
throw std::runtime_error("Tool returned error code!");
if (!IsLast) {
- const Node* NextNode = &getNode(ChooseEdge(CurNode->OutEdges,
- CurNode->Name())->ToolName());
- PassThroughGraph(Out, NextNode, TempDir);
+ const Node* NextNode =
+ &getNode(ChooseEdge(CurNode->OutEdges, InLangs,
+ CurNode->Name())->ToolName());
+ PassThroughGraph(Out, NextNode, InLangs, TempDir);
}
}
diff --git a/tools/llvmc2/CompilationGraph.h b/tools/llvmc2/CompilationGraph.h
index 3dc8bc0623..1158d8df1d 100644
--- a/tools/llvmc2/CompilationGraph.h
+++ b/tools/llvmc2/CompilationGraph.h
@@ -20,14 +20,18 @@
#include "llvm/ADT/GraphTraits.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ADT/iterator"
+//#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/System/Path.h"
+#include <set>
#include <string>
namespace llvmc {
+ typedef std::set<std::string> InputLanguagesSet;
+
// An edge of the compilation graph.
class Edge : public llvm::RefCountedBaseVPTR<Edge> {
public:
@@ -35,7 +39,7 @@ namespace llvmc {
virtual ~Edge() {};
const std::string& ToolName() const { return ToolName_; }
- virtual unsigned Weight() const = 0;
+ virtual unsigned Weight(const InputLanguagesSet& InLangs) const = 0;
private:
std::string ToolName_;
};
@@ -44,7 +48,7 @@ namespace llvmc {
class SimpleEdge : public Edge {
public:
SimpleEdge(const std::string& T) : Edge(T) {}
- unsigned Weight() const { return 1; }
+ unsigned Weight(const InputLanguagesSet&) const { return 1; }
};
// A node of the compilation graph.
@@ -160,11 +164,13 @@ namespace llvmc {
// Pass the input file through the toolchain.
void PassThroughGraph (const llvm::sys::Path& In, const Node* StartNode,
+ const InputLanguagesSet& InLangs,
const llvm::sys::Path& TempDir) const;
// Find head of the toolchain corresponding to the given file.
const Node* FindToolChain(const llvm::sys::Path& In,
- const std::string* forceLanguage) const;
+ const std::string* forceLanguage,
+ InputLanguagesSet& InLangs) const;
// Sort the nodes in topological order.
void TopologicalSort(std::vector<const Node*>& Out);
diff --git a/tools/llvmc2/Example.td b/tools/llvmc2/Example.td
index 227090258a..6fb998b28b 100644
--- a/tools/llvmc2/Example.td
+++ b/tools/llvmc2/Example.td
@@ -34,12 +34,14 @@ def CompilationGraph : CompilationGraph<[
Edge<llc, llvm_gcc_assembler>,
Edge<llvm_gcc_assembler, llvm_gcc_linker>,
OptionalEdge<llvm_gcc_assembler, llvm_gcc_cpp_linker,
- [(parameter_equals "linker", "g++"),
- (parameter_equals "linker", "c++")]>,
+ [(if_input_languages_contain "c++"),
+ (or (parameter_equals "linker", "g++"),
+ (parameter_equals "linker", "c++"))]>,
Edge<root, llvm_gcc_linker>,
OptionalEdge<root, llvm_gcc_cpp_linker,
- [(parameter_equals "linker", "g++"),
- (parameter_equals "linker", "c++")]>
+ [(if_input_languages_contain "c++"),
+ (or (parameter_equals "linker", "g++"),
+ (parameter_equals "linker", "c++"))]>
]>;
diff --git a/utils/TableGen/LLVMCConfigurationEmitter.cpp b/utils/TableGen/LLVMCConfigurationEmitter.cpp
index 3db9176396..101dd95117 100644
--- a/utils/TableGen/LLVMCConfigurationEmitter.cpp
+++ b/utils/TableGen/LLVMCConfigurationEmitter.cpp
@@ -911,19 +911,29 @@ void TypecheckGraph (Record* CompilationGraph,
}
// Helper function used by EmitEdgePropertyTest.
-void EmitEdgePropertyTest1Arg(const DagInit& Prop,
+bool EmitEdgePropertyTest1Arg(const std::string& PropName,
+ const DagInit& Prop,
const GlobalOptionDescriptions& OptDescs,
std::ostream& O) {
checkNumberOfArguments(&Prop, 1);
const std::string& OptName = InitPtrToString(Prop.getArg(0));
- const GlobalOptionDescription& OptDesc = OptDescs.FindOption(OptName);
- if (OptDesc.Type != OptionType::Switch)
- throw OptName + ": incorrect option type!";
- O << OptDesc.GenVariableName();
+ if (PropName == "switch_on") {
+ const GlobalOptionDescription& OptDesc = OptDescs.FindOption(OptName);
+ if (OptDesc.Type != OptionType::Switch)
+ throw OptName + ": incorrect option type!";
+ O << OptDesc.GenVariableName();
+ return true;
+ }
+ else if (PropName == "if_input_languages_contain") {
+ O << "InLangs.count(\"" << OptName << "\") != 0";
+ return true;
+ }
+
+ return false;
}
// Helper function used by EmitEdgePropertyTest.
-void EmitEdgePropertyTest2Args(const std::string& PropName,
+bool EmitEdgePropertyTest2Args(const std::string& PropName,
const DagInit& Prop,
const GlobalOptionDescriptions& OptDescs,
std::ostream& O) {
@@ -937,6 +947,7 @@ void EmitEdgePropertyTest2Args(const std::string& PropName,
&& OptDesc.Type != OptionType::Prefix)
throw OptName + ": incorrect option type!";
O << OptDesc.GenVariableName() << " == \"" << OptArg << "\"";
+ return true;
}
else if (PropName == "element_in_list") {
if (OptDesc.Type != OptionType::ParameterList
@@ -946,9 +957,10 @@ void EmitEdgePropertyTest2Args(const std::string& PropName,
O << "std::find(" << VarName << ".begin(),\n"
<< Indent3 << VarName << ".end(), \""
<< OptArg << "\") != " << VarName << ".end()";
+ return true;
}
- else
- throw PropName + ": unknown edge property!";
+
+ return false;
}
// Helper function used by EmitEdgeClass.
@@ -956,10 +968,29 @@ void EmitEdgePropertyTest(const std::string& PropName,
const DagInit& Prop,
const GlobalOptionDescriptions& OptDescs,
std::ostream& O) {
- if (PropName == "switch_on")
- EmitEdgePropertyTest1Arg(Prop, OptDescs, O);
+ if (EmitEdgePropertyTest1Arg(PropName, Prop, OptDescs, O))
+ return;
+ else if (EmitEdgePropertyTest2Args(PropName, Prop, OptDescs, O))
+ return;
else
- EmitEdgePropertyTest2Args(PropName, Prop, OptDescs, O);
+ throw PropName + ": unknown edge property!";
+}
+
+// Helper function used by EmitEdgeClass.
+void EmitLogicalOperationTest(const DagInit& Prop, const char* LogicOp,
+ const GlobalOptionDescriptions& OptDescs,
+ std::ostream& O) {
+ O << '(';
+ for (unsigned j = 0, NumArgs = Prop.getNumArgs(); j < NumArgs; ++j) {
+ const DagInit& InnerProp = dynamic_cast<DagInit&>(*Prop.getArg(j));
+ const std::string& InnerPropName =
+ InnerProp.getOperator()->getAsString();
+ EmitEdgePropertyTest(InnerPropName, InnerProp, OptDescs, O);
+ if (j != NumArgs - 1)
+ O << ")\n" << Indent3 << ' ' << LogicOp << " (";
+ else
+ O << ')';
+ }
}
// Emit a single Edge* class.
@@ -975,7 +1006,7 @@ void EmitEdgeClass(unsigned N, const std::string& Target,
<< "\") {}\n\n"
// Function Weight().
- << Indent1 << "unsigned Weight() const {\n"
+ << Indent1 << "unsigned Weight(const InputLanguagesSet& InLangs) const {\n"
<< Indent2 << "unsigned ret = 0;\n";
for (size_t i = 0, PropsSize = Props->size(); i < PropsSize; ++i) {
@@ -985,24 +1016,17 @@ void EmitEdgeClass(unsigned N, const std::string& Target,
if (PropName == "default")
IsDefault = true;
- O << Indent2 << "if ((";
+ O << Indent2 << "if (";
if (PropName == "and") {
- O << '(';
- for (unsigned j = 0, NumArgs = Prop.getNumArgs(); j < NumArgs; ++j) {
- const DagInit& InnerProp = dynamic_cast<DagInit&>(*Prop.getArg(j));
- const std::string& InnerPropName =
- InnerProp.getOperator()->getAsString();
- EmitEdgePropertyTest(InnerPropName, InnerProp, OptDescs, O);
- if (j != NumArgs - 1)
- O << ")\n" << Indent3 << " && (";
- else
- O << ')';
- }
+ EmitLogicalOperationTest(Prop, "&&", OptDescs, O);
+ }
+ else if (PropName == "or") {
+ EmitLogicalOperationTest(Prop, "||", OptDescs, O);
}
else {
EmitEdgePropertyTest(PropName, Prop, OptDescs, O);
}
- O << "))\n" << Indent3 << "ret += 2;\n";
+ O << ")\n" << Indent3 << "ret += 2;\n";
}
if (IsDefault)