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.
This commit is contained in:
kinke 2017-09-20 01:04:43 +02:00 committed by GitHub
parent 0546bd406b
commit ae9d43c167
14 changed files with 261 additions and 201 deletions

View file

@ -58,7 +58,7 @@ jobs:
export HOST_LDMD=$PWD/ldc2-$HOST_LDC_VERSION-linux-x86_64/bin/ldmd2 export HOST_LDMD=$PWD/ldc2-$HOST_LDC_VERSION-linux-x86_64/bin/ldmd2
mkdir bootstrap mkdir bootstrap
cd 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 ninja -j3
bin/ldc2 -version bin/ldc2 -version
cd .. cd ..
@ -68,7 +68,7 @@ jobs:
export HOST_LDMD=$PWD/bootstrap/bin/ldmd2 export HOST_LDMD=$PWD/bootstrap/bin/ldmd2
mkdir build mkdir build
cd 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 ninja -j3 all all-test-runners
bin/ldc2 -version bin/ldc2 -version
cd .. cd ..

View file

@ -6,7 +6,7 @@ matrix:
include: include:
- os: linux - os: linux
d: ldc 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 - os: linux
d: ldc d: ldc
env: LLVM_VERSION=4.0.1 OPTS="-DLIB_SUFFIX=64" env: LLVM_VERSION=4.0.1 OPTS="-DLIB_SUFFIX=64"

View file

