Take object file as input and handle files with the same name correctly.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@50749 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Mikhail Glushenkov 2008-05-06 18:10:20 +00:00
parent ecbdcf2ae0
commit 35a85e8453
7 changed files with 60 additions and 49 deletions

View File

@ -1,6 +1,5 @@
// Check that we can compile files of different types together. // Check that we can compile files of different types together.
// TOFIX: compiling files with same names should work. // RUN: llvmc2 %s %p/together.c -o %t
// RUN: llvmc2 %s %p/together1.c -o %t
// RUN: ./%t | grep hello // RUN: ./%t | grep hello
extern "C" void test(); extern "C" void test();

View File

@ -34,6 +34,7 @@ namespace {
if (!prog.canExecute()) if (!prog.canExecute())
throw std::runtime_error("Program '" + name + "' is not executable."); throw std::runtime_error("Program '" + name + "' is not executable.");
// Build the command line vector and redirects.
const sys::Path* redirects[3] = {0,0,0}; const sys::Path* redirects[3] = {0,0,0};
sys::Path stdout_redirect; sys::Path stdout_redirect;
@ -54,6 +55,7 @@ namespace {
} }
argv.push_back(0); // null terminate list. argv.push_back(0); // null terminate list.
// Invoke the program.
return sys::Program::ExecuteAndWait(prog, &argv[0], 0, &redirects[0]); return sys::Program::ExecuteAndWait(prog, &argv[0], 0, &redirects[0]);
} }

View File

