From ae9d43c167988b973eb76b92f34dab1481f9062a Mon Sep 17 00:00:00 2001 From: kinke Date: Wed, 20 Sep 2017 01:04:43 +0200 Subject: [PATCH] Use LLVM headers for shared codegen command-line options (#2148) I.e., llvm/CodeGen/CommandFlags.h which in turn includes llvm/MC/MCTargetOptionsCommandFlags.h. This gets rid of a few duplicates on our side and includes about 35 (depending on LLVM version) new command-line options. LLVM provides a helper function to set up the TargetOptions according to (most of) these options. Newer LLVM versions may add new options and we'll automatically inherit them, including setting up the TargetOptions accordingly. I did my best (TM) to remove a few unused/undesirable options and hide all remaining new ones except for `-fp-contract`. The lists will need to be tweaked from time to time. --- .circleci/config.yml | 4 +- .travis.yml | 2 +- CMakeLists.txt | 2 + driver/cache.cpp | 20 +++--- driver/cl_options-llvm.cpp | 64 ++++++++++++++++++ driver/cl_options-llvm.h | 36 ++++++++++ driver/cl_options.cpp | 121 +++++++++++++--------------------- driver/cl_options.h | 11 +--- driver/linker-gcc.cpp | 5 +- driver/main.cpp | 46 ++++++------- driver/targetmachine.cpp | 128 +++++++++++++++++------------------- driver/targetmachine.h | 19 +++--- gen/dcompute/targetCUDA.cpp | 2 +- gen/functions.cpp | 2 +- 14 files changed, 261 insertions(+), 201 deletions(-) create mode 100644 driver/cl_options-llvm.cpp create mode 100644 driver/cl_options-llvm.h 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