ldc/driver/linker.cpp

176 lines
5.4 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//===-- linker.cpp --------------------------------------------------------===//
//
// LDC the LLVM D compiler
//
// This file is distributed under the BSD-style LDC license. See the LICENSE
// file for details.
//
//===----------------------------------------------------------------------===//
#include "errors.h"
#include "driver/cl_options.h"
#include "driver/linker.h"
#include "driver/tool.h"
#include "gen/llvm.h"
#include "gen/logger.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/Linker/Linker.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/SourceMgr.h"
//////////////////////////////////////////////////////////////////////////////
static llvm::cl::opt<bool>
staticFlag("static", llvm::cl::ZeroOrMore,
llvm::cl::desc("Create a statically linked binary, including "
"all system dependencies"));
//////////////////////////////////////////////////////////////////////////////
// linker-gcc.cpp
int linkObjToBinaryGcc(llvm::StringRef outputPath,
llvm::cl::boolOrDefault fullyStaticFlag);
// linker-msvc.cpp
int linkObjToBinaryMSVC(llvm::StringRef outputPath,
llvm::cl::boolOrDefault fullyStaticFlag);
//////////////////////////////////////////////////////////////////////////////
static std::string getOutputName() {
const auto &triple = *global.params.targetTriple;
const bool sharedLib = global.params.dll;
const char *extension = nullptr;
if (sharedLib) {
extension = global.dll_ext;
} else if (triple.isOSWindows()) {
extension = "exe";
}
if (global.params.exefile) {
// DMD adds the default extension if there is none
return opts::invokedByLDMD && extension
? FileName::defaultExt(global.params.exefile, extension)
: global.params.exefile;
}
// Infer output name from first object file.
std::string result = global.params.objfiles->dim
? FileName::removeExt((*global.params.objfiles)[0])
: "a.out";
if (sharedLib && !triple.isWindowsMSVCEnvironment())
result = "lib" + result;
if (global.params.run) {
// If `-run` is passed, the executable is temporary and is removed
// after execution. Make sure the name does not collide with other files
// from other processes by creating a unique filename.
llvm::SmallString<128> tempFilename;
auto EC = llvm::sys::fs::createTemporaryFile(FileName::name(result.c_str()),
extension ? extension : "",
tempFilename);
if (!EC)
result = tempFilename.str();
} else if (extension) {
result += '.';
result += extension;
}
return result;
}
//////////////////////////////////////////////////////////////////////////////
#if LDC_LLVM_VER >= 306
/// Insert an LLVM bitcode file into the module
static void insertBitcodeIntoModule(const char *bcFile, llvm::Module &M,
llvm::LLVMContext &Context) {
Logger::println("*** Linking-in bitcode file %s ***", bcFile);
llvm::SMDiagnostic Err;
std::unique_ptr<llvm::Module> loadedModule(
getLazyIRFileModule(bcFile, Err, Context));
if (!loadedModule) {
error(Loc(), "Error when loading LLVM bitcode file: %s", bcFile);
fatal();
}
#if LDC_LLVM_VER >= 308
llvm::Linker(M).linkInModule(std::move(loadedModule));
#else
llvm::Linker(&M).linkInModule(loadedModule.release());
#endif
}
#endif // LDC_LLVM_VER >= 306
/// Insert LLVM bitcode files into the module
void insertBitcodeFiles(llvm::Module &M, llvm::LLVMContext &Ctx,
Array<const char *> &bitcodeFiles) {
#if LDC_LLVM_VER >= 306
for (const char *fname : bitcodeFiles) {
insertBitcodeIntoModule(fname, M, Ctx);
}
#else
if (!bitcodeFiles.empty()) {
error(Loc(),
"Passing LLVM bitcode files to LDC is not supported for LLVM < 3.6");
fatal();
}
#endif
}
//////////////////////////////////////////////////////////////////////////////
// path to the produced executable/shared library
static std::string gExePath;
//////////////////////////////////////////////////////////////////////////////
int linkObjToBinary() {
Logger::println("*** Linking executable ***");
// remember output path for later
gExePath = getOutputName();
createDirectoryForFileOrFail(gExePath);
llvm::cl::boolOrDefault fullyStaticFlag = llvm::cl::BOU_UNSET;
if (staticFlag.getNumOccurrences() != 0) {
fullyStaticFlag = staticFlag ? llvm::cl::BOU_TRUE : llvm::cl::BOU_FALSE;
}
if (global.params.targetTriple->isWindowsMSVCEnvironment()) {
return linkObjToBinaryMSVC(gExePath, fullyStaticFlag);
}
return linkObjToBinaryGcc(gExePath, fullyStaticFlag);
}
//////////////////////////////////////////////////////////////////////////////
void deleteExeFile() {
if (!gExePath.empty() && !llvm::sys::fs::is_directory(gExePath)) {
llvm::sys::fs::remove(gExePath);
}
}
//////////////////////////////////////////////////////////////////////////////
int runProgram() {
assert(!gExePath.empty());
// Run executable
int status =
executeToolAndWait(gExePath, opts::runargs, global.params.verbose);
if (status < 0) {
#if defined(_MSC_VER) || defined(__MINGW32__)
error(Loc(), "program received signal %d", -status);
#else
error(Loc(), "program received signal %d (%s)", -status,
strsignal(-status));
#endif
return -status;
}
return status;
}