@ -121,42 +121,50 @@ void CompilationGraph::insertEdge(const std::string& A, Edge* E) {
B.IncrInEdges(); B.IncrInEdges();
} }
// Make a temporary file named like BaseName-RandomDigits.Suffix
sys::Path MakeTempFile(const sys::Path& TempDir, const std::string& BaseName,
const std::string& Suffix) {
sys::Path Out = TempDir;
Out.appendComponent(BaseName);
Out.appendSuffix(Suffix);
Out.makeUnique(true, NULL);
Out.eraseFromDisk();
return Out;
}
// Pass input file through the chain until we bump into a Join node or // Pass input file through the chain until we bump into a Join node or
// a node that says that it is the last. // a node that says that it is the last.
const JoinTool* void CompilationGraph::PassThroughGraph (const sys::Path& InFile,
CompilationGraph::PassThroughGraph (sys::Path& In, const Node* StartNode,
const Node* StartNode, const sys::Path& TempDir) const {
const sys::Path& TempDir) const {
bool Last = false; bool Last = false;
sys::Path In = InFile;
const Node* CurNode = StartNode; const Node* CurNode = StartNode;
JoinTool* ret = 0;
while(!Last) { while(!Last) {
sys::Path Out; sys::Path Out;
Tool* CurTool = CurNode->ToolPtr.getPtr(); Tool* CurTool = CurNode->ToolPtr.getPtr();
if (CurTool->IsJoin()) { if (CurTool->IsJoin()) {
ret = &dynamic_cast<JoinTool&>(*CurTool); JoinTool& JT = dynamic_cast<JoinTool&>(*CurTool);
ret->AddToJoinList(In); JT.AddToJoinList(In);
break; break;
} }
// Is this the last tool? // Since toolchains do not have to end with a Join node, we should
// check if this Node is the last.
if (!CurNode->HasChildren() || CurTool->IsLast()) { if (!CurNode->HasChildren() || CurTool->IsLast()) {
// Check if the first tool is also the last if (!OutputFilename.empty()) {
if (Out.empty()) Out.set(OutputFilename);
}
else {
Out.set(In.getBasename()); Out.set(In.getBasename());
else Out.appendSuffix(CurTool->OutputSuffix());
Out.appendComponent(In.getBasename()); }
Out.appendSuffix(CurTool->OutputSuffix());
Last = true; Last = true;
} }
else { else {
Out = TempDir; Out = MakeTempFile(TempDir, In.getBasename(), CurTool->OutputSuffix());
Out.appendComponent(In.getBasename());
Out.appendSuffix(CurTool->OutputSuffix());
Out.makeUnique(true, NULL);
Out.eraseFromDisk();
} }
if (CurTool->GenerateAction(In, Out).Execute() != 0) if (CurTool->GenerateAction(In, Out).Execute() != 0)
@ -166,8 +174,6 @@ CompilationGraph::PassThroughGraph (sys::Path& In,
CurNode->Name())->ToolName()); CurNode->Name())->ToolName());
In = Out; Out.clear(); In = Out; Out.clear();
} }
return ret;
} }
// Sort the nodes in topological order. // Sort the nodes in topological order.
@ -215,7 +221,6 @@ const Node* CompilationGraph::FindToolChain(const sys::Path& In) const {
return &getNode(ChooseEdge(TV)->ToolName()); return &getNode(ChooseEdge(TV)->ToolName());
} }
// TOFIX: merge some parts with PassThroughGraph.
// Build the targets. Command-line options are passed through // Build the targets. Command-line options are passed through
// temporary variables. // temporary variables.
int CompilationGraph::Build (const sys::Path& TempDir) { int CompilationGraph::Build (const sys::Path& TempDir) {
@ -243,10 +248,12 @@ int CompilationGraph::Build (const sys::Path& TempDir) {
JoinTool* JT = &dynamic_cast<JoinTool&>(*CurNode->ToolPtr.getPtr()); JoinTool* JT = &dynamic_cast<JoinTool&>(*CurNode->ToolPtr.getPtr());
bool IsLast = false; bool IsLast = false;
// Has files pending? // Are there any files to be joined?
if (JT->JoinListEmpty()) if (JT->JoinListEmpty())
continue; continue;
// Is this the last tool in the chain?
// NOTE: we can process several chains in parallel.
if (!CurNode->HasChildren() || JT->IsLast()) { if (!CurNode->HasChildren() || JT->IsLast()) {
if (OutputFilename.empty()) { if (OutputFilename.empty()) {
Out.set("a"); Out.set("a");
@ -257,11 +264,7 @@ int CompilationGraph::Build (const sys::Path& TempDir) {
IsLast = true; IsLast = true;
} }
else { else {
Out = TempDir; Out = MakeTempFile(TempDir, "tmp", JT->OutputSuffix());
Out.appendComponent("tmp");
Out.appendSuffix(JT->OutputSuffix());
Out.makeUnique(true, NULL);
Out.eraseFromDisk();
} }
if (JT->GenerateAction(Out).Execute() != 0) if (JT->GenerateAction(Out).Execute() != 0)

View File

@ -28,7 +28,7 @@
namespace llvmc { namespace llvmc {
// An edge in the graph. // An edge of the compilation graph.
class Edge : public llvm::RefCountedBaseVPTR<Edge> { class Edge : public llvm::RefCountedBaseVPTR<Edge> {
public: public:
Edge(const std::string& T) : ToolName_(T) {} Edge(const std::string& T) : ToolName_(T) {}
@ -41,7 +41,7 @@ namespace llvmc {
std::string ToolName_; std::string ToolName_;
}; };
// Edges with no properties are instances of this class. // Edges that have no properties are instances of this class.
class SimpleEdge : public Edge { class SimpleEdge : public Edge {
public: public:
SimpleEdge(const std::string& T) : Edge(T) {} SimpleEdge(const std::string& T) : Edge(T) {}
@ -49,8 +49,9 @@ namespace llvmc {
bool isDefault() const { return true;} bool isDefault() const { return true;}
}; };
// A node in the graph. // A node of the compilation graph.
struct Node { struct Node {
// A Node holds a list of the outward edges.
typedef llvm::SmallVector<llvm::IntrusiveRefCntPtr<Edge>, 3> container_type; typedef llvm::SmallVector<llvm::IntrusiveRefCntPtr<Edge>, 3> container_type;
typedef container_type::iterator iterator; typedef container_type::iterator iterator;
typedef container_type::const_iterator const_iterator; typedef container_type::const_iterator const_iterator;
@ -74,10 +75,9 @@ namespace llvmc {
void AddEdge(Edge* E) void AddEdge(Edge* E)
{ OutEdges.push_back(llvm::IntrusiveRefCntPtr<Edge>(E)); } { OutEdges.push_back(llvm::IntrusiveRefCntPtr<Edge>(E)); }
// Inward edge counter. Used by Build() to implement topological // Inward edge counter. Used to implement topological sort.
// sort. // TOTHINK: Move the mutable counter back into Tool classes? Makes
// TOTHINK: Move the counter back into Tool classes? Makes us more // us more const-correct.
// const-correct.
void IncrInEdges() { ++InEdges; } void IncrInEdges() { ++InEdges; }
void DecrInEdges() { --InEdges; } void DecrInEdges() { --InEdges; }
bool HasNoInEdges() const { return InEdges == 0; } bool HasNoInEdges() const { return InEdges == 0; }
@ -85,11 +85,12 @@ namespace llvmc {
// Needed to implement NodeChildIterator/GraphTraits // Needed to implement NodeChildIterator/GraphTraits
CompilationGraph* OwningGraph; CompilationGraph* OwningGraph;
// The corresponding Tool. // The corresponding Tool.
// WARNING: For the root node, ToolPtr is NULL. // WARNING: ToolPtr can be NULL (for the root node).
llvm::IntrusiveRefCntPtr<Tool> ToolPtr; llvm::IntrusiveRefCntPtr<Tool> ToolPtr;
// Links to children. // Links to children.
container_type OutEdges; container_type OutEdges;
// Number of parents. Used for topological sorting. // Inward edge counter. Updated in
// CompilationGraph::insertEdge(). Used for topological sorting.
unsigned InEdges; unsigned InEdges;
}; };
@ -99,8 +100,9 @@ namespace llvmc {
class CompilationGraph { class CompilationGraph {
// Main data structure. // Main data structure.
typedef llvm::StringMap<Node> nodes_map_type; typedef llvm::StringMap<Node> nodes_map_type;
// These are used to map from language names-> tools. (We can have // These are used to map from language names to tools. (We can
// several tools associated with each language name.) // have several tools associated with each language name, hence
// the need for a vector of Edges.)
typedef typedef
llvm::SmallVector<llvm::IntrusiveRefCntPtr<Edge>, 3> tools_vector_type; llvm::SmallVector<llvm::IntrusiveRefCntPtr<Edge>, 3> tools_vector_type;
typedef llvm::StringMap<tools_vector_type> tools_map_type; typedef llvm::StringMap<tools_vector_type> tools_map_type;
@ -159,9 +161,8 @@ namespace llvmc {
const tools_vector_type& getToolsVector(const std::string& LangName) const; const tools_vector_type& getToolsVector(const std::string& LangName) const;
// Pass the input file through the toolchain. // Pass the input file through the toolchain.
const JoinTool* PassThroughGraph (llvm::sys::Path& In, void PassThroughGraph (const llvm::sys::Path& In, const Node* StartNode,
const Node* StartNode, const llvm::sys::Path& TempDir) const;
const llvm::sys::Path& TempDir) const;
// Find head of the toolchain corresponding to the given file. // Find head of the toolchain corresponding to the given file.
const Node* FindToolChain(const llvm::sys::Path& In) const; const Node* FindToolChain(const llvm::sys::Path& In) const;

View File

@ -32,5 +32,7 @@ def CompilationGraph : CompilationGraph<[
Edge<opt, llc>, Edge<opt, llc>,
Edge<llc, llvm_gcc_assembler>, Edge<llc, llvm_gcc_assembler>,
Edge<llvm_gcc_assembler, llvm_gcc_linker> Edge<llvm_gcc_assembler, llvm_gcc_linker>,
Edge<root, llvm_gcc_linker>
]>; ]>;

View File

@ -11,19 +11,21 @@
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// Open issue: should we use DAG lists in Tool specifications // TOTHINK: Open issue: should we use DAG lists in Tool specifications
// or change to something like // or change to something like
// def LLVMGccC : < Tool< // def LLVMGccC : < Tool<
// [ InLanguage<"c">, // [ InLanguage<"c">,
// PrefixListOption<"Wl", [UnpackValues, PropertyName<Arg>, ...]> // PrefixListOption<"Wl", [UnpackValues, PropertyName<Arg>, ...]>
// ...] ? // ...] ?
// DAG lists look more aesthetically pleasing to me. // DAG lists look more aesthetically pleasing to me.
def llvm_gcc_c : Tool< def llvm_gcc_c : Tool<
[(in_language "c"), [(in_language "c"),
(out_language "llvm-bitcode"), (out_language "llvm-bitcode"),
(output_suffix "bc"), (output_suffix "bc"),
(cmd_line "llvm-gcc -c $INFILE -o $OUTFILE -emit-llvm"), (cmd_line "llvm-gcc -c -x c $INFILE -o $OUTFILE -emit-llvm"),
(sink) (sink)
]>; ]>;
@ -31,7 +33,7 @@ def llvm_gcc_cpp : Tool<
[(in_language "c++"), [(in_language "c++"),
(out_language "llvm-bitcode"), (out_language "llvm-bitcode"),
(output_suffix "bc"), (output_suffix "bc"),
(cmd_line "llvm-g++ -c $INFILE -o $OUTFILE -emit-llvm"), (cmd_line "llvm-g++ -c -x c++ $INFILE -o $OUTFILE -emit-llvm"),
(sink) (sink)
]>; ]>;
@ -61,7 +63,8 @@ def llvm_gcc_assembler : Tool<
[(in_language "assembler"), [(in_language "assembler"),
(out_language "object-code"), (out_language "object-code"),
(output_suffix "o"), (output_suffix "o"),
(cmd_line "llvm-gcc -c $INFILE -o $OUTFILE"), (cmd_line "llvm-gcc -c -x assembler $INFILE -o $OUTFILE"),
(switch_option "c", (stop_compilation)),
(prefix_list_option "Wa", (unpack_values), (help "pass options to assembler")) (prefix_list_option "Wa", (unpack_values), (help "pass options to assembler"))
]>; ]>;
@ -85,4 +88,5 @@ def LanguageMap : LanguageMap<
LangToSuffixes<"llvm-assembler", ["ll"]>, LangToSuffixes<"llvm-assembler", ["ll"]>,
LangToSuffixes<"llvm-bitcode", ["bc"]>, LangToSuffixes<"llvm-bitcode", ["bc"]>,
LangToSuffixes<"object-code", ["o"]>, LangToSuffixes<"object-code", ["o"]>,
LangToSuffixes<"executable", ["out"]>]>; LangToSuffixes<"executable", ["out"]>
]>;