Merge pull request #341 from klickverbot/default-target-cpu

Use generic target CPU by default
This commit is contained in:
David Nadlinger
2013-05-09 13:16:02 -07:00
4 changed files with 272 additions and 119 deletions

View File

@@ -149,6 +149,7 @@ file(GLOB IR_HDR ir/*.h)
set(DRV_SRC
driver/cl_options.cpp
driver/configfile.cpp
driver/target.cpp
driver/toobj.cpp
driver/tool.cpp
driver/linker.cpp
@@ -158,6 +159,7 @@ set(DRV_HDR
driver/linker.h
driver/cl_options.h
driver/configfile.h
driver/target.h
driver/toobj.h
driver/tool.h
)

View File

@@ -17,23 +17,21 @@
#include "driver/cl_options.h"
#include "driver/configfile.h"
#include "driver/linker.h"
#include "driver/target.h"
#include "driver/toobj.h"
#include "gen/cl_helpers.h"
#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"
#include "gen/passes/Passes.h"
#include "llvm/Linker.h"
#include "llvm/MC/SubtargetFeature.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#if LDC_LLVM_VER >= 303
#include "llvm/LinkAllIR.h"
#include "llvm/IR/LLVMContext.h"
@@ -338,19 +336,10 @@ int main(int argc, char** argv)
return EXIT_FAILURE;
}
#if LDC_LLVM_VER >= 301
llvm::TargetOptions targetOptions;
#endif
Array* libs;
if (global.params.symdebug)
{
libs = global.params.debuglibnames;
#if LDC_LLVM_VER == 300
llvm::NoFramePointerElim = true;
#else
targetOptions.NoFramePointerElim = true;
#endif
}
else
libs = global.params.defaultlibnames;
@@ -452,120 +441,32 @@ int main(int argc, char** argv)
// create a proper target
Ir ir;
// check -m32/64 sanity
if (m32bits && m64bits)
error("cannot use both -m32 and -m64 options");
else if ((m32bits || m64bits) && (!mArch.empty() || !mTargetTriple.empty()))
// Set up the TargetMachine.
ExplicitBitness::Type bitness = ExplicitBitness::None;
if ((m32bits || m64bits) && (!mArch.empty() || !mTargetTriple.empty()))
error("-m32 and -m64 switches cannot be used together with -march and -mtriple switches");
if (m32bits)
bitness = ExplicitBitness::M32;
if (m64bits)
{
if (bitness != ExplicitBitness::None)
{
error("cannot use both -m32 and -m64 options");
}
}
if (global.errors)
fatal();
// override triple if needed
std::string defaultTriple = llvm::sys::getDefaultTargetTriple();
if (sizeof(void*) == 4 && m64bits)
{
#if LDC_LLVM_VER >= 301
defaultTriple = llvm::Triple(defaultTriple).get64BitArchVariant().str();
#else
defaultTriple = llvm::Triple__get64BitArchVariant(defaultTriple).str();
#endif
}
else if (sizeof(void*) == 8 && m32bits)
{
#if LDC_LLVM_VER >= 301
defaultTriple = llvm::Triple(defaultTriple).get32BitArchVariant().str();
#else
defaultTriple = llvm::Triple__get32BitArchVariant(defaultTriple).str();
#endif
}
std::string triple;
// did the user override the target triple?
if (mTargetTriple.empty())
{
if (!mArch.empty())
{
error("you must specify a target triple as well with -mtriple when using the -march option");
fatal();
}
triple = defaultTriple;
}
else
{
triple = llvm::Triple::normalize(mTargetTriple);
}
global.params.targetTriple = llvm::Triple(triple);
// Allocate target machine.
const llvm::Target *theTarget = NULL;
// Check whether the user has explicitly specified an architecture to compile for.
if (mArch.empty())
{
std::string Err;
theTarget = llvm::TargetRegistry::lookupTarget(triple, 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 (mArch == it->getName())
{
theTarget = &*it;
break;
}
}
if (!theTarget)
{
error("invalid target '%s'", mArch.c_str());
fatal();
}
}
// Package up features to be passed to target/subtarget
std::string FeaturesStr;
if (mCPU.size() || mAttrs.size())
{
llvm::SubtargetFeatures Features;
for (unsigned i = 0; i != mAttrs.size(); ++i)
Features.AddFeature(mAttrs[i]);
FeaturesStr = Features.getString();
}
// FIXME
//std::auto_ptr<llvm::TargetMachine> target(theTarget->createTargetMachine(triple, FeaturesStr));
//assert(target.get() && "Could not allocate target machine!");
//gTargetMachine = target.get();
#if LDC_LLVM_VER == 300
llvm::TargetMachine* target = theTarget->createTargetMachine(triple, mCPU, FeaturesStr,
mRelocModel, mCodeModel);
#else
llvm::TargetMachine * target = theTarget->createTargetMachine(
llvm::StringRef(triple),
llvm::StringRef(mCPU),
llvm::StringRef(FeaturesStr),
targetOptions,
mRelocModel,
mCodeModel,
codeGenOptLevel()
);
#endif
gTargetMachine = target;
gTargetMachine = createTargetMachine(mTargetTriple, mArch, mCPU, mAttrs, bitness,
mRelocModel, mCodeModel, codeGenOptLevel(), global.params.symdebug);
global.params.targetTriple = llvm::Triple(gTargetMachine->getTargetTriple());
#if LDC_LLVM_VER >= 302
gDataLayout = target->getDataLayout();
gDataLayout = gTargetMachine->getDataLayout();
#else
gDataLayout = target->getTargetData();
gDataLayout = gTargetMachine->getTargetData();
#endif
// Starting with LLVM 3.1 we could also use global.params.targetTriple.isArch64Bit();

198
driver/target.cpp Normal file
View File

@@ -0,0 +1,198 @@
//===-- target.cpp --------------------------------------------------------===//
//
// LDC the LLVM D compiler
//
// This file is distributed under the BSD-style LDC license. See the LICENSE
// 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"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Target/TargetMachine.h"
#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,
std::string cpu,
std::vector<std::string> attrs,
ExplicitBitness::Type bitness,
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)
{
#if LDC_LLVM_VER >= 301
defaultTriple = llvm::Triple(defaultTriple).get64BitArchVariant().str();
#else
defaultTriple = llvm::Triple__get64BitArchVariant(defaultTriple).str();
#endif
}
else if (sizeof(void*) == 8 && bitness == ExplicitBitness::M32)
{
#if LDC_LLVM_VER >= 301
defaultTriple = llvm::Triple(defaultTriple).get32BitArchVariant().str();
#else
defaultTriple = llvm::Triple__get32BitArchVariant(defaultTriple).str();
#endif
}
llvm::Triple triple;
// did the user override the target triple?
if (targetTriple.empty())
{
if (!arch.empty())
{
error("you must specify a target triple as well with -mtriple when using the -arch option");
fatal();
}
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())
{
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();
}
}
// 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())
{
llvm::SubtargetFeatures Features;
for (unsigned i = 0; i != attrs.size(); ++i)
Features.AddFeature(attrs[i]);
FeaturesStr = Features.getString();
}
#if LDC_LLVM_VER == 300
llvm::NoFramePointerElim = genDebugInfo;
return theTarget->createTargetMachine(triple.str(), cpu, FeaturesStr,
relocModel, codeModel);
#else
llvm::TargetOptions targetOptions;
targetOptions.NoFramePointerElim = genDebugInfo;
return theTarget->createTargetMachine(
triple.str(),
cpu,
FeaturesStr,
targetOptions,
relocModel,
codeModel,
codeGenOptLevel
);
#endif
}

52
driver/target.h Normal file
View File

@@ -0,0 +1,52 @@
//===-- driver/target.h - LLVM target setup ---------------------*- C++ -*-===//
//
// LDC the LLVM D compiler
//
// This file is distributed under the BSD-style LDC license. See the LICENSE
// file for details.
//
//===----------------------------------------------------------------------===//
//
// Handles setting up an LLVM TargetMachine from the ugiven command-line
// arguments.
//
//===----------------------------------------------------------------------===//
#ifndef LDC_DRIVER_TARGET_H
#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 <string>
#include <vector>
namespace ExplicitBitness {
enum Type {
None,
M32,
M64
};
}
namespace llvm { class TargetMachine; }
/**
* Creates an LLVM TargetMachine suitable for the given (usually command-line)
* 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<std::string> attrs,
ExplicitBitness::Type bitness,
llvm::Reloc::Model relocModel,
llvm::CodeModel::Model codeModel,
llvm::CodeGenOpt::Level codeGenOptLevel,
bool genDebugInfo);
#endif // LDC_DRIVER_TARGET_H