Integrate LLD for MSVC targets via experimental CMake option LDC_WITH_LLD

Results in a 7.5% bigger RelWithDebInfo ldc2.exe on Win64 with LLVM 3.9.1.

LLD is currently enforced when building with LDC_WITH_LLD=ON. And LLD
still doesn't support debuginfo (.pdb) generation for MSVC targets.
This commit is contained in:
Martin 2017-05-27 15:47:12 +02:00
parent ede23642ef
commit 00d5f9b5b5
5 changed files with 62 additions and 32 deletions

View file

@ -80,10 +80,12 @@ set(CONF_INST_DIR ${SYSCONF_INSTALL_DIR} CACHE PATH "Directory ldc.conf is insta
# Note: LIB_SUFFIX should perhaps be renamed to LDC_LIBDIR_SUFFIX. # Note: LIB_SUFFIX should perhaps be renamed to LDC_LIBDIR_SUFFIX.
set(LIB_SUFFIX "" CACHE STRING "Appended to the library installation directory. Set to '64' to install libraries into ${PREFIX}/lib64.") set(LIB_SUFFIX "" CACHE STRING "Appended to the library installation directory. Set to '64' to install libraries into ${PREFIX}/lib64.")
# The following flags are currently not well tested, expect the build to fail. # The following flag is currently not well tested, expect the build to fail.
option(GENERATE_OFFTI "generate complete ClassInfo.offTi arrays") option(GENERATE_OFFTI "generate complete ClassInfo.offTi arrays")
mark_as_advanced(GENERATE_OFFTI) mark_as_advanced(GENERATE_OFFTI)
option(LDC_WITH_LLD "Integrate LLD, the LLVM cross-linker")
if(D_VERSION EQUAL 1) if(D_VERSION EQUAL 1)
message(FATAL_ERROR "D version 1 is no longer supported. message(FATAL_ERROR "D version 1 is no longer supported.
Please consider using D version 2 or checkout the 'd1' git branch for the last version supporting D version 1.") Please consider using D version 2 or checkout the 'd1' git branch for the last version supporting D version 1.")
@ -428,8 +430,6 @@ include_directories( SYSTEM
) )
append("-I${PROJECT_SOURCE_DIR}" DDMD_DFLAGS) append("-I${PROJECT_SOURCE_DIR}" DDMD_DFLAGS)
append("-I${PROJECT_BINARY_DIR}" DDMD_DFLAGS) append("-I${PROJECT_BINARY_DIR}" DDMD_DFLAGS)
if(MSVC) if(MSVC)
include_directories(${PROJECT_SOURCE_DIR}/vcbuild) include_directories(${PROJECT_SOURCE_DIR}/vcbuild)
endif() endif()
@ -448,6 +448,10 @@ if(GENERATE_OFFTI)
append("-DGENERATE_OFFTI" LDC_CXXFLAGS) append("-DGENERATE_OFFTI" LDC_CXXFLAGS)
endif() endif()
if(LDC_WITH_LLD)
append("-DLDC_WITH_LLD" LDC_CXXFLAGS)
endif()
option(RISCV_LLVM_DEV, "full RISC-V support with riscv-llvm") option(RISCV_LLVM_DEV, "full RISC-V support with riscv-llvm")
mark_as_advanced(RISCV_LLVM_DEV) mark_as_advanced(RISCV_LLVM_DEV)
@ -548,6 +552,13 @@ add_custom_target(${LDMD_EXE} ALL DEPENDS ${LDMD_EXE_FULL})
# Figure out how to link the main LDC executable, for which we need to take the # Figure out how to link the main LDC executable, for which we need to take the
# LLVM flags into account. # LLVM flags into account.
set(LDC_LINKERFLAG_LIST "${SANITIZE_LDFLAGS};${LLVM_LIBRARIES};${LLVM_LDFLAGS}") set(LDC_LINKERFLAG_LIST "${SANITIZE_LDFLAGS};${LLVM_LIBRARIES};${LLVM_LDFLAGS}")
if(LDC_WITH_LLD)
if(MSVC)
list(APPEND LDC_LINKERFLAG_LIST lldCOFF.lib lldCore.lib lldDriver.lib)
else()
set(LDC_LINKERFLAG_LIST "-llldCOFF;-llldCore;-llldDriver;${LDC_LINKERFLAG_LIST}")
endif()
endif()
set(LDC_LINK_MANUALLY OFF) set(LDC_LINK_MANUALLY OFF)
if(UNIX AND (CMAKE_COMPILER_IS_GNUCXX OR (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang"))) if(UNIX AND (CMAKE_COMPILER_IS_GNUCXX OR (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")))

View file

