diff --git a/driver/main.cpp b/driver/main.cpp index d29da866..3ed1d247 100644 --- a/driver/main.cpp +++ b/driver/main.cpp @@ -23,7 +23,6 @@ #include "gen/irstate.h" #include "gen/linkage.h" #include "gen/llvm.h" -#include "gen/llvmcompat.h" #include "gen/logger.h" #include "gen/metadata.h" #include "gen/optimizer.h" diff --git a/driver/target.cpp b/driver/target.cpp index b2c56192..f01d9089 100644 --- a/driver/target.cpp +++ b/driver/target.cpp @@ -6,8 +6,15 @@ // file for details. // //===----------------------------------------------------------------------===// +// +// Note: The target CPU detection logic has been adapted from Clang +// (lib/Driver/Tools.cpp). +// +//===----------------------------------------------------------------------===// #include "driver/target.h" +#include "gen/llvmcompat.h" +#include "llvm/ADT/Triple.h" #include "llvm/MC/SubtargetFeature.h" #include "llvm/Support/Host.h" #include "llvm/Support/TargetRegistry.h" @@ -16,6 +23,57 @@ #include "llvm/Target/TargetOptions.h" #include "mars.h" + +static std::string getX86TargetCPU(std::string arch, + 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; + + if (triple.isOSDarwin()) + return is64Bit ? "core2" : "yonah"; + + // Everything else goes to x86-64 in 64-bit mode. + if (is64Bit) + return "x86-64"; + + if (triple.getOSName().startswith("haiku")) + return "i586"; + if (triple.getOSName().startswith("openbsd")) + return "i486"; + if (triple.getOSName().startswith("bitrig")) + return "i686"; + if (triple.getOSName().startswith("freebsd")) + return "i486"; + if (triple.getOSName().startswith("netbsd")) + return "i486"; +#if LDC_LLVM_VER >= 302 + // All x86 devices running Android have core2 as their common + // denominator. This makes a better choice than pentium4. + if (triple.getEnvironment() == llvm::Triple::Android) + return "core2"; +#endif + + // Fallback to p4. + return "pentium4"; +} + + llvm::TargetMachine* createTargetMachine( std::string targetTriple, std::string arch, @@ -46,7 +104,7 @@ llvm::TargetMachine* createTargetMachine( #endif } - std::string triple; + llvm::Triple triple; // did the user override the target triple? if (targetTriple.empty()) @@ -56,21 +114,20 @@ llvm::TargetMachine* createTargetMachine( error("you must specify a target triple as well with -mtriple when using the -arch option"); fatal(); } - triple = defaultTriple; + triple = llvm::Triple(defaultTriple); } else { - triple = llvm::Triple::normalize(targetTriple); + 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()) { std::string Err; - theTarget = llvm::TargetRegistry::lookupTarget(triple, Err); + theTarget = llvm::TargetRegistry::lookupTarget(triple.str(), Err); if (theTarget == 0) { error("%s Please use the -march option.", Err.c_str()); @@ -96,6 +153,19 @@ llvm::TargetMachine* createTargetMachine( } } + + // 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); + } + } + // Package up features to be passed to target/subtarget std::string FeaturesStr; if (cpu.size() || attrs.size()) @@ -109,14 +179,14 @@ llvm::TargetMachine* createTargetMachine( #if LDC_LLVM_VER == 300 llvm::NoFramePointerElim = genDebugInfo; - return theTarget->createTargetMachine(triple, cpu, FeaturesStr, + return theTarget->createTargetMachine(triple.str(), cpu, FeaturesStr, relocModel, codeModel); #else llvm::TargetOptions targetOptions; targetOptions.NoFramePointerElim = genDebugInfo; return theTarget->createTargetMachine( - triple, + triple.str(), cpu, FeaturesStr, targetOptions, diff --git a/driver/target.h b/driver/target.h index 0b1b7926..4eb4c635 100644 --- a/driver/target.h +++ b/driver/target.h @@ -16,6 +16,9 @@ #define LDC_DRIVER_TARGET_H #include "llvm/Support/CodeGen.h" +#if LDC_LLVM_VER == 300 +#include "llvm/Target/TargetMachine.h" // For llvm::CodeGenOpt::Level. +#endif #include #include