diff --git a/CMakeLists.txt b/CMakeLists.txt index 3bbb287f..eb4468ae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 ) diff --git a/driver/main.cpp b/driver/main.cpp index 2dcf1af8..d29da866 100644 --- a/driver/main.cpp +++ b/driver/main.cpp @@ -17,6 +17,7 @@ #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" @@ -28,12 +29,10 @@ #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 +337,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 +442,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 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(); diff --git a/driver/target.cpp b/driver/target.cpp new file mode 100644 index 00000000..b2c56192 --- /dev/null +++ b/driver/target.cpp @@ -0,0 +1,128 @@ +//===-- target.cpp --------------------------------------------------------===// +// +// LDC – the LLVM D compiler +// +// This file is distributed under the BSD-style LDC license. See the LICENSE +// file for details. +// +//===----------------------------------------------------------------------===// + +#include "driver/target.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" + +llvm::TargetMachine* createTargetMachine( + std::string targetTriple, + std::string arch, + std::string cpu, + std::vector 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 + } + + std::string 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 = defaultTriple; + } + else + { + 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); + 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(); + } + } + + // 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, cpu, FeaturesStr, + relocModel, codeModel); +#else + llvm::TargetOptions targetOptions; + targetOptions.NoFramePointerElim = genDebugInfo; + + return theTarget->createTargetMachine( + triple, + cpu, + FeaturesStr, + targetOptions, + relocModel, + codeModel, + codeGenOptLevel + ); +#endif +} diff --git a/driver/target.h b/driver/target.h new file mode 100644 index 00000000..0b1b7926 --- /dev/null +++ b/driver/target.h @@ -0,0 +1,49 @@ +//===-- 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" +#include +#include + +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 attrs, + ExplicitBitness::Type bitness, + llvm::Reloc::Model relocModel, + llvm::CodeModel::Model codeModel, + llvm::CodeGenOpt::Level codeGenOptLevel, + bool genDebugInfo); + +#endif // LDC_DRIVER_TARGET_H