Skip to content

Commit e0c07e8

Browse files
committed
Integrate LLD 5.0+ for ELF and Mach-O targets
Requires LLD 5.0+, otherwise LDC aborts due to conflicting command-line options.
1 parent a04f2a0 commit e0c07e8

File tree

3 files changed

+57
-5
lines changed

3 files changed

+57
-5
lines changed

CMakeLists.txt

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -572,14 +572,25 @@ add_custom_target(${LDMD_EXE} ALL DEPENDS ${LDMD_EXE_FULL})
572572

573573
# Figure out how to link the main LDC executable, for which we need to take the
574574
# LLVM flags into account.
575-
set(LDC_LINKERFLAG_LIST "${SANITIZE_LDFLAGS};${LLVM_LIBRARIES};${LLVM_LDFLAGS}")
575+
set(LDC_LINKERFLAG_LIST "")
576576
if(LDC_WITH_LLD)
577-
if(MSVC)
578-
list(APPEND LDC_LINKERFLAG_LIST lldCOFF.lib lldCore.lib lldDriver.lib)
577+
# ELF and Mach-O are only supported starting with LLD 5.0, otherwise there
578+
# are command-line option conflicts with LDC.
579+
if(LDC_LLVM_VER LESS 500)
580+
if(MSVC)
581+
list(APPEND LDC_LINKERFLAG_LIST lldDriver.lib lldCOFF.lib lldCore.lib)
582+
else()
583+
list(APPEND LDC_LINKERFLAG_LIST -llldDriver -llldCOFF -llldCore)
584+
endif()
579585
else()
580-
set(LDC_LINKERFLAG_LIST "-llldCOFF;-llldCore;-llldDriver;${LDC_LINKERFLAG_LIST}")
586+
if(MSVC)
587+
list(APPEND LDC_LINKERFLAG_LIST lldDriver.lib lldCOFF.lib lldELF.lib lldMachO.lib lldYAML.lib lldReaderWriter.lib lldConfig.lib lldCore.lib)
588+
else()
589+
list(APPEND LDC_LINKERFLAG_LIST -llldDriver -llldCOFF -llldELF -llldMachO -llldYAML -llldReaderWriter -llldConfig -llldCore)
590+
endif()
581591
endif()
582592
endif()
593+
list(APPEND LDC_LINKERFLAG_LIST ${SANITIZE_LDFLAGS} ${LLVM_LIBRARIES} ${LLVM_LDFLAGS})
583594

584595
set(LDC_LINK_MANUALLY OFF)
585596
if(UNIX AND (CMAKE_COMPILER_IS_GNUCXX OR (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")))

driver/cl_options-llvm.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,18 @@ TargetOptions InitTargetOptionsFromCodeGenFlags() {
4949
std::string getCPUStr() { return ::getCPUStr(); }
5050
std::string getFeaturesStr() { return ::getFeaturesStr(); }
5151
} // namespace opts
52+
53+
#if LDC_WITH_LLD && LDC_LLVM_VER >= 500
54+
// LLD 5.0 uses the shared header too (for LTO) and exposes some wrappers in
55+
// the lld namespace. Define them here to prevent the LLD object from being
56+
// linked in with its conflicting command-line options.
57+
namespace lld {
58+
TargetOptions InitTargetOptionsFromCodeGenFlags() {
59+
return ::InitTargetOptionsFromCodeGenFlags();
60+
}
61+
62+
CodeModel::Model GetCodeModelFromCMModel() {
63+
return CMModel;
64+
}
65+
}
66+
#endif // LDC_WITH_LLD && LDC_LLVM_VER >= 500

driver/linker-gcc.cpp

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@
2121
#include "llvm/Target/TargetMachine.h"
2222
#include "llvm/Target/TargetOptions.h"
2323

24+
#if LDC_WITH_LLD && LDC_LLVM_VER >= 500
25+
#include "lld/Driver/Driver.h"
26+
#endif
27+
2428
//////////////////////////////////////////////////////////////////////////////
2529

2630
static llvm::cl::opt<std::string>
@@ -481,7 +485,7 @@ void ArgsBuilder::addTargetFlags() {
481485
}
482486

483487
//////////////////////////////////////////////////////////////////////////////
484-
// (Yet unused) specialization for plain ld.
488+
// Specialization for plain ld.
485489

486490
class LdArgsBuilder : public ArgsBuilder {
487491
void addSanitizers() override {}
@@ -513,6 +517,28 @@ class LdArgsBuilder : public ArgsBuilder {
513517

514518
int linkObjToBinaryGcc(llvm::StringRef outputPath, bool useInternalLinker,
515519
llvm::cl::boolOrDefault fullyStaticFlag) {
520+
#if LDC_WITH_LLD && LDC_LLVM_VER >= 500
521+
if (useInternalLinker) {
522+
LdArgsBuilder argsBuilder;
523+
argsBuilder.build(outputPath, fullyStaticFlag);
524+
525+
const auto fullArgs =
526+
getFullArgs("ld.lld", argsBuilder.args, global.params.verbose);
527+
528+
bool success = false;
529+
if (global.params.targetTriple->isOSBinFormatELF()) {
530+
success = lld::elf::link(fullArgs, /*CanExitEarly*/ false);
531+
} else if (global.params.targetTriple->isOSBinFormatMachO()) {
532+
success = lld::mach_o::link(fullArgs);
533+
}
534+
535+
if (!success)
536+
error(Loc(), "linking with LLD failed");
537+
538+
return success ? 0 : 1;
539+
}
540+
#endif
541+
516542
// find gcc for linking
517543
const std::string tool = getGcc();
518544

0 commit comments

Comments
 (0)