diff --git a/.circleci/config.yml b/.circleci/config.yml index 89e79efe3c..8a6dcdbf22 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -58,7 +58,7 @@ jobs: export HOST_LDMD=$PWD/ldc2-$HOST_LDC_VERSION-linux-x86_64/bin/ldmd2 mkdir bootstrap cd bootstrap - cmake -G Ninja -DLDC_WITH_LLD=OFF -DLLVM_ROOT_DIR=$PWD/../llvm-$LLVM_VERSION -DBUILD_SHARED_LIBS=OFF -DD_COMPILER=$HOST_LDMD .. + cmake -G Ninja -DLLVM_ROOT_DIR=$PWD/../llvm-$LLVM_VERSION -DBUILD_SHARED_LIBS=OFF -DD_COMPILER=$HOST_LDMD .. ninja -j3 bin/ldc2 -version cd .. @@ -68,7 +68,7 @@ jobs: export HOST_LDMD=$PWD/bootstrap/bin/ldmd2 mkdir build cd build - cmake -G Ninja -DLDC_WITH_LLD=OFF -DLLVM_ROOT_DIR=$PWD/../llvm-$LLVM_VERSION -DLDC_INSTALL_LTOPLUGIN=ON -DLDC_INSTALL_LLVM_RUNTIME_LIBS=ON -DD_COMPILER=$HOST_LDMD .. + cmake -G Ninja -DLLVM_ROOT_DIR=$PWD/../llvm-$LLVM_VERSION -DLDC_INSTALL_LTOPLUGIN=ON -DLDC_INSTALL_LLVM_RUNTIME_LIBS=ON -DD_COMPILER=$HOST_LDMD .. ninja -j3 all all-test-runners bin/ldc2 -version cd .. diff --git a/.travis.yml b/.travis.yml index fea2417bd4..d5a35b03ad 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,7 @@ matrix: include: - os: linux d: ldc - env: LLVM_VERSION=5.0.0 OPTS="-DLIB_SUFFIX=64 -DLDC_WITH_LLD=OFF" + env: LLVM_VERSION=5.0.0 OPTS="-DLIB_SUFFIX=64" - os: linux d: ldc env: LLVM_VERSION=4.0.1 OPTS="-DLIB_SUFFIX=64" diff --git a/CMakeLists.txt b/CMakeLists.txt index a98c786b63..e028fa2a57 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -339,6 +339,7 @@ set(DRV_SRC driver/cache.cpp driver/cl_options.cpp driver/cl_options_sanitizers.cpp + driver/cl_options-llvm.cpp driver/codegenerator.cpp driver/configfile.cpp driver/dcomputecodegenerator.cpp @@ -358,6 +359,7 @@ set(DRV_HDR driver/cache_pruning.h driver/cl_options.h driver/cl_options_sanitizers.h + driver/cl_options-llvm.h driver/codegenerator.h driver/configfile.h driver/dcomputecodegenerator.h diff --git a/driver/cache.cpp b/driver/cache.cpp index 2f5380709f..4f9540fd61 100644 --- a/driver/cache.cpp +++ b/driver/cache.cpp @@ -302,14 +302,18 @@ void outputIR2ObjRelevantCmdlineArgs(llvm::raw_ostream &hash_os) { // sharing the cache). outputOptimizationSettings(hash_os); opts::outputSanitizerSettings(hash_os); - hash_os << opts::mCPU; - for (auto &attr : opts::mAttrs) { - hash_os << attr; - } - hash_os << opts::mFloatABI; - hash_os << opts::mRelocModel; - hash_os << opts::mCodeModel; - hash_os << opts::disableFpElim; + hash_os << opts::getCPUStr(); + hash_os << opts::getFeaturesStr(); + hash_os << opts::floatABI; +#if LDC_LLVM_VER >= 309 + const auto relocModel = opts::getRelocModel(); + if (relocModel.hasValue()) + hash_os << relocModel.getValue(); +#else + hash_os << opts::getRelocModel(); +#endif + hash_os << opts::getCodeModel(); + hash_os << opts::disableFPElim(); } // Output to `hash_os` all environment flags that influence object code output diff --git a/driver/cl_options-llvm.cpp b/driver/cl_options-llvm.cpp new file mode 100644 index 0000000000..e8ec1be803 --- /dev/null +++ b/driver/cl_options-llvm.cpp @@ -0,0 +1,64 @@ +//===-- cl_options-llvm.cpp -----------------------------------------------===// +// +// LDC – the LLVM D compiler +// +// This file is distributed under the BSD-style LDC license. See the LICENSE +// file for details. +// +//===----------------------------------------------------------------------===// + +#include "driver/cl_options-llvm.h" + +// Pull in command-line options and helper functions from special LLVM header +// shared by multiple LLVM tools. +#include "llvm/CodeGen/CommandFlags.h" + +static cl::opt + DisableRedZone("disable-red-zone", cl::ZeroOrMore, + cl::desc("Do not emit code that uses the red zone.")); + +// Now expose the helper functions (with static linkage) via external wrappers +// in the opts namespace, including some additional helper functions. +namespace opts { + +std::string getArchStr() { return ::MArch; } + +#if LDC_LLVM_VER >= 309 +Optional getRelocModel() { return ::getRelocModel(); } +#else +Reloc::Model getRelocModel() { return ::RelocModel; } +#endif + +CodeModel::Model getCodeModel() { return ::CMModel; } + +bool disableFPElim() { return ::DisableFPElim; } + +bool disableRedZone() { return ::DisableRedZone; } + +bool printTargetFeaturesHelp() { + if (MCPU == "help") + return true; + return std::any_of(MAttrs.begin(), MAttrs.end(), + [](const std::string &a) { return a == "help"; }); +} + +TargetOptions InitTargetOptionsFromCodeGenFlags() { + return ::InitTargetOptionsFromCodeGenFlags(); +} + +std::string getCPUStr() { return ::getCPUStr(); } +std::string getFeaturesStr() { return ::getFeaturesStr(); } +} // namespace opts + +#if LDC_WITH_LLD && LDC_LLVM_VER >= 500 +// LLD 5.0 uses the shared header too (for LTO) and exposes some wrappers in +// the lld namespace. Define them here to prevent the LLD object from being +// linked in with its conflicting command-line options. +namespace lld { +TargetOptions InitTargetOptionsFromCodeGenFlags() { + return ::InitTargetOptionsFromCodeGenFlags(); +} + +CodeModel::Model GetCodeModelFromCMModel() { return CMModel; } +} +#endif // LDC_WITH_LLD && LDC_LLVM_VER >= 500 diff --git a/driver/cl_options-llvm.h b/driver/cl_options-llvm.h new file mode 100644 index 0000000000..b249cbfc29 --- /dev/null +++ b/driver/cl_options-llvm.h @@ -0,0 +1,36 @@ +//===-- driver/cl_options-llvm.h - LLVM command line options ----*- C++ -*-===// +// +// LDC – the LLVM D compiler +// +// This file is distributed under the BSD-style LDC license. See the LICENSE +// file for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LDC_DRIVER_CL_OPTIONS_LLVM_H +#define LDC_DRIVER_CL_OPTIONS_LLVM_H + +#include "llvm/ADT/Optional.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/CodeGen.h" +#include "llvm/Target/TargetOptions.h" + +namespace opts { + +std::string getArchStr(); +#if LDC_LLVM_VER >= 309 +llvm::Optional getRelocModel(); +#else +llvm::Reloc::Model getRelocModel(); +#endif +llvm::CodeModel::Model getCodeModel(); +bool disableFPElim(); +bool disableRedZone(); +bool printTargetFeaturesHelp(); + +llvm::TargetOptions InitTargetOptionsFromCodeGenFlags(); +std::string getCPUStr(); +std::string getFeaturesStr(); +} + +#endif diff --git a/driver/cl_options.cpp b/driver/cl_options.cpp index 4179d4bf43..674d7e4f00 100644 --- a/driver/cl_options.cpp +++ b/driver/cl_options.cpp @@ -134,10 +134,6 @@ static cl::opt debugInfo( clEnumValN(3, "gline-tables-only", "Add line tables only")), cl::location(global.params.symdebug), cl::init(0)); -static cl::opt - dwarfVersion("dwarf-version", cl::desc("Dwarf version"), cl::ZeroOrMore, - cl::location(global.params.dwarfVersion), cl::Hidden); - cl::opt noAsm("noasm", cl::desc("Disallow use of inline assembler"), cl::ZeroOrMore); @@ -175,12 +171,6 @@ static cl::opt cl::desc("Remove generated object files on success"), cl::location(global.params.cleanupObjectFiles)); -// Disabling Red Zone -cl::opt - disableRedZone("disable-red-zone", cl::ZeroOrMore, - cl::desc("Do not emit code that uses the red zone."), - cl::location(global.params.disableRedZone)); - // DDoc options static cl::opt doDdoc("D", cl::desc("Generate documentation"), cl::location(global.params.doDocComments), @@ -296,21 +286,10 @@ cl::opt "'-deps' alone prints module dependencies " "(imports/file/version/debug/lib)")); -cl::opt mArch("march", cl::ZeroOrMore, - cl::desc("Architecture to generate code for:")); - cl::opt m32bits("m32", cl::desc("32 bit target"), cl::ZeroOrMore); cl::opt m64bits("m64", cl::desc("64 bit target"), cl::ZeroOrMore); -cl::opt - mCPU("mcpu", cl::ZeroOrMore, cl::value_desc("cpu-name"), cl::init(""), - cl::desc("Target a specific cpu type (-mcpu=help for details)")); - -cl::list - mAttrs("mattr", cl::CommaSeparated, cl::value_desc("a1,+a2,-a3,..."), - cl::desc("Target specific attributes (-mattr=help for details)")); - cl::opt mTargetTriple("mtriple", cl::ZeroOrMore, cl::desc("Override target triple")); @@ -325,54 +304,7 @@ static cl::list modFileAliasStrings( cl::value_desc("="), cl::location(modFileAliasStringsStore)); -cl::opt mRelocModel( - "relocation-model", cl::desc("Relocation model"), cl::ZeroOrMore, -#if LDC_LLVM_VER < 309 - cl::init(llvm::Reloc::Default), -#endif - clEnumValues( -#if LDC_LLVM_VER < 309 - clEnumValN(llvm::Reloc::Default, "default", - "Target default relocation model"), -#endif - clEnumValN(llvm::Reloc::Static, "static", "Non-relocatable code"), - clEnumValN(llvm::Reloc::PIC_, "pic", - "Fully relocatable, position independent code"), - clEnumValN(llvm::Reloc::DynamicNoPIC, "dynamic-no-pic", - "Relocatable external references, non-relocatable code"))); - -cl::opt mCodeModel( - "code-model", cl::desc("Code model"), cl::ZeroOrMore, -#if LDC_LLVM_VER < 600 - cl::init(llvm::CodeModel::Default), - clEnumValues( - clEnumValN(llvm::CodeModel::Default, "default", - "Target default code model"), -#else - cl::init(llvm::CodeModel::Small), - clEnumValues( -#endif - clEnumValN(llvm::CodeModel::Small, "small", "Small code model"), - clEnumValN(llvm::CodeModel::Kernel, "kernel", "Kernel code model"), - clEnumValN(llvm::CodeModel::Medium, "medium", "Medium code model"), - clEnumValN(llvm::CodeModel::Large, "large", "Large code model"))); - -cl::opt mFloatABI( - "float-abi", cl::desc("ABI/operations to use for floating-point types:"), - cl::ZeroOrMore, cl::init(FloatABI::Default), - clEnumValues( - clEnumValN(FloatABI::Default, "default", - "Target default floating-point ABI"), - clEnumValN(FloatABI::Soft, "soft", - "Software floating-point ABI and operations"), - clEnumValN(FloatABI::SoftFP, "softfp", - "Soft-float ABI, but hardware floating-point instructions"), - clEnumValN(FloatABI::Hard, "hard", - "Hardware floating-point ABI and instructions"))); - -cl::opt - disableFpElim("disable-fp-elim", cl::ZeroOrMore, - cl::desc("Disable frame pointer elimination optimization")); +FloatABI::Type floatABI; // Storage for the dynamically created float-abi option. static cl::opt> asserts("asserts", cl::ZeroOrMore, cl::desc("(*) Enable assertions"), @@ -437,12 +369,10 @@ cl::opt disableLinkerStripDead( // Math options bool fFastMath; // Storage for the dynamically created ffast-math option. llvm::FastMathFlags defaultFMF; -void setDefaultMathOptions(llvm::TargetMachine &target) { +void setDefaultMathOptions(llvm::TargetOptions &targetOptions) { if (fFastMath) { defaultFMF.setUnsafeAlgebra(); - - llvm::TargetOptions &TO = target.Options; - TO.UnsafeFPMath = true; + targetOptions.UnsafeFPMath = true; } } @@ -560,6 +490,7 @@ void createClashingOptions() { // is a clash in the command line options. renameAndHide("color", "llvm-color"); renameAndHide("ffast-math", "llvm-ffast-math"); + renameAndHide("float-abi", "llvm-float-abi"); // Step 2. Add the LDC options. new cl::opt>( @@ -567,6 +498,19 @@ void createClashingOptions() { cl::desc("(*) Force colored console output")); new cl::opt("ffast-math", cl::ZeroOrMore, cl::location(fFastMath), cl::desc("Set @fastmath for all functions.")); + new cl::opt( + "float-abi", cl::desc("ABI/operations to use for floating-point types:"), + cl::ZeroOrMore, cl::location(floatABI), cl::init(FloatABI::Default), + clEnumValues( + clEnumValN(FloatABI::Default, "default", + "Target default floating-point ABI"), + clEnumValN(FloatABI::Soft, "soft", + "Software floating-point ABI and operations"), + clEnumValN( + FloatABI::SoftFP, "softfp", + "Soft-float ABI, but hardware floating-point instructions"), + clEnumValN(FloatABI::Hard, "hard", + "Hardware floating-point ABI and instructions"))); } /// Hides command line options exposed from within LLVM that are unlikely @@ -603,6 +547,15 @@ void hideLLVMOptions() { "verify-region-info", "verify-scev", "verify-scev-maps", "x86-early-ifcvt", "x86-use-vzeroupper", "x86-recip-refinement-steps", + "thread-model", "exception-model", "enable-fp-mad", + "enable-unsafe-fp-math", "enable-no-infs-fp-math", + "enable-no-nans-fp-math", "enable-no-trapping-fp-math", + "denormal-fp-math", "recip", "nozero-initialized-in-bss", "tailcallopt", + "stack-symbol-ordering", "stack-alignment", "enable-pie", "use-ctors", + "emulated-tls", "unique-section-names", "jump-table-type", "meabi", + "debugger-tune", "asm-instrumentation", "mc-relax-all", + "incremental-linker-compatible", "asm-show-inst", "pie-copy-relocations", + // We enable -fdata-sections/-ffunction-sections by default where it makes // sense for reducing code size, so hide them to avoid confusion. // @@ -611,7 +564,20 @@ void hideLLVMOptions() { // on the target triple (and thus we do not know it until after the // command // line has been parsed). - "fdata-sections", "ffunction-sections"}; + "fdata-sections", "ffunction-sections", "data-sections", + "function-sections"}; + + // pulled in from shared LLVM headers, but unused or not desired in LDC + static const char *const removedOptions[] = {"disable-tail-calls", + "fatal-warnings", + "filetype", + "no-deprecated-warn", + "no-warn", + "stackrealign", + "start-after", + "stop-after", + "trap-func", + "W"}; llvm::StringMap &map = cl::getRegisteredOptions(); for (const auto name : hiddenOptions) { @@ -622,6 +588,13 @@ void hideLLVMOptions() { it->second->setHiddenFlag(cl::Hidden); } } + + for (const auto name : removedOptions) { + auto it = map.find(name); + if (it != map.end()) { + map.erase(it); + } + } } } // namespace opts diff --git a/driver/cl_options.h b/driver/cl_options.h index 5030a52e47..b7cfdc00e3 100644 --- a/driver/cl_options.h +++ b/driver/cl_options.h @@ -15,6 +15,7 @@ #ifndef LDC_DRIVER_CL_OPTIONS_H #define LDC_DRIVER_CL_OPTIONS_H +#include "driver/cl_options-llvm.h" #include "driver/targetmachine.h" #include "gen/cl_helpers.h" #include "llvm/ADT/SmallVector.h" @@ -69,24 +70,18 @@ extern cl::opt cacheDir; extern cl::list linkerSwitches; extern cl::list ccSwitches; -extern cl::opt mArch; extern cl::opt m32bits; extern cl::opt m64bits; -extern cl::opt mCPU; -extern cl::list mAttrs; extern cl::opt mTargetTriple; extern cl::opt mABI; -extern cl::opt mRelocModel; -extern cl::opt mCodeModel; -extern cl::opt disableFpElim; -extern cl::opt mFloatABI; +extern FloatABI::Type floatABI; extern cl::opt linkonceTemplates; extern cl::opt disableLinkerStripDead; // Math options extern bool fFastMath; extern llvm::FastMathFlags defaultFMF; -void setDefaultMathOptions(llvm::TargetMachine &target); +void setDefaultMathOptions(llvm::TargetOptions &targetOptions); extern cl::opt boundsCheck; extern bool nonSafeBoundsChecks; diff --git a/driver/linker-gcc.cpp b/driver/linker-gcc.cpp index 8e2a77ca9b..4ae7ed9e9e 100644 --- a/driver/linker-gcc.cpp +++ b/driver/linker-gcc.cpp @@ -118,8 +118,9 @@ void ArgsBuilder::addLTOGoldPluginFlags() { if (opts::isUsingThinLTO()) addLdFlag("-plugin-opt=thinlto"); - if (!opts::mCPU.empty()) - addLdFlag(llvm::Twine("-plugin-opt=mcpu=") + opts::mCPU); + const auto cpu = gTargetMachine->getTargetCPU(); + if (!cpu.empty()) + addLdFlag(llvm::Twine("-plugin-opt=mcpu=") + cpu); // Use the O-level passed to LDC as the O-level for LTO, but restrict it to // the [0, 3] range that can be passed to the linker plugin. diff --git a/driver/main.cpp b/driver/main.cpp index 1de3613144..4c0d766307 100644 --- a/driver/main.cpp +++ b/driver/main.cpp @@ -104,18 +104,6 @@ static cl::opt linkDebugLib( "link-debuglib", cl::ZeroOrMore, cl::desc("Link with libraries specified in -debuglib, not -defaultlib")); -#if LDC_LLVM_VER >= 309 -static inline llvm::Optional getRelocModel() { - if (mRelocModel.getNumOccurrences()) { - llvm::Reloc::Model R = mRelocModel; - return R; - } - return llvm::None; -} -#else -static inline llvm::Reloc::Model getRelocModel() { return mRelocModel; } -#endif - // This function exits the program. void printVersion(llvm::raw_ostream &OS) { OS << "LDC - the LLVM D compiler (" << global.ldc_version << "):\n"; @@ -372,8 +360,7 @@ void parseCommandLine(int argc, char **argv, Strings &sourceFiles, const_cast(allArguments.data()), "LDC - the LLVM D compiler\n"); - helpOnly = mCPU == "help" || - (std::find(mAttrs.begin(), mAttrs.end(), "help") != mAttrs.end()); + helpOnly = opts::printTargetFeaturesHelp(); if (helpOnly) { auto triple = llvm::Triple(cfg_triple); std::string errMsg; @@ -599,19 +586,12 @@ void parseCommandLine(int argc, char **argv, Strings &sourceFiles, error(Loc(), "-lib and -shared switches cannot be used together"); } -#if LDC_LLVM_VER >= 309 - if (global.params.dll && !mRelocModel.getNumOccurrences()) { -#else - if (global.params.dll && mRelocModel == llvm::Reloc::Default) { -#endif - mRelocModel = llvm::Reloc::PIC_; - } - if (soname.getNumOccurrences() > 0 && !global.params.dll) { error(Loc(), "-soname can be used only when building a shared library"); } global.params.hdrStripPlainFunctions = !opts::hdrKeepAllBodies; + global.params.disableRedZone = opts::disableRedZone(); } void initializePasses() { @@ -1010,7 +990,8 @@ int cppmain(int argc, char **argv) { } // Set up the TargetMachine. - if ((m32bits || m64bits) && (!mArch.empty() || !mTargetTriple.empty())) { + const auto arch = getArchStr(); + if ((m32bits || m64bits) && (!arch.empty() || !mTargetTriple.empty())) { error(Loc(), "-m32 and -m64 switches cannot be used together with -march " "and -mtriple switches"); } @@ -1025,9 +1006,21 @@ int cppmain(int argc, char **argv) { fatal(); } + auto relocModel = getRelocModel(); +#if LDC_LLVM_VER >= 309 + if (global.params.dll && !relocModel.hasValue()) { +#else + if (global.params.dll && relocModel == llvm::Reloc::Default) { +#endif + relocModel = llvm::Reloc::PIC_; + } + gTargetMachine = createTargetMachine( - mTargetTriple, mArch, mCPU, mAttrs, bitness, mFloatABI, getRelocModel(), - mCodeModel, codeGenOptLevel(), disableFpElim, disableLinkerStripDead); + mTargetTriple, arch, opts::getCPUStr(), opts::getFeaturesStr(), bitness, + floatABI, relocModel, opts::getCodeModel(), codeGenOptLevel(), + disableLinkerStripDead); + + opts::setDefaultMathOptions(gTargetMachine->Options); #if LDC_LLVM_VER >= 308 static llvm::DataLayout DL = gTargetMachine->createDataLayout(); @@ -1043,6 +1036,7 @@ int cppmain(int argc, char **argv) { global.params.isLP64 = gDataLayout->getPointerSizeInBits() == 64; global.params.is64bit = triple->isArch64Bit(); global.params.hasObjectiveC = objc_isSupported(*triple); + global.params.dwarfVersion = gTargetMachine->Options.MCOptions.DwarfVersion; // mscoff enables slightly different handling of interface functions // in the front end global.params.mscoff = triple->isKnownWindowsMSVCEnvironment(); @@ -1050,8 +1044,6 @@ int cppmain(int argc, char **argv) { global.obj_ext = "obj"; } - opts::setDefaultMathOptions(*gTargetMachine); - // allocate the target abi gABI = TargetABI::getTarget(); diff --git a/driver/targetmachine.cpp b/driver/targetmachine.cpp index 99ce714ae4..d75a31b2c6 100644 --- a/driver/targetmachine.cpp +++ b/driver/targetmachine.cpp @@ -15,6 +15,7 @@ #include "driver/cl_options.h" #include "driver/targetmachine.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Triple.h" #include "llvm/MC/SubtargetFeature.h" @@ -27,6 +28,7 @@ #include "llvm/Target/TargetOptions.h" #include "llvm/IR/Module.h" #include "mars.h" +#include "driver/cl_options.h" #include "gen/logger.h" static const char *getABI(const llvm::Triple &triple) { @@ -197,28 +199,13 @@ static std::string getAArch64TargetCPU(const llvm::Triple &triple) { return "generic"; } -/// Returns the LLVM name of the target CPU to use given the provided -/// -mcpu argument and target triple. -static std::string getTargetCPU(const std::string &cpu, - const llvm::Triple &triple) { - if (!cpu.empty()) { - if (cpu != "native") { - return cpu; - } - - // FIXME: Reject attempts to use -mcpu=native unless the target matches - // the host. - std::string hostCPU = llvm::sys::getHostCPUName(); - if (!hostCPU.empty() && hostCPU != "generic") { - return hostCPU; - } - } - +/// Returns the LLVM name of the default CPU for the provided target triple. +static std::string getTargetCPU(const llvm::Triple &triple) { switch (triple.getArch()) { default: // We don't know about the specifics of this platform, just return the // empty string and let LLVM decide. - return cpu; + return ""; case llvm::Triple::x86: case llvm::Triple::x86_64: return getX86TargetCPU(triple); @@ -355,17 +342,18 @@ const llvm::Target *lookupTarget(const std::string &arch, llvm::Triple &triple, } llvm::TargetMachine * -createTargetMachine(std::string targetTriple, std::string arch, std::string cpu, - std::vector attrs, - ExplicitBitness::Type bitness, FloatABI::Type floatABI, +createTargetMachine(const std::string targetTriple, const std::string arch, + std::string cpu, const std::string featuresString, + const ExplicitBitness::Type bitness, + FloatABI::Type floatABI, #if LDC_LLVM_VER >= 309 llvm::Optional relocModel, #else llvm::Reloc::Model relocModel, #endif - llvm::CodeModel::Model codeModel, - llvm::CodeGenOpt::Level codeGenOptLevel, - bool noFramePointerElim, bool noLinkerStripDead) { + const llvm::CodeModel::Model codeModel, + const llvm::CodeGenOpt::Level codeGenOptLevel, + const bool noLinkerStripDead) { // Determine target triple. If the user didn't explicitly specify one, use // the one set at LLVM configure time. llvm::Triple triple; @@ -398,47 +386,40 @@ createTargetMachine(std::string targetTriple, std::string arch, std::string cpu, fatal(); } - // Package up features to be passed to target/subtarget. - llvm::SubtargetFeatures features; - features.getDefaultSubtargetFeatures(triple); - if (cpu == "native") { - llvm::StringMap hostFeatures; - if (llvm::sys::getHostCPUFeatures(hostFeatures)) { - for (const auto &hf : hostFeatures) { - features.AddFeature( - std::string(hf.second ? "+" : "-").append(hf.first())); - } - } - } - for (auto &attr : attrs) { - features.AddFeature(attr); - } - // With an empty CPU string, LLVM will default to the host CPU, which is // usually not what we want (expected behavior from other compilers is // to default to "generic"). - cpu = getTargetCPU(cpu, triple); + if (cpu.empty() || cpu == "generic") { + cpu = getTargetCPU(triple); + if (cpu.empty()) + cpu = "generic"; + } + + // Package up features to be passed to target/subtarget. + llvm::SmallVector features; + + // NOTE: needs a persistent (non-temporary) string + auto splitAndAddFeatures = [&features](llvm::StringRef str) { + str.split(features, ",", -1, /* KeepEmpty */ false); + }; + + llvm::SubtargetFeatures defaultSubtargetFeatures; + defaultSubtargetFeatures.getDefaultSubtargetFeatures(triple); + const std::string defaultSubtargetFeaturesString = + defaultSubtargetFeatures.getString(); + splitAndAddFeatures(defaultSubtargetFeaturesString); + + splitAndAddFeatures(featuresString); // cmpxchg16b is not available on old 64bit CPUs. Enable code generation // if the user did not make an explicit choice. if (cpu == "x86-64") { - const char *cx16_plus = "+cx16"; - const char *cx16_minus = "-cx16"; - bool cx16 = false; - for (auto &attr : attrs) { - if (attr == cx16_plus || attr == cx16_minus) { - cx16 = true; - } + const bool has_cx16 = + std::any_of(features.begin(), features.end(), + [](llvm::StringRef f) { return f.substr(1) == "cx16"; }); + if (!has_cx16) { + features.push_back("+cx16"); } - if (!cx16) { - features.AddFeature(cx16_plus); - } - } - - if (Logger::enabled()) { - Logger::println("Targeting '%s' (CPU '%s' with features '%s')", - triple.str().c_str(), cpu.c_str(), - features.getString().c_str()); } // Handle cases where LLVM picks wrong default relocModel @@ -473,26 +454,28 @@ createTargetMachine(std::string targetTriple, std::string arch, std::string cpu, } } - if (floatABI == FloatABI::Default) { + llvm::TargetOptions targetOptions = opts::InitTargetOptionsFromCodeGenFlags(); + if (targetOptions.MCOptions.ABIName.empty()) + targetOptions.MCOptions.ABIName = getABI(triple); + + auto ldcFloatABI = floatABI; + if (ldcFloatABI == FloatABI::Default) { switch (triple.getArch()) { default: // X86, ... - floatABI = FloatABI::Hard; + ldcFloatABI = FloatABI::Hard; break; case llvm::Triple::arm: case llvm::Triple::thumb: - floatABI = getARMFloatABI(triple, getLLVMArchSuffixForARM(cpu)); + ldcFloatABI = getARMFloatABI(triple, getLLVMArchSuffixForARM(cpu)); break; } } - llvm::TargetOptions targetOptions; - targetOptions.MCOptions.ABIName = getABI(triple); - - switch (floatABI) { + switch (ldcFloatABI) { default: llvm_unreachable("Floating point ABI type unknown."); case FloatABI::Soft: - features.AddFeature("+soft-float"); + features.push_back("+soft-float"); targetOptions.FloatABIType = llvm::FloatABI::Soft; break; case FloatABI::SoftFP: @@ -514,11 +497,20 @@ createTargetMachine(std::string targetTriple, std::string arch, std::string cpu, targetOptions.DataSections = true; } - return target->createTargetMachine(triple.str(), cpu, features.getString(), - targetOptions, relocModel, codeModel, + const std::string finalFeaturesString = + llvm::join(features.begin(), features.end(), ","); + + if (Logger::enabled()) { + Logger::println("Targeting '%s' (CPU '%s' with features '%s')", + triple.str().c_str(), cpu.c_str(), + finalFeaturesString.c_str()); + } + + return target->createTargetMachine(triple.str(), cpu, finalFeaturesString, + targetOptions, relocModel, opts::getCodeModel(), codeGenOptLevel); } - + ComputeBackend::Type getComputeTargetType(llvm::Module* m) { llvm::Triple::ArchType a = llvm::Triple(m->getTargetTriple()).getArch(); if (a == llvm::Triple::spir || a == llvm::Triple::spir64) diff --git a/driver/targetmachine.h b/driver/targetmachine.h index 91af541244..6033694b68 100644 --- a/driver/targetmachine.h +++ b/driver/targetmachine.h @@ -52,18 +52,19 @@ ComputeBackend::Type getComputeTargetType(llvm::Module*); * parameters and the host platform defaults. * * Does not depend on any global state. - */ -llvm::TargetMachine *createTargetMachine( - std::string targetTriple, std::string arch, std::string cpu, - std::vector attrs, ExplicitBitness::Type bitness, - FloatABI::Type floatABI, +*/ +llvm::TargetMachine * +createTargetMachine(std::string targetTriple, std::string arch, std::string cpu, + std::string featuresString, ExplicitBitness::Type bitness, + FloatABI::Type floatABI, #if LDC_LLVM_VER >= 309 - llvm::Optional relocModel, + llvm::Optional relocModel, #else - llvm::Reloc::Model relocModel, + llvm::Reloc::Model relocModel, #endif - llvm::CodeModel::Model codeModel, llvm::CodeGenOpt::Level codeGenOptLevel, - bool noFramePointerElim, bool noLinkerStripDead); + llvm::CodeModel::Model codeModel, + llvm::CodeGenOpt::Level codeGenOptLevel, + bool noLinkerStripDead); /** * Returns the Mips ABI which is used for code generation. diff --git a/gen/dcompute/targetCUDA.cpp b/gen/dcompute/targetCUDA.cpp index 10899094ff..d99ea09c3c 100644 --- a/gen/dcompute/targetCUDA.cpp +++ b/gen/dcompute/targetCUDA.cpp @@ -56,7 +56,7 @@ public: is64 ? "nvptx64-nvidia-cuda" : "nvptx-nvidia-cuda", is64 ? "nvptx64" : "nvptx", "sm_" + ldc::to_string(tversion / 10), {}, is64 ? ExplicitBitness::M64 : ExplicitBitness::M32, ::FloatABI::Hard, - llvm::Reloc::Static, llvm::CodeModel::Medium, codeGenOptLevel(), false, + llvm::Reloc::Static, llvm::CodeModel::Medium, codeGenOptLevel(), false); } diff --git a/gen/functions.cpp b/gen/functions.cpp index 1d91333d68..7be17eaa78 100644 --- a/gen/functions.cpp +++ b/gen/functions.cpp @@ -460,7 +460,7 @@ void applyTargetMachineAttributes(llvm::Function &func, // Frame pointer elimination func.addFnAttr("no-frame-pointer-elim", - opts::disableFpElim ? "true" : "false"); + opts::disableFPElim() ? "true" : "false"); } } // anonymous namespace