mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-02-18 12:43:21 +01:00
[svn r297] Fixed: rewrote linker code to use LLVM's Program facilities instead of DMD's oldschool broken "native" approach.
This commit is contained in:
158
gen/linker.cpp
158
gen/linker.cpp
@@ -1,8 +1,15 @@
|
||||
#include "gen/llvm.h"
|
||||
#include "llvm/Linker.h"
|
||||
#include "llvm/System/Program.h"
|
||||
|
||||
#include "root.h"
|
||||
#include "mars.h"
|
||||
#include "module.h"
|
||||
|
||||
#define NO_COUT_LOGGER
|
||||
#include "gen/logger.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef std::vector<llvm::Module*> Module_vector;
|
||||
|
||||
@@ -23,3 +30,154 @@ void linkModules(llvm::Module* dst, const Module_vector& MV)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int linkExecutable()
|
||||
{
|
||||
Logger::println("*** Linking executable ***");
|
||||
|
||||
// error string
|
||||
std::string errstr;
|
||||
|
||||
// find the llvm-ld program
|
||||
llvm::sys::Path ldpath = llvm::sys::Program::FindProgramByName("llvm-ld");
|
||||
if (ldpath.isEmpty())
|
||||
{
|
||||
error("linker program not found");
|
||||
fatal();
|
||||
}
|
||||
|
||||
// build arguments
|
||||
std::vector<const char*> args;
|
||||
|
||||
// first the program name ??
|
||||
args.push_back("llvm-ld");
|
||||
|
||||
// output filename
|
||||
std::string exestr;
|
||||
if (global.params.exefile)
|
||||
{ // explicit
|
||||
exestr = global.params.exefile;
|
||||
}
|
||||
else
|
||||
{ // inferred
|
||||
// try root module name
|
||||
if (Module::rootModule)
|
||||
exestr = Module::rootModule->toChars();
|
||||
else
|
||||
exestr = "a.out";
|
||||
}
|
||||
if (global.params.isWindows)
|
||||
exestr.append(".exe");
|
||||
|
||||
std::string outopt = "-o=" + exestr;
|
||||
args.push_back(outopt.c_str());
|
||||
|
||||
// create path to exe
|
||||
llvm::sys::Path exepath(exestr);
|
||||
exepath.set(exepath.getDirname());
|
||||
exepath.createDirectoryOnDisk(true, &errstr);
|
||||
if (!errstr.empty())
|
||||
{
|
||||
error("failed to create path to linking output\n%s", errstr.c_str());
|
||||
fatal();
|
||||
}
|
||||
|
||||
// strip debug info
|
||||
if (!global.params.symdebug)
|
||||
args.push_back("-strip-debug");
|
||||
|
||||
// optimization level
|
||||
if (!global.params.optimize)
|
||||
args.push_back("-disable-opt");
|
||||
else
|
||||
{
|
||||
const char* s = 0;
|
||||
switch(global.params.optimizeLevel)
|
||||
{
|
||||
case 0:
|
||||
s = "-O0"; break;
|
||||
case 1:
|
||||
s = "-O1"; break;
|
||||
case 2:
|
||||
s = "-O2"; break;
|
||||
case 3:
|
||||
s = "-O3"; break;
|
||||
case 4:
|
||||
s = "-O4"; break;
|
||||
case 5:
|
||||
s = "-O5"; break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
args.push_back(s);
|
||||
}
|
||||
|
||||
// inlining
|
||||
if (!(global.params.useInline || global.params.llvmInline))
|
||||
{
|
||||
args.push_back("-disable-inlining");
|
||||
}
|
||||
|
||||
// additional linker switches
|
||||
for (int i = 0; i < global.params.linkswitches->dim; i++)
|
||||
{
|
||||
char *p = (char *)global.params.linkswitches->data[i];
|
||||
args.push_back(p);
|
||||
}
|
||||
|
||||
// native please
|
||||
args.push_back("-native");
|
||||
|
||||
|
||||
// user libs
|
||||
for (int i = 0; i < global.params.libfiles->dim; i++)
|
||||
{
|
||||
char *p = (char *)global.params.libfiles->data[i];
|
||||
args.push_back(p);
|
||||
}
|
||||
|
||||
// default libs
|
||||
args.push_back("-ltango-base-c-llvmdc");
|
||||
args.push_back("-lpthread");
|
||||
args.push_back("-ldl");
|
||||
args.push_back("-lm");
|
||||
|
||||
// object files
|
||||
for (int i = 0; i < global.params.objfiles->dim; i++)
|
||||
{
|
||||
char *p = (char *)global.params.objfiles->data[i];
|
||||
args.push_back(p);
|
||||
}
|
||||
|
||||
// runtime library
|
||||
// must be linked in last to null terminate the moduleinfo appending list
|
||||
std::string runtime_path(global.params.runtimePath);
|
||||
if (*runtime_path.rbegin() != '/')
|
||||
runtime_path.append("/");
|
||||
runtime_path.append("libtango-base-llvmdc.a");
|
||||
args.push_back(runtime_path.c_str());
|
||||
|
||||
// print link command?
|
||||
if (!global.params.quiet || global.params.verbose)
|
||||
{
|
||||
// Print it
|
||||
for (int i = 0; i < args.size(); i++)
|
||||
printf("%s ", args[i]);
|
||||
printf("\n");
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
// terminate args list
|
||||
args.push_back(NULL);
|
||||
|
||||
// try to call linker!!!
|
||||
if (int status = llvm::sys::Program::ExecuteAndWait(ldpath, &args[0], NULL, NULL, 0,0, &errstr))
|
||||
{
|
||||
error("linking failed:\nstatus: %d", status);
|
||||
if (!errstr.empty())
|
||||
error("message: %s", errstr.c_str());
|
||||
fatal();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user