@ -339,6 +339,7 @@ set(DRV_SRC
driver/cache.cpp driver/cache.cpp
driver/cl_options.cpp driver/cl_options.cpp
driver/cl_options_sanitizers.cpp driver/cl_options_sanitizers.cpp
driver/cl_options-llvm.cpp
driver/codegenerator.cpp driver/codegenerator.cpp
driver/configfile.cpp driver/configfile.cpp
driver/dcomputecodegenerator.cpp driver/dcomputecodegenerator.cpp
@ -358,6 +359,7 @@ set(DRV_HDR
driver/cache_pruning.h driver/cache_pruning.h
driver/cl_options.h driver/cl_options.h
driver/cl_options_sanitizers.h driver/cl_options_sanitizers.h
driver/cl_options-llvm.h
driver/codegenerator.h driver/codegenerator.h
driver/configfile.h driver/configfile.h
driver/dcomputecodegenerator.h driver/dcomputecodegenerator.h

View file

@ -302,14 +302,18 @@ void outputIR2ObjRelevantCmdlineArgs(llvm::raw_ostream &hash_os) {
// sharing the cache). // sharing the cache).
outputOptimizationSettings(hash_os); outputOptimizationSettings(hash_os);
opts::outputSanitizerSettings(hash_os); opts::outputSanitizerSettings(hash_os);
hash_os << opts::mCPU; hash_os << opts::getCPUStr();
for (auto &attr : opts::mAttrs) { hash_os << opts::getFeaturesStr();
hash_os << attr; hash_os << opts::floatABI;
} #if LDC_LLVM_VER >= 309
hash_os << opts::mFloatABI; const auto relocModel = opts::getRelocModel();
hash_os << opts::mRelocModel; if (relocModel.hasValue())
hash_os << opts::mCodeModel; hash_os << relocModel.getValue();
hash_os << opts::disableFpElim; #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 // Output to `hash_os` all environment flags that influence object code output

View file

@ -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<bool>
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<Reloc::Model> 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

36
driver/cl_options-llvm.h Normal file
View file

@ -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<llvm::Reloc::Model> 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

View file

@ -134,10 +134,6 @@ static cl::opt<ubyte, true> debugInfo(
clEnumValN(3, "gline-tables-only", "Add line tables only")), clEnumValN(3, "gline-tables-only", "Add line tables only")),
cl::location(global.params.symdebug), cl::init(0)); cl::location(global.params.symdebug), cl::init(0));
static cl::opt<unsigned, true>
dwarfVersion("dwarf-version", cl::desc("Dwarf version"), cl::ZeroOrMore,
cl::location(global.params.dwarfVersion), cl::Hidden);
cl::opt<bool> noAsm("noasm", cl::desc("Disallow use of inline assembler"), cl::opt<bool> noAsm("noasm", cl::desc("Disallow use of inline assembler"),
cl::ZeroOrMore); cl::ZeroOrMore);
@ -175,12 +171,6 @@ static cl::opt<bool, true>
cl::desc("Remove generated object files on success"), cl::desc("Remove generated object files on success"),
cl::location(global.params.cleanupObjectFiles)); cl::location(global.params.cleanupObjectFiles));
// Disabling Red Zone
cl::opt<bool, true>
disableRedZone("disable-red-zone", cl::ZeroOrMore,
cl::desc("Do not emit code that uses the red zone."),
cl::location(global.params.disableRedZone));
// DDoc options // DDoc options
static cl::opt<bool, true> doDdoc("D", cl::desc("Generate documentation"), static cl::opt<bool, true> doDdoc("D", cl::desc("Generate documentation"),
cl::location(global.params.doDocComments), cl::location(global.params.doDocComments),
@ -296,21 +286,10 @@ cl::opt<std::string>
"'-deps' alone prints module dependencies " "'-deps' alone prints module dependencies "
"(imports/file/version/debug/lib)")); "(imports/file/version/debug/lib)"));
cl::opt<std::string> mArch("march", cl::ZeroOrMore,
cl::desc("Architecture to generate code for:"));
cl::opt<bool> m32bits("m32", cl::desc("32 bit target"), cl::ZeroOrMore); cl::opt<bool> m32bits("m32", cl::desc("32 bit target"), cl::ZeroOrMore);
cl::opt<bool> m64bits("m64", cl::desc("64 bit target"), cl::ZeroOrMore); cl::opt<bool> m64bits("m64", cl::desc("64 bit target"), cl::ZeroOrMore);
cl::opt<std::string>
mCPU("mcpu", cl::ZeroOrMore, cl::value_desc("cpu-name"), cl::init(""),
cl::desc("Target a specific cpu type (-mcpu=help for details)"));
cl::list<std::string>
mAttrs("mattr", cl::CommaSeparated, cl::value_desc("a1,+a2,-a3,..."),
cl::desc("Target specific attributes (-mattr=help for details)"));
cl::opt<std::string> mTargetTriple("mtriple", cl::ZeroOrMore, cl::opt<std::string> mTargetTriple("mtriple", cl::ZeroOrMore,
cl::desc("Override target triple")); cl::desc("Override target triple"));
@ -325,54 +304,7 @@ static cl::list<std::string, StringsAdapter> modFileAliasStrings(
cl::value_desc("<package.module>=<filespec>"), cl::value_desc("<package.module>=<filespec>"),
cl::location(modFileAliasStringsStore)); cl::location(modFileAliasStringsStore));
cl::opt<llvm::Reloc::Model> mRelocModel( FloatABI::Type floatABI; // Storage for the dynamically created float-abi option.
"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<llvm::CodeModel::Model> 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<FloatABI::Type> 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<bool>
disableFpElim("disable-fp-elim", cl::ZeroOrMore,
cl::desc("Disable frame pointer elimination optimization"));
static cl::opt<bool, true, FlagParser<bool>> static cl::opt<bool, true, FlagParser<bool>>
asserts("asserts", cl::ZeroOrMore, cl::desc("(*) Enable assertions"), asserts("asserts", cl::ZeroOrMore, cl::desc("(*) Enable assertions"),
@ -437,12 +369,10 @@ cl::opt<bool> disableLinkerStripDead(
// Math options // Math options
bool fFastMath; // Storage for the dynamically created ffast-math option. bool fFastMath; // Storage for the dynamically created ffast-math option.
llvm::FastMathFlags defaultFMF; llvm::FastMathFlags defaultFMF;
void setDefaultMathOptions(llvm::TargetMachine &target) { void setDefaultMathOptions(llvm::TargetOptions &targetOptions) {
if (fFastMath) { if (fFastMath) {
defaultFMF.setUnsafeAlgebra(); defaultFMF.setUnsafeAlgebra();
targetOptions.UnsafeFPMath = true;
llvm::TargetOptions &TO = target.Options;
TO.UnsafeFPMath = true;
} }
} }
@ -560,6 +490,7 @@ void createClashingOptions() {
// is a clash in the command line options. // is a clash in the command line options.
renameAndHide("color", "llvm-color"); renameAndHide("color", "llvm-color");
renameAndHide("ffast-math", "llvm-ffast-math"); renameAndHide("ffast-math", "llvm-ffast-math");
renameAndHide("float-abi", "llvm-float-abi");
// Step 2. Add the LDC options. // Step 2. Add the LDC options.
new cl::opt<bool, true, FlagParser<bool>>( new cl::opt<bool, true, FlagParser<bool>>(
@ -567,6 +498,19 @@ void createClashingOptions() {
cl::desc("(*) Force colored console output")); cl::desc("(*) Force colored console output"));
new cl::opt<bool, true>("ffast-math", cl::ZeroOrMore, cl::location(fFastMath), new cl::opt<bool, true>("ffast-math", cl::ZeroOrMore, cl::location(fFastMath),
cl::desc("Set @fastmath for all functions.")); cl::desc("Set @fastmath for all functions."));
new cl::opt<FloatABI::Type, true>(
"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 /// 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", "verify-region-info", "verify-scev", "verify-scev-maps",
"x86-early-ifcvt", "x86-use-vzeroupper", "x86-recip-refinement-steps", "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 // We enable -fdata-sections/-ffunction-sections by default where it makes
// sense for reducing code size, so hide them to avoid confusion. // 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 // on the target triple (and thus we do not know it until after the
// command // command
// line has been parsed). // 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<cl::Option *> &map = cl::getRegisteredOptions(); llvm::StringMap<cl::Option *> &map = cl::getRegisteredOptions();
for (const auto name : hiddenOptions) { for (const auto name : hiddenOptions) {
@ -622,6 +588,13 @@ void hideLLVMOptions() {
it->second->setHiddenFlag(cl::Hidden); it->second->setHiddenFlag(cl::Hidden);
} }
} }
for (const auto name : removedOptions) {
auto it = map.find(name);
if (it != map.end()) {
map.erase(it);
}
}
} }
} // namespace opts } // namespace opts

View file

@ -15,6 +15,7 @@
#ifndef LDC_DRIVER_CL_OPTIONS_H #ifndef LDC_DRIVER_CL_OPTIONS_H
#define LDC_DRIVER_CL_OPTIONS_H #define LDC_DRIVER_CL_OPTIONS_H
#include "driver/cl_options-llvm.h"
#include "driver/targetmachine.h" #include "driver/targetmachine.h"
#include "gen/cl_helpers.h" #include "gen/cl_helpers.h"
#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallVector.h"
@ -69,24 +70,18 @@ extern cl::opt<std::string> cacheDir;
extern cl::list<std::string> linkerSwitches; extern cl::list<std::string> linkerSwitches;
extern cl::list<std::string> ccSwitches; extern cl::list<std::string> ccSwitches;
extern cl::opt<std::string> mArch;
extern cl::opt<bool> m32bits; extern cl::opt<bool> m32bits;
extern cl::opt<bool> m64bits; extern cl::opt<bool> m64bits;
extern cl::opt<std::string> mCPU;
extern cl::list<std::string> mAttrs;
extern cl::opt<std::string> mTargetTriple; extern cl::opt<std::string> mTargetTriple;
extern cl::opt<std::string> mABI; extern cl::opt<std::string> mABI;
extern cl::opt<llvm::Reloc::Model> mRelocModel; extern FloatABI::Type floatABI;
extern cl::opt<llvm::CodeModel::Model> mCodeModel;
extern cl::opt<bool> disableFpElim;
extern cl::opt<FloatABI::Type> mFloatABI;
extern cl::opt<bool> linkonceTemplates; extern cl::opt<bool> linkonceTemplates;
extern cl::opt<bool> disableLinkerStripDead; extern cl::opt<bool> disableLinkerStripDead;
// Math options // Math options
extern bool fFastMath; extern bool fFastMath;
extern llvm::FastMathFlags defaultFMF; extern llvm::FastMathFlags defaultFMF;
void setDefaultMathOptions(llvm::TargetMachine &target); void setDefaultMathOptions(llvm::TargetOptions &targetOptions);
extern cl::opt<BOUNDSCHECK> boundsCheck; extern cl::opt<BOUNDSCHECK> boundsCheck;
extern bool nonSafeBoundsChecks; extern bool nonSafeBoundsChecks;

View file

@ -118,8 +118,9 @@ void ArgsBuilder::addLTOGoldPluginFlags() {
if (opts::isUsingThinLTO()) if (opts::isUsingThinLTO())
addLdFlag("-plugin-opt=thinlto"); addLdFlag("-plugin-opt=thinlto");
if (!opts::mCPU.empty()) const auto cpu = gTargetMachine->getTargetCPU();
addLdFlag(llvm::Twine("-plugin-opt=mcpu=") + opts::mCPU); 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 // 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. // the [0, 3] range that can be passed to the linker plugin.

View file

@ -104,18 +104,6 @@ static cl::opt<bool> linkDebugLib(
"link-debuglib", cl::ZeroOrMore, "link-debuglib", cl::ZeroOrMore,
cl::desc("Link with libraries specified in -debuglib, not -defaultlib")); cl::desc("Link with libraries specified in -debuglib, not -defaultlib"));
#if LDC_LLVM_VER >= 309
static inline llvm::Optional<llvm::Reloc::Model> 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. // This function exits the program.
void printVersion(llvm::raw_ostream &OS) { void printVersion(llvm::raw_ostream &OS) {
OS << "LDC - the LLVM D compiler (" << global.ldc_version << "):\n"; OS << "LDC - the LLVM D compiler (" << global.ldc_version << "):\n";
@ -372,8 +360,7 @@ void parseCommandLine(int argc, char **argv, Strings &sourceFiles,
const_cast<char **>(allArguments.data()), const_cast<char **>(allArguments.data()),
"LDC - the LLVM D compiler\n"); "LDC - the LLVM D compiler\n");
helpOnly = mCPU == "help" || helpOnly = opts::printTargetFeaturesHelp();
(std::find(mAttrs.begin(), mAttrs.end(), "help") != mAttrs.end());
if (helpOnly) { if (helpOnly) {
auto triple = llvm::Triple(cfg_triple); auto triple = llvm::Triple(cfg_triple);
std::string errMsg; 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"); 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) { if (soname.getNumOccurrences() > 0 && !global.params.dll) {
error(Loc(), "-soname can be used only when building a shared library"); error(Loc(), "-soname can be used only when building a shared library");
} }
global.params.hdrStripPlainFunctions = !opts::hdrKeepAllBodies; global.params.hdrStripPlainFunctions = !opts::hdrKeepAllBodies;
global.params.disableRedZone = opts::disableRedZone();
} }
void initializePasses() { void initializePasses() {
@ -1010,7 +990,8 @@ int cppmain(int argc, char **argv) {
} }
// Set up the TargetMachine. // 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 " error(Loc(), "-m32 and -m64 switches cannot be used together with -march "
"and -mtriple switches"); "and -mtriple switches");
} }
@ -1025,9 +1006,21 @@ int cppmain(int argc, char **argv) {
fatal(); 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( gTargetMachine = createTargetMachine(
mTargetTriple, mArch, mCPU, mAttrs, bitness, mFloatABI, getRelocModel(), mTargetTriple, arch, opts::getCPUStr(), opts::getFeaturesStr(), bitness,
mCodeModel, codeGenOptLevel(), disableFpElim, disableLinkerStripDead); floatABI, relocModel, opts::getCodeModel(), codeGenOptLevel(),
disableLinkerStripDead);
opts::setDefaultMathOptions(gTargetMachine->Options);
#if LDC_LLVM_VER >= 308 #if LDC_LLVM_VER >= 308
static llvm::DataLayout DL = gTargetMachine->createDataLayout(); static llvm::DataLayout DL = gTargetMachine->createDataLayout();
@ -1043,6 +1036,7 @@ int cppmain(int argc, char **argv) {
global.params.isLP64 = gDataLayout->getPointerSizeInBits() == 64; global.params.isLP64 = gDataLayout->getPointerSizeInBits() == 64;
global.params.is64bit = triple->isArch64Bit(); global.params.is64bit = triple->isArch64Bit();
global.params.hasObjectiveC = objc_isSupported(*triple); global.params.hasObjectiveC = objc_isSupported(*triple);
global.params.dwarfVersion = gTargetMachine->Options.MCOptions.DwarfVersion;
// mscoff enables slightly different handling of interface functions // mscoff enables slightly different handling of interface functions
// in the front end // in the front end
global.params.mscoff = triple->isKnownWindowsMSVCEnvironment(); global.params.mscoff = triple->isKnownWindowsMSVCEnvironment();
@ -1050,8 +1044,6 @@ int cppmain(int argc, char **argv) {
global.obj_ext = "obj"; global.obj_ext = "obj";
} }
opts::setDefaultMathOptions(*gTargetMachine);
// allocate the target abi // allocate the target abi
gABI = TargetABI::getTarget(); gABI = TargetABI::getTarget();

View file

@ -15,6 +15,7 @@
#include "driver/cl_options.h" #include "driver/cl_options.h"
#include "driver/targetmachine.h" #include "driver/targetmachine.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Triple.h" #include "llvm/ADT/Triple.h"
#include "llvm/MC/SubtargetFeature.h" #include "llvm/MC/SubtargetFeature.h"
@ -27,6 +28,7 @@
#include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetOptions.h"
#include "llvm/IR/Module.h" #include "llvm/IR/Module.h"
#include "mars.h" #include "mars.h"
#include "driver/cl_options.h"
#include "gen/logger.h" #include "gen/logger.h"
static const char *getABI(const llvm::Triple &triple) { static const char *getABI(const llvm::Triple &triple) {
@ -197,28 +199,13 @@ static std::string getAArch64TargetCPU(const llvm::Triple &triple) {
return "generic"; return "generic";
} }
/// Returns the LLVM name of the target CPU to use given the provided /// Returns the LLVM name of the default CPU for the provided target triple.
/// -mcpu argument and target triple. static std::string getTargetCPU(const llvm::Triple &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;
}
}
switch (triple.getArch()) { switch (triple.getArch()) {
default: default:
// We don't know about the specifics of this platform, just return the // We don't know about the specifics of this platform, just return the
// empty string and let LLVM decide. // empty string and let LLVM decide.
return cpu; return "";
case llvm::Triple::x86: case llvm::Triple::x86:
case llvm::Triple::x86_64: case llvm::Triple::x86_64:
return getX86TargetCPU(triple); return getX86TargetCPU(triple);
@ -355,17 +342,18 @@ const llvm::Target *lookupTarget(const std::string &arch, llvm::Triple &triple,
} }
llvm::TargetMachine * llvm::TargetMachine *
createTargetMachine(std::string targetTriple, std::string arch, std::string cpu, createTargetMachine(const std::string targetTriple, const std::string arch,
std::vector<std::string> attrs, std::string cpu, const std::string featuresString,
ExplicitBitness::Type bitness, FloatABI::Type floatABI, const ExplicitBitness::Type bitness,
FloatABI::Type floatABI,
#if LDC_LLVM_VER >= 309 #if LDC_LLVM_VER >= 309
llvm::Optional<llvm::Reloc::Model> relocModel, llvm::Optional<llvm::Reloc::Model> relocModel,
#else #else
llvm::Reloc::Model relocModel, llvm::Reloc::Model relocModel,
#endif #endif
llvm::CodeModel::Model codeModel, const llvm::CodeModel::Model codeModel,
llvm::CodeGenOpt::Level codeGenOptLevel, const llvm::CodeGenOpt::Level codeGenOptLevel,
bool noFramePointerElim, bool noLinkerStripDead) { const bool noLinkerStripDead) {
// Determine target triple. If the user didn't explicitly specify one, use // Determine target triple. If the user didn't explicitly specify one, use
// the one set at LLVM configure time. // the one set at LLVM configure time.
llvm::Triple triple; llvm::Triple triple;
@ -398,47 +386,40 @@ createTargetMachine(std::string targetTriple, std::string arch, std::string cpu,
fatal(); fatal();
} }
// Package up features to be passed to target/subtarget.
llvm::SubtargetFeatures features;
features.getDefaultSubtargetFeatures(triple);
if (cpu == "native") {
llvm::StringMap<bool> 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 // 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 // usually not what we want (expected behavior from other compilers is
// to default to "generic"). // 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<llvm::StringRef, 8> 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 // cmpxchg16b is not available on old 64bit CPUs. Enable code generation
// if the user did not make an explicit choice. // if the user did not make an explicit choice.
if (cpu == "x86-64") { if (cpu == "x86-64") {
const char *cx16_plus = "+cx16"; const bool has_cx16 =
const char *cx16_minus = "-cx16"; std::any_of(features.begin(), features.end(),
bool cx16 = false; [](llvm::StringRef f) { return f.substr(1) == "cx16"; });
for (auto &attr : attrs) { if (!has_cx16) {
if (attr == cx16_plus || attr == cx16_minus) { features.push_back("+cx16");
cx16 = true;
}
} }
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 // 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()) { switch (triple.getArch()) {
default: // X86, ... default: // X86, ...
floatABI = FloatABI::Hard; ldcFloatABI = FloatABI::Hard;
break; break;
case llvm::Triple::arm: case llvm::Triple::arm:
case llvm::Triple::thumb: case llvm::Triple::thumb:
floatABI = getARMFloatABI(triple, getLLVMArchSuffixForARM(cpu)); ldcFloatABI = getARMFloatABI(triple, getLLVMArchSuffixForARM(cpu));
break; break;
} }
} }
llvm::TargetOptions targetOptions; switch (ldcFloatABI) {
targetOptions.MCOptions.ABIName = getABI(triple);
switch (floatABI) {
default: default:
llvm_unreachable("Floating point ABI type unknown."); llvm_unreachable("Floating point ABI type unknown.");
case FloatABI::Soft: case FloatABI::Soft:
features.AddFeature("+soft-float"); features.push_back("+soft-float");
targetOptions.FloatABIType = llvm::FloatABI::Soft; targetOptions.FloatABIType = llvm::FloatABI::Soft;
break; break;
case FloatABI::SoftFP: case FloatABI::SoftFP:
@ -514,11 +497,20 @@ createTargetMachine(std::string targetTriple, std::string arch, std::string cpu,
targetOptions.DataSections = true; targetOptions.DataSections = true;
} }
return target->createTargetMachine(triple.str(), cpu, features.getString(), const std::string finalFeaturesString =
targetOptions, relocModel, codeModel, 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); codeGenOptLevel);
} }
ComputeBackend::Type getComputeTargetType(llvm::Module* m) { ComputeBackend::Type getComputeTargetType(llvm::Module* m) {
llvm::Triple::ArchType a = llvm::Triple(m->getTargetTriple()).getArch(); llvm::Triple::ArchType a = llvm::Triple(m->getTargetTriple()).getArch();
if (a == llvm::Triple::spir || a == llvm::Triple::spir64) if (a == llvm::Triple::spir || a == llvm::Triple::spir64)

View file

@ -52,18 +52,19 @@ ComputeBackend::Type getComputeTargetType(llvm::Module*);
* parameters and the host platform defaults. * parameters and the host platform defaults.
* *
* Does not depend on any global state. * Does not depend on any global state.
*/ */
llvm::TargetMachine *createTargetMachine( llvm::TargetMachine *
std::string targetTriple, std::string arch, std::string cpu, createTargetMachine(std::string targetTriple, std::string arch, std::string cpu,
std::vector<std::string> attrs, ExplicitBitness::Type bitness, std::string featuresString, ExplicitBitness::Type bitness,
FloatABI::Type floatABI, FloatABI::Type floatABI,
#if LDC_LLVM_VER >= 309 #if LDC_LLVM_VER >= 309
llvm::Optional<llvm::Reloc::Model> relocModel, llvm::Optional<llvm::Reloc::Model> relocModel,
#else #else
llvm::Reloc::Model relocModel, llvm::Reloc::Model relocModel,
#endif #endif
llvm::CodeModel::Model codeModel, llvm::CodeGenOpt::Level codeGenOptLevel, llvm::CodeModel::Model codeModel,
bool noFramePointerElim, bool noLinkerStripDead); llvm::CodeGenOpt::Level codeGenOptLevel,
bool noLinkerStripDead);
/** /**
* Returns the Mips ABI which is used for code generation. * Returns the Mips ABI which is used for code generation.

View file

@ -56,7 +56,7 @@ public:
is64 ? "nvptx64-nvidia-cuda" : "nvptx-nvidia-cuda", is64 ? "nvptx64-nvidia-cuda" : "nvptx-nvidia-cuda",
is64 ? "nvptx64" : "nvptx", "sm_" + ldc::to_string(tversion / 10), {}, is64 ? "nvptx64" : "nvptx", "sm_" + ldc::to_string(tversion / 10), {},
is64 ? ExplicitBitness::M64 : ExplicitBitness::M32, ::FloatABI::Hard, is64 ? ExplicitBitness::M64 : ExplicitBitness::M32, ::FloatABI::Hard,
llvm::Reloc::Static, llvm::CodeModel::Medium, codeGenOptLevel(), false, llvm::Reloc::Static, llvm::CodeModel::Medium, codeGenOptLevel(),
false); false);
} }

View file

@ -460,7 +460,7 @@ void applyTargetMachineAttributes(llvm::Function &func,
// Frame pointer elimination // Frame pointer elimination
func.addFnAttr("no-frame-pointer-elim", func.addFnAttr("no-frame-pointer-elim",
opts::disableFpElim ? "true" : "false"); opts::disableFPElim() ? "true" : "false");
} }
} // anonymous namespace } // anonymous namespace