//
// The LLVM Compiler Infrastructure
//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//
//===----------------------------------------------------------------------===//
+#include "X86MCAsmInfo.h"
#include "X86TargetMachine.h"
#include "X86.h"
-#include "llvm/Module.h"
#include "llvm/PassManager.h"
-#include "llvm/CodeGen/IntrinsicLowering.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/Passes.h"
+#include "llvm/MC/MCCodeEmitter.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/Support/FormattedStream.h"
#include "llvm/Target/TargetOptions.h"
-#include "llvm/Target/TargetMachineRegistry.h"
-#include "llvm/Transforms/Scalar.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/ADT/Statistic.h"
+#include "llvm/Target/TargetRegistry.h"
using namespace llvm;
-X86VectorEnum llvm::X86Vector = NoSSE;
-bool llvm::X86ScalarSSE = false;
-bool llvm::X86DAGIsel = false;
-
-/// X86TargetMachineModule - Note that this is used on hosts that cannot link
-/// in a library unless there are references into the library. In particular,
-/// it seems that it is not possible to get things to work on Win32 without
-/// this. Though it is unused, do not remove it.
-extern "C" int X86TargetMachineModule;
-int X86TargetMachineModule = 0;
-
-namespace {
- cl::opt<bool> DisableOutput("disable-x86-llc-output", cl::Hidden,
- cl::desc("Disable the X86 asm printer, for use "
- "when profiling the code generator."));
- cl::opt<bool, true> EnableSSEFP("enable-sse-scalar-fp",
- cl::desc("Perform FP math in SSE regs instead of the FP stack"),
- cl::location(X86ScalarSSE),
- cl::init(false));
-
- cl::opt<bool, true> EnableX86DAGDAG("enable-x86-dag-isel", cl::Hidden,
- cl::desc("Enable DAG-to-DAG isel for X86"),
- cl::location(X86DAGIsel),
- cl::init(false));
-
- // FIXME: This should eventually be handled with target triples and
- // subtarget support!
- cl::opt<X86VectorEnum, true>
- SSEArg(
- cl::desc("Enable SSE support in the X86 target:"),
- cl::values(
- clEnumValN(SSE, "sse", " Enable SSE support"),
- clEnumValN(SSE2, "sse2", " Enable SSE and SSE2 support"),
- clEnumValN(SSE3, "sse3", " Enable SSE, SSE2, and SSE3 support"),
- clEnumValEnd),
- cl::location(X86Vector), cl::init(NoSSE));
-
- // Register the target.
- RegisterTarget<X86TargetMachine> X("x86", " IA-32 (Pentium and above)");
+static MCAsmInfo *createMCAsmInfo(const Target &T, StringRef TT) {
+ Triple TheTriple(TT);
+ switch (TheTriple.getOS()) {
+ case Triple::Darwin:
+ return new X86MCAsmInfoDarwin(TheTriple);
+ case Triple::MinGW32:
+ case Triple::MinGW64:
+ case Triple::Cygwin:
+ case Triple::Win32:
+ return new X86MCAsmInfoCOFF(TheTriple);
+ default:
+ return new X86ELFMCAsmInfo(TheTriple);
+ }
}
-unsigned X86TargetMachine::getJITMatchQuality() {
-#if defined(i386) || defined(__i386__) || defined(__x86__) || defined(_M_IX86)
- return 10;
-#else
- return 0;
-#endif
+static MCStreamer *createMCStreamer(const Target &T, const std::string &TT,
+ MCContext &Ctx, TargetAsmBackend &TAB,
+ raw_ostream &_OS,
+ MCCodeEmitter *_Emitter,
+ bool RelaxAll) {
+ Triple TheTriple(TT);
+ switch (TheTriple.getOS()) {
+ case Triple::Darwin:
+ return createMachOStreamer(Ctx, TAB, _OS, _Emitter, RelaxAll);
+ case Triple::MinGW32:
+ case Triple::MinGW64:
+ case Triple::Cygwin:
+ case Triple::Win32:
+ return createWinCOFFStreamer(Ctx, TAB, *_Emitter, _OS, RelaxAll);
+ default:
+ return createELFStreamer(Ctx, TAB, _OS, _Emitter, RelaxAll);
+ }
}
-unsigned X86TargetMachine::getModuleMatchQuality(const Module &M) {
- // We strongly match "i[3-9]86-*".
- std::string TT = M.getTargetTriple();
- if (TT.size() >= 5 && TT[0] == 'i' && TT[2] == '8' && TT[3] == '6' &&
- TT[4] == '-' && TT[1] - '3' < 6)
- return 20;
-
- if (M.getEndianness() == Module::LittleEndian &&
- M.getPointerSize() == Module::Pointer32)
- return 10; // Weak match
- else if (M.getEndianness() != Module::AnyEndianness ||
- M.getPointerSize() != Module::AnyPointerSize)
- return 0; // Match for some other target
-
- return getJITMatchQuality()/2;
+extern "C" void LLVMInitializeX86Target() {
+ // Register the target.
+ RegisterTargetMachine<X86_32TargetMachine> X(TheX86_32Target);
+ RegisterTargetMachine<X86_64TargetMachine> Y(TheX86_64Target);
+
+ // Register the target asm info.
+ RegisterAsmInfoFn A(TheX86_32Target, createMCAsmInfo);
+ RegisterAsmInfoFn B(TheX86_64Target, createMCAsmInfo);
+
+ // Register the code emitter.
+ TargetRegistry::RegisterCodeEmitter(TheX86_32Target,
+ createX86_32MCCodeEmitter);
+ TargetRegistry::RegisterCodeEmitter(TheX86_64Target,
+ createX86_64MCCodeEmitter);
+
+ // Register the asm backend.
+ TargetRegistry::RegisterAsmBackend(TheX86_32Target,
+ createX86_32AsmBackend);
+ TargetRegistry::RegisterAsmBackend(TheX86_64Target,
+ createX86_64AsmBackend);
+
+ // Register the object streamer.
+ TargetRegistry::RegisterObjectStreamer(TheX86_32Target,
+ createMCStreamer);
+ TargetRegistry::RegisterObjectStreamer(TheX86_64Target,
+ createMCStreamer);
}
-/// X86TargetMachine ctor - Create an ILP32 architecture model
-///
-X86TargetMachine::X86TargetMachine(const Module &M,
- IntrinsicLowering *IL,
- const std::string &FS)
- : TargetMachine("X86", IL, true, 4, 4, 4, 4, 4),
- Subtarget(M, FS),
- FrameInfo(TargetFrameInfo::StackGrowsDown,
- Subtarget.getStackAlignment(), -4),
- JITInfo(*this) {
- // Scalar SSE FP requires at least SSE2
- X86ScalarSSE &= X86Vector >= SSE2;
- // Ignore -enable-sse-scalar-fp if -enable-x86-dag-isel.
- X86ScalarSSE |= (X86DAGIsel && X86Vector >= SSE2);
+X86_32TargetMachine::X86_32TargetMachine(const Target &T, const std::string &TT,
+ const std::string &FS)
+ : X86TargetMachine(T, TT, FS, false),
+ DataLayout(getSubtargetImpl()->isTargetDarwin() ?
+ "e-p:32:32-f64:32:64-i64:32:64-f80:128:128-n8:16:32" :
+ (getSubtargetImpl()->isTargetCygMing() ||
+ getSubtargetImpl()->isTargetWindows()) ?
+ "e-p:32:32-f64:64:64-i64:64:64-f80:32:32-n8:16:32" :
+ "e-p:32:32-f64:32:64-i64:32:64-f80:32:32-n8:16:32"),
+ InstrInfo(*this),
+ TSInfo(*this),
+ TLInfo(*this),
+ JITInfo(*this) {
}
-// addPassesToEmitFile - We currently use all of the same passes as the JIT
-// does to emit statically compiled machine code.
-bool X86TargetMachine::addPassesToEmitFile(PassManager &PM, std::ostream &Out,
- CodeGenFileType FileType,
- bool Fast) {
- if (FileType != TargetMachine::AssemblyFile &&
- FileType != TargetMachine::ObjectFile) return true;
-
- // FIXME: Implement efficient support for garbage collection intrinsics.
- PM.add(createLowerGCPass());
+X86_64TargetMachine::X86_64TargetMachine(const Target &T, const std::string &TT,
+ const std::string &FS)
+ : X86TargetMachine(T, TT, FS, true),
+ DataLayout("e-p:64:64-s:64-f64:64:64-i64:64:64-f80:128:128-n8:16:32:64"),
+ InstrInfo(*this),
+ TSInfo(*this),
+ TLInfo(*this),
+ JITInfo(*this) {
+}
- // FIXME: Implement the invoke/unwind instructions!
- PM.add(createLowerInvokePass());
+/// X86TargetMachine ctor - Create an X86 target.
+///
+X86TargetMachine::X86TargetMachine(const Target &T, const std::string &TT,
+ const std::string &FS, bool is64Bit)
+ : LLVMTargetMachine(T, TT),
+ Subtarget(TT, FS, is64Bit),
+ FrameInfo(*this, Subtarget),
+ ELFWriterInfo(is64Bit, true) {
+ DefRelocModel = getRelocationModel();
+
+ // If no relocation model was picked, default as appropriate for the target.
+ if (getRelocationModel() == Reloc::Default) {
+ // Darwin defaults to PIC in 64 bit mode and dynamic-no-pic in 32 bit mode.
+ // Win64 requires rip-rel addressing, thus we force it to PIC. Otherwise we
+ // use static relocation model by default.
+ if (Subtarget.isTargetDarwin()) {
+ if (Subtarget.is64Bit())
+ setRelocationModel(Reloc::PIC_);
+ else
+ setRelocationModel(Reloc::DynamicNoPIC);
+ } else if (Subtarget.isTargetWin64())
+ setRelocationModel(Reloc::PIC_);
+ else
+ setRelocationModel(Reloc::Static);
+ }
+
+ assert(getRelocationModel() != Reloc::Default &&
+ "Relocation mode not picked");
+
+ // ELF and X86-64 don't have a distinct DynamicNoPIC model. DynamicNoPIC
+ // is defined as a model for code which may be used in static or dynamic
+ // executables but not necessarily a shared library. On X86-32 we just
+ // compile in -static mode, in x86-64 we use PIC.
+ if (getRelocationModel() == Reloc::DynamicNoPIC) {
+ if (is64Bit)
+ setRelocationModel(Reloc::PIC_);
+ else if (!Subtarget.isTargetDarwin())
+ setRelocationModel(Reloc::Static);
+ }
+
+ // If we are on Darwin, disallow static relocation model in X86-64 mode, since
+ // the Mach-O file format doesn't support it.
+ if (getRelocationModel() == Reloc::Static &&
+ Subtarget.isTargetDarwin() &&
+ is64Bit)
+ setRelocationModel(Reloc::PIC_);
+
+ // Determine the PICStyle based on the target selected.
+ if (getRelocationModel() == Reloc::Static) {
+ // Unless we're in PIC or DynamicNoPIC mode, set the PIC style to None.
+ Subtarget.setPICStyle(PICStyles::None);
+ } else if (Subtarget.is64Bit()) {
+ // PIC in 64 bit mode is always rip-rel.
+ Subtarget.setPICStyle(PICStyles::RIPRel);
+ } else if (Subtarget.isTargetCygMing()) {
+ Subtarget.setPICStyle(PICStyles::None);
+ } else if (Subtarget.isTargetDarwin()) {
+ if (getRelocationModel() == Reloc::PIC_)
+ Subtarget.setPICStyle(PICStyles::StubPIC);
+ else {
+ assert(getRelocationModel() == Reloc::DynamicNoPIC);
+ Subtarget.setPICStyle(PICStyles::StubDynamicNoPIC);
+ }
+ } else if (Subtarget.isTargetELF()) {
+ Subtarget.setPICStyle(PICStyles::GOT);
+ }
- // FIXME: Implement the switch instruction in the instruction selector!
- PM.add(createLowerSwitchPass());
+ // Finally, if we have "none" as our PIC style, force to static mode.
+ if (Subtarget.getPICStyle() == PICStyles::None)
+ setRelocationModel(Reloc::Static);
+}
- // Make sure that no unreachable blocks are instruction selected.
- PM.add(createUnreachableBlockEliminationPass());
+//===----------------------------------------------------------------------===//
+// Pass Pipeline Configuration
+//===----------------------------------------------------------------------===//
+bool X86TargetMachine::addInstSelector(PassManagerBase &PM,
+ CodeGenOpt::Level OptLevel) {
// Install an instruction selector.
- if (X86DAGIsel)
- PM.add(createX86ISelDag(*this));
- else
- PM.add(createX86ISelPattern(*this));
+ PM.add(createX86ISelDag(*this, OptLevel));
- // Print the instruction selected machine code...
- if (PrintMachineCode)
- PM.add(createMachineFunctionPrinterPass(&std::cerr));
+ // For 32-bit, prepend instructions to set the "global base reg" for PIC.
+ if (!Subtarget.is64Bit())
+ PM.add(createGlobalBaseRegPass());
- // Perform register allocation to convert to a concrete x86 representation
- PM.add(createRegisterAllocator());
+ return false;
+}
- if (PrintMachineCode)
- PM.add(createMachineFunctionPrinterPass(&std::cerr));
+bool X86TargetMachine::addPreRegAlloc(PassManagerBase &PM,
+ CodeGenOpt::Level OptLevel) {
+ PM.add(createX86MaxStackAlignmentHeuristicPass());
+ return false; // -print-machineinstr shouldn't print after this.
+}
+bool X86TargetMachine::addPostRegAlloc(PassManagerBase &PM,
+ CodeGenOpt::Level OptLevel) {
PM.add(createX86FloatingPointStackifierPass());
-
- if (PrintMachineCode)
- PM.add(createMachineFunctionPrinterPass(&std::cerr));
-
- // Insert prolog/epilog code. Eliminate abstract frame index references...
- PM.add(createPrologEpilogCodeInserter());
-
- PM.add(createX86PeepholeOptimizerPass());
-
- if (PrintMachineCode) // Print the register-allocated code
- PM.add(createX86CodePrinterPass(std::cerr, *this));
-
- if (!DisableOutput)
- switch (FileType) {
- default:
- assert(0 && "Unexpected filetype here!");
- case TargetMachine::AssemblyFile:
- PM.add(createX86CodePrinterPass(Out, *this));
- break;
- case TargetMachine::ObjectFile:
- // FIXME: We only support emission of ELF files for now, this should check
- // the target triple and decide on the format to write (e.g. COFF on
- // win32).
- addX86ELFObjectWriterPass(PM, Out, *this);
- break;
- }
-
- // Delete machine code for this function
- PM.add(createMachineCodeDeleter());
-
- return false; // success!
+ return true; // -print-machineinstr should print after this.
}
-/// addPassesToJITCompile - Add passes to the specified pass manager to
-/// implement a fast dynamic compiler for this target. Return true if this is
-/// not supported for this target.
-///
-void X86JITInfo::addPassesToJITCompile(FunctionPassManager &PM) {
- // FIXME: Implement efficient support for garbage collection intrinsics.
- PM.add(createLowerGCPass());
-
- // FIXME: Implement the invoke/unwind instructions!
- PM.add(createLowerInvokePass());
-
- // FIXME: Implement the switch instruction in the instruction selector!
- PM.add(createLowerSwitchPass());
-
- // Make sure that no unreachable blocks are instruction selected.
- PM.add(createUnreachableBlockEliminationPass());
-
- // Install an instruction selector.
- if (X86DAGIsel)
- PM.add(createX86ISelDag(TM));
- else
- PM.add(createX86ISelPattern(TM));
+bool X86TargetMachine::addPreEmitPass(PassManagerBase &PM,
+ CodeGenOpt::Level OptLevel) {
+ if (OptLevel != CodeGenOpt::None && Subtarget.hasSSE2()) {
+ PM.add(createSSEDomainFixPass());
+ return true;
+ }
+ return false;
+}
- // FIXME: Add SSA based peephole optimizer here.
+bool X86TargetMachine::addCodeEmitter(PassManagerBase &PM,
+ CodeGenOpt::Level OptLevel,
+ JITCodeEmitter &JCE) {
+ // FIXME: Move this to TargetJITInfo!
+ // On Darwin, do not override 64-bit setting made in X86TargetMachine().
+ if (DefRelocModel == Reloc::Default &&
+ (!Subtarget.isTargetDarwin() || !Subtarget.is64Bit())) {
+ setRelocationModel(Reloc::Static);
+ Subtarget.setPICStyle(PICStyles::None);
+ }
+
- // Print the instruction selected machine code...
- if (PrintMachineCode)
- PM.add(createMachineFunctionPrinterPass(&std::cerr));
+ PM.add(createX86JITCodeEmitterPass(*this, JCE));
- // Perform register allocation to convert to a concrete x86 representation
- PM.add(createRegisterAllocator());
+ return false;
+}
- if (PrintMachineCode)
- PM.add(createMachineFunctionPrinterPass(&std::cerr));
+void X86TargetMachine::setCodeModelForStatic() {
- PM.add(createX86FloatingPointStackifierPass());
+ if (getCodeModel() != CodeModel::Default) return;
- if (PrintMachineCode)
- PM.add(createMachineFunctionPrinterPass(&std::cerr));
+ // For static codegen, if we're not already set, use Small codegen.
+ setCodeModel(CodeModel::Small);
+}
- // Insert prolog/epilog code. Eliminate abstract frame index references...
- PM.add(createPrologEpilogCodeInserter());
- PM.add(createX86PeepholeOptimizerPass());
+void X86TargetMachine::setCodeModelForJIT() {
- if (PrintMachineCode) // Print the register-allocated code
- PM.add(createX86CodePrinterPass(std::cerr, TM));
-}
+ if (getCodeModel() != CodeModel::Default) return;
-bool X86TargetMachine::addPassesToEmitMachineCode(FunctionPassManager &PM,
- MachineCodeEmitter &MCE) {
- PM.add(createX86CodeEmitterPass(MCE));
- // Delete machine code for this function
- PM.add(createMachineCodeDeleter());
- return false;
+ // 64-bit JIT places everything in the same buffer except external functions.
+ if (Subtarget.is64Bit())
+ setCodeModel(CodeModel::Large);
+ else
+ setCodeModel(CodeModel::Small);
}