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.
// TOFIX: compiling files with same names should work.
// RUN: llvmc2 %s %p/together1.c -o %t
// RUN: llvmc2 %s %p/together.c -o %t
// RUN: ./%t | grep hello
extern "C" void test();

View File

@ -34,6 +34,7 @@ namespace {
if (!prog.canExecute())
throw std::runtime_error("Program '" + name + "' is not executable.");
// Build the command line vector and redirects.
const sys::Path* redirects[3] = {0,0,0};
sys::Path stdout_redirect;
@ -54,6 +55,7 @@ namespace {
}
argv.push_back(0); // null terminate list.
// Invoke the program.
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();
}
// 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
// a node that says that it is the last.
const JoinTool*
CompilationGraph::PassThroughGraph (sys::Path& In,
const Node* StartNode,
const sys::Path& TempDir) const {
void CompilationGraph::PassThroughGraph (const sys::Path& InFile,
const Node* StartNode,
const sys::Path& TempDir) const {
bool Last = false;
sys::Path In = InFile;
const Node* CurNode = StartNode;
JoinTool* ret = 0;
while(!Last) {
sys::Path Out;
Tool* CurTool = CurNode->ToolPtr.getPtr();
if (CurTool->IsJoin()) {
ret = &dynamic_cast<JoinTool&>(*CurTool);
ret->AddToJoinList(In);
JoinTool& JT = dynamic_cast<JoinTool&>(*CurTool);
JT.AddToJoinList(In);
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()) {
// Check if the first tool is also the last
if (Out.empty())
if (!OutputFilename.empty()) {
Out.set(OutputFilename);
}
else {
Out.set(In.getBasename());
else
Out.appendComponent(In.getBasename());
Out.appendSuffix(CurTool->OutputSuffix());
Out.appendSuffix(CurTool->OutputSuffix());
}
Last = true;
}
else {
Out = TempDir;
Out.appendComponent(In.getBasename());
Out.appendSuffix(CurTool->OutputSuffix());
Out.makeUnique(true, NULL);
Out.eraseFromDisk();
Out = MakeTempFile(TempDir, In.getBasename(), CurTool->OutputSuffix());
}
if (CurTool->GenerateAction(In, Out).Execute() != 0)
@ -166,8 +174,6 @@ CompilationGraph::PassThroughGraph (sys::Path& In,
CurNode->Name())->ToolName());
In = Out; Out.clear();
}
return ret;
}
// Sort the nodes in topological order.
@ -215,7 +221,6 @@ const Node* CompilationGraph::FindToolChain(const sys::Path& In) const {
return &getNode(ChooseEdge(TV)->ToolName());
}
// TOFIX: merge some parts with PassThroughGraph.
// Build the targets. Command-line options are passed through
// temporary variables.
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());
bool IsLast = false;
// Has files pending?
// Are there any files to be joined?
if (JT->JoinListEmpty())
continue;
// Is this the last tool in the chain?
// NOTE: we can process several chains in parallel.
if (!CurNode->HasChildren() || JT->IsLast()) {
if (OutputFilename.empty()) {
Out.set("a");
@ -257,11 +264,7 @@ int CompilationGraph::Build (const sys::Path& TempDir) {
IsLast = true;
}
else {
Out = TempDir;
Out.appendComponent("tmp");
Out.appendSuffix(JT->OutputSuffix());
Out.makeUnique(true, NULL);
Out.eraseFromDisk();
Out = MakeTempFile(TempDir, "tmp", JT->OutputSuffix());
}
if (JT->GenerateAction(Out).Execute() != 0)

View File

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

View File

@ -32,5 +32,7 @@ def CompilationGraph : CompilationGraph<[
Edge<opt, llc>,
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
// def LLVMGccC : < Tool<
// [ InLanguage<"c">,
// PrefixListOption<"Wl", [UnpackValues, PropertyName<Arg>, ...]>
// ...] ?
// DAG lists look more aesthetically pleasing to me.
def llvm_gcc_c : Tool<
[(in_language "c"),
(out_language "llvm-bitcode"),
(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)
]>;
@ -31,7 +33,7 @@ def llvm_gcc_cpp : Tool<
[(in_language "c++"),
(out_language "llvm-bitcode"),
(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)
]>;
@ -61,7 +63,8 @@ def llvm_gcc_assembler : Tool<
[(in_language "assembler"),
(out_language "object-code"),
(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"))
]>;
@ -85,4 +88,5 @@ def LanguageMap : LanguageMap<
LangToSuffixes<"llvm-assembler", ["ll"]>,
LangToSuffixes<"llvm-bitcode", ["bc"]>,
LangToSuffixes<"object-code", ["o"]>,
LangToSuffixes<"executable", ["out"]>]>;
LangToSuffixes<"executable", ["out"]>
]>;