@ -362,19 +362,7 @@ int createStaticLibrary() {
#if LDC_LLVM_VER >= 309 #if LDC_LLVM_VER >= 309
if (useInternalArchiver) { if (useInternalArchiver) {
std::vector<const char *> fullArgs; const auto fullArgs = getFullArgs(tool, args, global.params.verbose);
fullArgs.reserve(1 + args.size());
fullArgs.push_back(tool.c_str());
for (const auto &arg : args)
fullArgs.push_back(arg.c_str());
if (global.params.verbose) {
for (auto arg : fullArgs) {
fprintf(global.stdmsg, "%s ", arg);
}
fprintf(global.stdmsg, "\n");
fflush(global.stdmsg);
}
const int exitCode = const int exitCode =
isTargetMSVC ? internalLib(fullArgs) : internalAr(fullArgs); isTargetMSVC ? internalLib(fullArgs) : internalAr(fullArgs);

View file

@ -12,6 +12,10 @@
#include "driver/tool.h" #include "driver/tool.h"
#include "gen/logger.h" #include "gen/logger.h"
#if LDC_WITH_LLD
#include "lld/Driver/Driver.h"
#endif
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
static llvm::cl::opt<std::string> mscrtlib( static llvm::cl::opt<std::string> mscrtlib(
@ -160,6 +164,20 @@ int linkObjToBinaryMSVC(llvm::StringRef outputPath,
} }
logstr << "\n"; // FIXME where's flush ? logstr << "\n"; // FIXME where's flush ?
#if LDC_WITH_LLD
const bool useInternalLinker = true; // TODO
if (useInternalLinker) {
const auto fullArgs =
getFullArgs("lld-link.exe", args, global.params.verbose);
const bool success = lld::coff::link(fullArgs);
if (!success)
error(Loc(), "linking with LLD failed");
return success ? 0 : 1;
}
#endif
// try to call linker // try to call linker
return executeToolAndWait(tool, args, global.params.verbose); return executeToolAndWait(tool, args, global.params.verbose);
} }

View file

@ -89,6 +89,30 @@ void createDirectoryForFileOrFail(llvm::StringRef fileName) {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
std::vector<const char *> getFullArgs(const std::string &tool,
const std::vector<std::string> &args,
bool printVerbose) {
std::vector<const char *> fullArgs;
fullArgs.reserve(args.size() +
2); // executeToolAndWait() appends an additional null
fullArgs.push_back(tool.c_str());
for (const auto &arg : args)
fullArgs.push_back(arg.c_str());
// Print command line if requested
if (printVerbose) {
for (auto arg : fullArgs)
fprintf(global.stdmsg, "%s ", arg);
fprintf(global.stdmsg, "\n");
fflush(global.stdmsg);
}
return fullArgs;
}
////////////////////////////////////////////////////////////////////////////////
int executeToolAndWait(const std::string &tool_, int executeToolAndWait(const std::string &tool_,
std::vector<std::string> const &args, bool verbose) { std::vector<std::string> const &args, bool verbose) {
const auto tool = findProgramByName(tool_); const auto tool = findProgramByName(tool_);
@ -99,24 +123,9 @@ int executeToolAndWait(const std::string &tool_,
// Construct real argument list. // Construct real argument list.
// First entry is the tool itself, last entry must be NULL. // First entry is the tool itself, last entry must be NULL.
std::vector<const char *> realargs; auto realargs = getFullArgs(tool, args, verbose);
realargs.reserve(args.size() + 2);
realargs.push_back(tool.c_str());
for (const auto &arg : args) {
realargs.push_back(arg.c_str());
}
realargs.push_back(nullptr); realargs.push_back(nullptr);
// Print command line if requested
if (verbose) {
// Print it
for (size_t i = 0; i < realargs.size() - 1; i++) {
fprintf(global.stdmsg, "%s ", realargs[i]);
}
fprintf(global.stdmsg, "\n");
fflush(global.stdmsg);
}
// Execute tool. // Execute tool.
std::string errstr; std::string errstr;
if (int status = llvm::sys::ExecuteAndWait(tool, &realargs[0], nullptr, if (int status = llvm::sys::ExecuteAndWait(tool, &realargs[0], nullptr,

View file

@ -28,6 +28,10 @@ std::string getProgram(const char *name,
void createDirectoryForFileOrFail(llvm::StringRef fileName); void createDirectoryForFileOrFail(llvm::StringRef fileName);
std::vector<const char *> getFullArgs(const std::string &tool,
const std::vector<std::string> &args,
bool printVerbose);
int executeToolAndWait(const std::string &tool, int executeToolAndWait(const std::string &tool,
std::vector<std::string> const &args, std::vector<std::string> const &args,
bool verbose = false); bool verbose = false);