mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-15 12:23:13 +01:00
Merge pull request #488 from klickverbot/arm
Phobos "Hello World" compiles now on ARM. No EH support yet.
This commit is contained in:
@@ -1,21 +1,15 @@
|
||||
# Find the libconfig++ includes and library
|
||||
# - Find the libconfig++ includes and library
|
||||
#
|
||||
# This module defines
|
||||
# LIBCONFIG++_INCLUDE_DIR, where to find libconfig++ include files, etc.
|
||||
# LIBCONFIG++_LIBRARY, the library to link against to use libconfig++.
|
||||
# LIBCONFIG++_FOUND, If false, do not try to use libconfig++.
|
||||
|
||||
set(LIBCONFIG++_FOUND FALSE)
|
||||
|
||||
find_path(LIBCONFIG++_INCLUDE_DIR libconfig.h++)
|
||||
|
||||
find_library(LIBCONFIG++_LIBRARY config++)
|
||||
|
||||
if (LIBCONFIG++_INCLUDE_DIR AND LIBCONFIG++_LIBRARY)
|
||||
set(LIBCONFIG++_FOUND TRUE)
|
||||
endif (LIBCONFIG++_INCLUDE_DIR AND LIBCONFIG++_LIBRARY)
|
||||
|
||||
# Use the default CMake facilities for handling QUIET/REQUIRED.
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(LIBCONFIG++
|
||||
find_package_handle_standard_args(LibConfig++
|
||||
REQUIRED_VARS LIBCONFIG++_INCLUDE_DIR LIBCONFIG++_LIBRARY)
|
||||
|
||||
@@ -315,6 +315,16 @@ cl::opt<llvm::CodeModel::Model> mCodeModel("code-model",
|
||||
clEnumValN(llvm::CodeModel::Large, "large", "Large code model"),
|
||||
clEnumValEnd));
|
||||
|
||||
cl::opt<FloatABI::Type> mFloatABI("float-abi",
|
||||
cl::desc("ABI/operations to use for floating-point types:"),
|
||||
cl::init(FloatABI::Default),
|
||||
cl::values(
|
||||
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"),
|
||||
clEnumValEnd));
|
||||
|
||||
static cl::opt<bool, true, FlagParser> asserts("asserts",
|
||||
cl::desc("(*) Enable assertions"),
|
||||
cl::value_desc("bool"),
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#ifndef LDC_DRIVER_CL_OPTIONS_H
|
||||
#define LDC_DRIVER_CL_OPTIONS_H
|
||||
|
||||
#include "driver/targetmachine.h"
|
||||
#include "gen/cl_helpers.h"
|
||||
#include "llvm/Support/CodeGen.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
@@ -60,6 +61,7 @@ namespace opts {
|
||||
extern cl::opt<std::string> mTargetTriple;
|
||||
extern cl::opt<llvm::Reloc::Model> mRelocModel;
|
||||
extern cl::opt<llvm::CodeModel::Model> mCodeModel;
|
||||
extern cl::opt<FloatABI::Type> mFloatABI;
|
||||
extern cl::opt<bool, true> singleObj;
|
||||
extern cl::opt<bool> linkonceTemplates;
|
||||
|
||||
|
||||
@@ -635,17 +635,21 @@ int main(int argc, char **argv)
|
||||
if (global.errors)
|
||||
fatal();
|
||||
|
||||
gTargetMachine = createTargetMachine(mTargetTriple, mArch, mCPU, mAttrs, bitness,
|
||||
mRelocModel, mCodeModel, codeGenOptLevel(), global.params.symdebug);
|
||||
llvm::Triple targetTriple = llvm::Triple(gTargetMachine->getTargetTriple());
|
||||
global.params.targetTriple = targetTriple;
|
||||
global.params.trace = false;
|
||||
global.params.isLinux = targetTriple.getOS() == llvm::Triple::Linux;
|
||||
global.params.isOSX = targetTriple.isMacOSX();
|
||||
global.params.isWindows = targetTriple.isOSWindows();
|
||||
global.params.isFreeBSD = targetTriple.getOS() == llvm::Triple::FreeBSD;
|
||||
global.params.isOpenBSD = targetTriple.getOS() == llvm::Triple::OpenBSD;
|
||||
global.params.isSolaris = targetTriple.getOS() == llvm::Triple::Solaris;
|
||||
gTargetMachine = createTargetMachine(mTargetTriple, mArch, mCPU, mAttrs,
|
||||
bitness, mFloatABI, mRelocModel, mCodeModel, codeGenOptLevel(),
|
||||
global.params.symdebug);
|
||||
|
||||
{
|
||||
llvm::Triple triple = llvm::Triple(gTargetMachine->getTargetTriple());
|
||||
global.params.targetTriple = triple;
|
||||
global.params.isLinux = triple.getOS() == llvm::Triple::Linux;
|
||||
global.params.isOSX = triple.isMacOSX();
|
||||
global.params.isWindows = triple.isOSWindows();
|
||||
global.params.isFreeBSD = triple.getOS() == llvm::Triple::FreeBSD;
|
||||
global.params.isOpenBSD = triple.getOS() == llvm::Triple::OpenBSD;
|
||||
global.params.isSolaris = triple.getOS() == llvm::Triple::Solaris;
|
||||
global.params.is64bit = triple.isArch64Bit();
|
||||
}
|
||||
|
||||
#if LDC_LLVM_VER >= 302
|
||||
gDataLayout = gTargetMachine->getDataLayout();
|
||||
@@ -653,9 +657,6 @@ int main(int argc, char **argv)
|
||||
gDataLayout = gTargetMachine->getTargetData();
|
||||
#endif
|
||||
|
||||
// Starting with LLVM 3.1 we could also use global.params.targetTriple.isArch64Bit();
|
||||
global.params.is64bit = gDataLayout->getPointerSizeInBits(ADDRESS_SPACE) == 64;
|
||||
|
||||
// Set predefined version identifiers.
|
||||
registerPredefinedVersions();
|
||||
|
||||
|
||||
@@ -8,47 +8,35 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Note: The target CPU detection logic has been adapted from Clang
|
||||
// (lib/Driver/Tools.cpp).
|
||||
// (Tools.cpp and ToolChain.cpp in lib/Driver, the latter seems to have the
|
||||
// more up-to-date version).
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "driver/targetmachine.h"
|
||||
#include "llvm/ADT/StringSwitch.h"
|
||||
#include "llvm/ADT/Triple.h"
|
||||
#include "llvm/MC/SubtargetFeature.h"
|
||||
#include "llvm/Support/Host.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/TargetRegistry.h"
|
||||
#include "llvm/Support/TargetSelect.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include "llvm/Target/TargetOptions.h"
|
||||
#include "mars.h"
|
||||
#include "gen/logger.h"
|
||||
|
||||
|
||||
static std::string getX86TargetCPU(std::string arch,
|
||||
const llvm::Triple &triple)
|
||||
static std::string getX86TargetCPU(const llvm::Triple &triple)
|
||||
{
|
||||
if (!arch.empty()) {
|
||||
if (arch != "native")
|
||||
return arch;
|
||||
|
||||
// FIXME: Reject attempts to use -march=native unless the target matches
|
||||
// the host.
|
||||
//
|
||||
// FIXME: We should also incorporate the detected target features for use
|
||||
// with -native.
|
||||
std::string cpu = llvm::sys::getHostCPUName();
|
||||
if (!cpu.empty() && cpu != "generic")
|
||||
return cpu;
|
||||
}
|
||||
|
||||
// Select the default CPU if none was given (or detection failed).
|
||||
|
||||
bool is64Bit = triple.getArch() == llvm::Triple::x86_64;
|
||||
|
||||
// Intel Macs are relatively recent, take advantage of that.
|
||||
if (triple.isOSDarwin())
|
||||
return is64Bit ? "core2" : "yonah";
|
||||
return triple.isArch64Bit() ? "core2" : "yonah";
|
||||
|
||||
// Everything else goes to x86-64 in 64-bit mode.
|
||||
if (is64Bit)
|
||||
if (triple.isArch64Bit())
|
||||
return "x86-64";
|
||||
|
||||
if (triple.getOSName().startswith("haiku"))
|
||||
@@ -72,98 +60,268 @@ static std::string getX86TargetCPU(std::string arch,
|
||||
return "pentium4";
|
||||
}
|
||||
|
||||
static std::string getARMTargetCPU(const llvm::Triple &triple)
|
||||
{
|
||||
const char *result = llvm::StringSwitch<const char *>(triple.getArchName())
|
||||
.Cases("armv2", "armv2a","arm2")
|
||||
.Case("armv3", "arm6")
|
||||
.Case("armv3m", "arm7m")
|
||||
.Case("armv4", "strongarm")
|
||||
.Case("armv4t", "arm7tdmi")
|
||||
.Cases("armv5", "armv5t", "arm10tdmi")
|
||||
.Cases("armv5e", "armv5te", "arm1026ejs")
|
||||
.Case("armv5tej", "arm926ej-s")
|
||||
.Cases("armv6", "armv6k", "arm1136jf-s")
|
||||
.Case("armv6j", "arm1136j-s")
|
||||
.Cases("armv6z", "armv6zk", "arm1176jzf-s")
|
||||
.Case("armv6t2", "arm1156t2-s")
|
||||
.Cases("armv6m", "armv6-m", "cortex-m0")
|
||||
.Cases("armv7", "armv7a", "armv7-a", "cortex-a8")
|
||||
.Cases("armv7l", "armv7-l", "cortex-a8")
|
||||
.Cases("armv7f", "armv7-f", "cortex-a9-mp")
|
||||
.Cases("armv7s", "armv7-s", "swift")
|
||||
.Cases("armv7r", "armv7-r", "cortex-r4")
|
||||
.Cases("armv7m", "armv7-m", "cortex-m3")
|
||||
.Cases("armv7em", "armv7e-m", "cortex-m4")
|
||||
.Cases("armv8", "armv8a", "armv8-a", "cortex-a53")
|
||||
.Case("ep9312", "ep9312")
|
||||
.Case("iwmmxt", "iwmmxt")
|
||||
.Case("xscale", "xscale")
|
||||
// If all else failed, return the most base CPU with thumb interworking
|
||||
// supported by LLVM.
|
||||
.Default(0);
|
||||
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
return (triple.getEnvironment() == llvm::Triple::GNUEABIHF) ?
|
||||
"arm1176jzf-s" : "arm7tdmi";
|
||||
}
|
||||
|
||||
/// 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;
|
||||
}
|
||||
|
||||
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;
|
||||
case llvm::Triple::x86:
|
||||
case llvm::Triple::x86_64:
|
||||
return getX86TargetCPU(triple);
|
||||
case llvm::Triple::arm:
|
||||
return getARMTargetCPU(triple);
|
||||
}
|
||||
}
|
||||
|
||||
static const char *getLLVMArchSuffixForARM(llvm::StringRef CPU)
|
||||
{
|
||||
return llvm::StringSwitch<const char *>(CPU)
|
||||
.Case("strongarm", "v4")
|
||||
.Cases("arm7tdmi", "arm7tdmi-s", "arm710t", "v4t")
|
||||
.Cases("arm720t", "arm9", "arm9tdmi", "v4t")
|
||||
.Cases("arm920", "arm920t", "arm922t", "v4t")
|
||||
.Cases("arm940t", "ep9312","v4t")
|
||||
.Cases("arm10tdmi", "arm1020t", "v5")
|
||||
.Cases("arm9e", "arm926ej-s", "arm946e-s", "v5e")
|
||||
.Cases("arm966e-s", "arm968e-s", "arm10e", "v5e")
|
||||
.Cases("arm1020e", "arm1022e", "xscale", "iwmmxt", "v5e")
|
||||
.Cases("arm1136j-s", "arm1136jf-s", "arm1176jz-s", "v6")
|
||||
.Cases("arm1176jzf-s", "mpcorenovfp", "mpcore", "v6")
|
||||
.Cases("arm1156t2-s", "arm1156t2f-s", "v6t2")
|
||||
.Cases("cortex-a5", "cortex-a7", "cortex-a8", "v7")
|
||||
.Cases("cortex-a9", "cortex-a12", "cortex-a15", "v7")
|
||||
.Cases("cortex-r4", "cortex-r5", "v7r")
|
||||
.Case("cortex-m0", "v6m")
|
||||
.Case("cortex-m3", "v7m")
|
||||
.Case("cortex-m4", "v7em")
|
||||
.Case("cortex-a9-mp", "v7f")
|
||||
.Case("swift", "v7s")
|
||||
.Case("cortex-a53", "v8")
|
||||
.Default("");
|
||||
}
|
||||
|
||||
static FloatABI::Type getARMFloatABI(const llvm::Triple &triple,
|
||||
const char* llvmArchSuffix)
|
||||
{
|
||||
switch (triple.getOS()) {
|
||||
case llvm::Triple::Darwin:
|
||||
case llvm::Triple::MacOSX:
|
||||
case llvm::Triple::IOS: {
|
||||
// Darwin defaults to "softfp" for v6 and v7.
|
||||
if (llvm::StringRef(llvmArchSuffix).startswith("v6") ||
|
||||
llvm::StringRef(llvmArchSuffix).startswith("v7"))
|
||||
return FloatABI::SoftFP;
|
||||
return FloatABI::Soft;
|
||||
}
|
||||
|
||||
case llvm::Triple::FreeBSD:
|
||||
// FreeBSD defaults to soft float
|
||||
return FloatABI::Soft;
|
||||
|
||||
default:
|
||||
switch(triple.getEnvironment()) {
|
||||
case llvm::Triple::GNUEABIHF:
|
||||
return FloatABI::Hard;
|
||||
case llvm::Triple::GNUEABI:
|
||||
return FloatABI::SoftFP;
|
||||
case llvm::Triple::EABI:
|
||||
// EABI is always AAPCS, and if it was not marked 'hard', it's softfp
|
||||
return FloatABI::SoftFP;
|
||||
#if LDC_LLVM_VER >= 302
|
||||
case llvm::Triple::Android: {
|
||||
if (llvm::StringRef(llvmArchSuffix).startswith("v7"))
|
||||
return FloatABI::SoftFP;
|
||||
return FloatABI::Soft;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
// Assume "soft".
|
||||
// TODO: Warn the user we are guessing.
|
||||
return FloatABI::Soft;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Looks up a target based on an arch name and a target triple.
|
||||
///
|
||||
/// If the arch name is non-empty, then the lookup is done by arch. Otherwise,
|
||||
/// the target triple is used.
|
||||
///
|
||||
/// This has been adapted from the corresponding LLVM 3.2+ overload of
|
||||
/// llvm::TargetRegistry::lookupTarget. Once support for LLVM 3.1 is dropped,
|
||||
/// the registry method can be used instead.
|
||||
const llvm::Target *lookupTarget(const std::string &arch, llvm::Triple &triple,
|
||||
std::string &errorMsg)
|
||||
{
|
||||
// Allocate target machine. First, check whether the user has explicitly
|
||||
// specified an architecture to compile for. If so we have to look it up by
|
||||
// name, because it might be a backend that has no mapping to a target triple.
|
||||
const llvm::Target *target = 0;
|
||||
if (!arch.empty())
|
||||
{
|
||||
for (llvm::TargetRegistry::iterator it = llvm::TargetRegistry::begin(),
|
||||
ie = llvm::TargetRegistry::end(); it != ie; ++it)
|
||||
{
|
||||
if (arch == it->getName())
|
||||
{
|
||||
target = &*it;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!target)
|
||||
{
|
||||
errorMsg = "invalid target architecture '" + arch + "', see "
|
||||
"-version for a list of supported targets.";
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Adjust the triple to match (if known), otherwise stick with the
|
||||
// given triple.
|
||||
llvm::Triple::ArchType Type = llvm::Triple::getArchTypeForLLVMName(arch);
|
||||
if (Type != llvm::Triple::UnknownArch)
|
||||
triple.setArch(Type);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string tempError;
|
||||
target = llvm::TargetRegistry::lookupTarget(triple.getTriple(), tempError);
|
||||
if (!target)
|
||||
{
|
||||
errorMsg = "unable to get target for '" + triple.getTriple() +
|
||||
"', see -version and -mtriple.";
|
||||
}
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
llvm::TargetMachine* createTargetMachine(
|
||||
std::string targetTriple,
|
||||
std::string arch,
|
||||
std::string cpu,
|
||||
std::vector<std::string> attrs,
|
||||
ExplicitBitness::Type bitness,
|
||||
FloatABI::Type floatABI,
|
||||
llvm::Reloc::Model relocModel,
|
||||
llvm::CodeModel::Model codeModel,
|
||||
llvm::CodeGenOpt::Level codeGenOptLevel,
|
||||
bool genDebugInfo)
|
||||
{
|
||||
// override triple if needed
|
||||
std::string defaultTriple = llvm::sys::getDefaultTargetTriple();
|
||||
if (sizeof(void*) == 4 && bitness == ExplicitBitness::M64)
|
||||
{
|
||||
defaultTriple = llvm::Triple(defaultTriple).get64BitArchVariant().str();
|
||||
}
|
||||
else if (sizeof(void*) == 8 && bitness == ExplicitBitness::M32)
|
||||
{
|
||||
defaultTriple = llvm::Triple(defaultTriple).get32BitArchVariant().str();
|
||||
}
|
||||
|
||||
// Determine target triple. If the user didn't explicitly specify one, use
|
||||
// the one set at LLVM configure time.
|
||||
llvm::Triple triple;
|
||||
|
||||
// did the user override the target triple?
|
||||
if (targetTriple.empty())
|
||||
{
|
||||
if (!arch.empty())
|
||||
triple = llvm::Triple(llvm::sys::getDefaultTargetTriple());
|
||||
|
||||
// Handle -m32/-m64.
|
||||
if (sizeof(void*) == 4 && bitness == ExplicitBitness::M64)
|
||||
{
|
||||
error("you must specify a target triple as well with -mtriple when using the -arch option");
|
||||
fatal();
|
||||
triple = triple.get64BitArchVariant();
|
||||
}
|
||||
else if (sizeof(void*) == 8 && bitness == ExplicitBitness::M32)
|
||||
{
|
||||
triple = triple.get32BitArchVariant();
|
||||
}
|
||||
triple = llvm::Triple(defaultTriple);
|
||||
}
|
||||
else
|
||||
{
|
||||
triple = llvm::Triple(llvm::Triple::normalize(targetTriple));
|
||||
}
|
||||
|
||||
// Allocate target machine.
|
||||
const llvm::Target *theTarget = NULL;
|
||||
// Check whether the user has explicitly specified an architecture to compile for.
|
||||
if (arch.empty())
|
||||
// Look up the LLVM backend to use. This also updates triple with the
|
||||
// user-specified arch, if any.
|
||||
std::string errMsg;
|
||||
const llvm::Target *target = lookupTarget(arch, triple, errMsg);
|
||||
if (target == 0)
|
||||
{
|
||||
std::string Err;
|
||||
theTarget = llvm::TargetRegistry::lookupTarget(triple.str(), Err);
|
||||
if (theTarget == 0)
|
||||
{
|
||||
error("%s Please use the -march option.", Err.c_str());
|
||||
fatal();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (llvm::TargetRegistry::iterator it = llvm::TargetRegistry::begin(),
|
||||
ie = llvm::TargetRegistry::end(); it != ie; ++it)
|
||||
{
|
||||
if (arch == it->getName())
|
||||
{
|
||||
theTarget = &*it;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!theTarget)
|
||||
{
|
||||
error("invalid target '%s'", arch.c_str());
|
||||
fatal();
|
||||
}
|
||||
error("%s", errMsg.c_str());
|
||||
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))
|
||||
{
|
||||
llvm::StringMapConstIterator<bool> i = hostFeatures.begin(),
|
||||
end = hostFeatures.end();
|
||||
for (; i != end; ++i)
|
||||
features.AddFeature(i->first(), i->second);
|
||||
}
|
||||
}
|
||||
for (unsigned i = 0; i < attrs.size(); ++i)
|
||||
features.AddFeature(attrs[i]);
|
||||
|
||||
// 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").
|
||||
if (cpu.empty())
|
||||
{
|
||||
if (triple.getArch() == llvm::Triple::x86_64 ||
|
||||
triple.getArch() == llvm::Triple::x86)
|
||||
{
|
||||
cpu = getX86TargetCPU(arch, triple);
|
||||
}
|
||||
}
|
||||
cpu = getTargetCPU(cpu, triple);
|
||||
|
||||
// Package up features to be passed to target/subtarget
|
||||
std::string FeaturesStr;
|
||||
if (cpu.size() || attrs.size())
|
||||
if (Logger::enabled())
|
||||
{
|
||||
llvm::SubtargetFeatures Features;
|
||||
for (unsigned i = 0; i != attrs.size(); ++i)
|
||||
Features.AddFeature(attrs[i]);
|
||||
FeaturesStr = Features.getString();
|
||||
Logger::println("Targeting '%s' (CPU '%s' with features '%s')",
|
||||
triple.str().c_str(), cpu.c_str(), features.getString().c_str());
|
||||
}
|
||||
|
||||
if (triple.isMacOSX() && relocModel == llvm::Reloc::Default)
|
||||
@@ -173,13 +331,60 @@ llvm::TargetMachine* createTargetMachine(
|
||||
relocModel = llvm::Reloc::PIC_;
|
||||
}
|
||||
|
||||
if (floatABI == FloatABI::Default)
|
||||
{
|
||||
switch (triple.getArch())
|
||||
{
|
||||
default: // X86, ...
|
||||
floatABI = FloatABI::Hard;
|
||||
break;
|
||||
case llvm::Triple::arm:
|
||||
floatABI = getARMFloatABI(triple, getLLVMArchSuffixForARM(cpu));
|
||||
break;
|
||||
case llvm::Triple::thumb:
|
||||
floatABI = FloatABI::Soft;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (triple.getArch() == llvm::Triple::arm)
|
||||
{
|
||||
// On ARM, we want to use EHABI exception handling, as we don't support
|
||||
// SJLJ EH in druntime. Unfortunately, it is still in a partly
|
||||
// experimental state, and the -arm-enable-ehabi-descriptors command
|
||||
// line option is not exposed via an internal API at all.
|
||||
const char *backendArgs[3] = {
|
||||
"ldc2", // Fake name, irrelevant.
|
||||
"-arm-enable-ehabi",
|
||||
"-arm-enable-ehabi-descriptors"
|
||||
};
|
||||
llvm::cl::ParseCommandLineOptions(3, backendArgs);
|
||||
}
|
||||
|
||||
llvm::TargetOptions targetOptions;
|
||||
targetOptions.NoFramePointerElim = genDebugInfo;
|
||||
|
||||
return theTarget->createTargetMachine(
|
||||
switch (floatABI)
|
||||
{
|
||||
default: llvm_unreachable("Floating point ABI type unknown.");
|
||||
case FloatABI::Soft:
|
||||
targetOptions.UseSoftFloat = true;
|
||||
targetOptions.FloatABIType = llvm::FloatABI::Soft;
|
||||
break;
|
||||
case FloatABI::SoftFP:
|
||||
targetOptions.UseSoftFloat = false;
|
||||
targetOptions.FloatABIType = llvm::FloatABI::Soft;
|
||||
break;
|
||||
case FloatABI::Hard:
|
||||
targetOptions.UseSoftFloat = false;
|
||||
targetOptions.FloatABIType = llvm::FloatABI::Hard;
|
||||
break;
|
||||
}
|
||||
|
||||
return target->createTargetMachine(
|
||||
triple.str(),
|
||||
cpu,
|
||||
FeaturesStr,
|
||||
features.getString(),
|
||||
targetOptions,
|
||||
relocModel,
|
||||
codeModel,
|
||||
|
||||
@@ -27,6 +27,15 @@ namespace ExplicitBitness {
|
||||
};
|
||||
}
|
||||
|
||||
namespace FloatABI {
|
||||
enum Type {
|
||||
Default,
|
||||
Soft,
|
||||
SoftFP,
|
||||
Hard
|
||||
};
|
||||
}
|
||||
|
||||
namespace llvm { class TargetMachine; }
|
||||
|
||||
/**
|
||||
@@ -41,6 +50,7 @@ llvm::TargetMachine* createTargetMachine(
|
||||
std::string cpu,
|
||||
std::vector<std::string> attrs,
|
||||
ExplicitBitness::Type bitness,
|
||||
FloatABI::Type floatABI,
|
||||
llvm::Reloc::Model relocModel,
|
||||
llvm::CodeModel::Model codeModel,
|
||||
llvm::CodeGenOpt::Level codeGenOptLevel,
|
||||
|
||||
@@ -108,6 +108,11 @@ if(UNIX)
|
||||
endif()
|
||||
list(REMOVE_ITEM LDC_D ${RUNTIME_DIR}/src/ldc/eh2.d)
|
||||
list(REMOVE_ITEM DCRT_C ${RUNTIME_DC_DIR}/msvc.c)
|
||||
|
||||
# Using CMAKE_SYSTEM_PROCESSOR might be inacurrate when somebody is
|
||||
# cross-compiling by just setting the tool executbles to a cross toolchain,
|
||||
# so just always include the file.
|
||||
list(APPEND DCRT_C ${RUNTIME_DIR}/src/ldc/arm_unwind.c)
|
||||
elseif(WIN32)
|
||||
list(APPEND CORE_D_SYS ${CORE_D_WIN})
|
||||
if (MSVC)
|
||||
|
||||
Submodule runtime/druntime updated: a116bff228...822720b863
Reference in New Issue
Block a user