mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-17 21:29:20 +00:00
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:
parent
ecbdcf2ae0
commit
35a85e8453
@ -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();
|
||||||
|
@ -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]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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;
|
||||||
|
@ -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>
|
||||||
]>;
|
]>;
|
||||||
|
@ -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"]>
|
||||||
|
]>;
|
||||||
|
Loading…
Reference in New Issue
Block a user