diff --git a/include/llvm/Target/TargetMachine.h b/include/llvm/Target/TargetMachine.h index 6e3fe35ab16..efeb61d4997 100644 --- a/include/llvm/Target/TargetMachine.h +++ b/include/llvm/Target/TargetMachine.h @@ -19,6 +19,7 @@ namespace llvm { +class TargetSubtarget; class TargetInstrInfo; class TargetInstrDescriptor; class TargetJITInfo; @@ -97,6 +98,13 @@ public: virtual const TargetFrameInfo *getFrameInfo() const { return 0; } const TargetData &getTargetData() const { return DataLayout; } + virtual const TargetSubtarget *getSubtargetImpl() const { return 0; } + template STC *getSubtarget() const { + assert(getSubtargetImpl() && dynamic_cast(getSubtargetImpl()) && + "Not the right kind of subtarget!"); + return (STC*)getSubtargetImpl(); + } + /// getRegisterInfo - If register information is available, return it. If /// not, return null. This is kept separate from RegInfo until RegInfo has /// details of graph coloring register allocation removed from it. diff --git a/include/llvm/Target/TargetSubtarget.h b/include/llvm/Target/TargetSubtarget.h new file mode 100644 index 00000000000..e99afe24680 --- /dev/null +++ b/include/llvm/Target/TargetSubtarget.h @@ -0,0 +1,41 @@ +//==-- llvm/Target/TargetSubtarget.h - Target Information --------*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Nate Begeman and is distributed under the +// University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file describes the subtarget options of a Target machine. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETSUBTARGET_H +#define LLVM_TARGET_TARGETSUBTARGET_H + +namespace llvm { + +class Module; + +//===----------------------------------------------------------------------===// +/// +/// TargetSubtarget - Generic base class for all target subtargets. All +/// Target-specific options that control code generation and printing should +/// be exposed through a TargetSubtarget-derived class. +/// +class TargetSubtarget { + TargetSubtarget(const TargetSubtarget&); // DO NOT IMPLEMENT + void operator=(const TargetSubtarget&); // DO NOT IMPLEMENT +protected: // Can only create subclasses... + /// This constructor initializes the data members to match that + /// of the specified module. + /// + TargetSubtarget(const Module &M); +public: + virtual ~TargetSubtarget(); +}; + +} // End llvm namespace + +#endif diff --git a/lib/Target/TargetSubtarget.cpp b/lib/Target/TargetSubtarget.cpp new file mode 100644 index 00000000000..ebb13084752 --- /dev/null +++ b/lib/Target/TargetSubtarget.cpp @@ -0,0 +1,22 @@ +//===-- TargetSubtarget.cpp - General Target Information -------------------==// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Nate Begeman and is distributed under the +// University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file describes the general parts of a Subtarget. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Target/TargetSubtarget.h" +using namespace llvm; + +//--------------------------------------------------------------------------- +// TargetSubtarget Class +// +TargetSubtarget::TargetSubtarget(const Module &M) {} + +TargetSubtarget::~TargetSubtarget() {} diff --git a/lib/Target/X86/X86ISelPattern.cpp b/lib/Target/X86/X86ISelPattern.cpp index 66e6f71bff3..6bd8e27607f 100644 --- a/lib/Target/X86/X86ISelPattern.cpp +++ b/lib/Target/X86/X86ISelPattern.cpp @@ -14,6 +14,7 @@ #include "X86.h" #include "X86InstrBuilder.h" #include "X86RegisterInfo.h" +#include "X86Subtarget.h" #include "llvm/CallingConv.h" #include "llvm/Constants.h" #include "llvm/Instructions.h" @@ -26,6 +27,7 @@ #include "llvm/CodeGen/SSARegMap.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetLowering.h" +#include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Support/CFG.h" #include "llvm/Support/MathExtras.h" @@ -996,8 +998,13 @@ namespace { /// TheDAG - The DAG being selected during Select* operations. SelectionDAG *TheDAG; + + /// Subtarget - Keep a pointer to the X86Subtarget around so that we can + /// make the right decision when generating code for different targets. + const X86Subtarget *Subtarget; public: ISel(TargetMachine &TM) : SelectionDAGISel(X86Lowering), X86Lowering(TM) { + Subtarget = TM.getSubtarget(); } virtual const char *getPassName() const { @@ -1314,8 +1321,18 @@ bool ISel::MatchAddress(SDOperand N, X86ISelAddressMode &AM) { break; case ISD::GlobalAddress: if (AM.GV == 0) { - AM.GV = cast(N)->getGlobal(); - return false; + GlobalValue *GV = cast(N)->getGlobal(); + // For Darwin, external and weak symbols are indirect, so we want to load + // the value at address GV, not the value of GV itself. This means that + // the GlobalAddress must be in the base or index register of the address, + // not the GV offset field. + if (Subtarget->getIndirectExternAndWeakGlobals() && + (GV->hasWeakLinkage() || GV->isExternal())) { + break; + } else { + AM.GV = GV; + return false; + } } break; case ISD::Constant: @@ -2236,7 +2253,15 @@ unsigned ISel::SelectExpr(SDOperand N) { return Result; case ISD::GlobalAddress: { GlobalValue *GV = cast(N)->getGlobal(); - BuildMI(BB, X86::MOV32ri, 1, Result).addGlobalAddress(GV); + // For Darwin, external and weak symbols are indirect, so we want to load + // the value at address GV, not the value of GV itself. + if (Subtarget->getIndirectExternAndWeakGlobals() && + (GV->hasWeakLinkage() || GV->isExternal())) { + BuildMI(BB, X86::MOV32rm, 4, Result).addReg(0).addZImm(1).addReg(0) + .addGlobalAddress(GV, false, 0); + } else { + BuildMI(BB, X86::MOV32ri, 1, Result).addGlobalAddress(GV); + } return Result; } case ISD::ExternalSymbol: { diff --git a/lib/Target/X86/X86Subtarget.cpp b/lib/Target/X86/X86Subtarget.cpp new file mode 100644 index 00000000000..e50d2d6d87b --- /dev/null +++ b/lib/Target/X86/X86Subtarget.cpp @@ -0,0 +1,59 @@ +//===- X86Subtarget.cpp - X86 Instruction Information -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Nate Begeman and is distributed under the +// University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the X86 specific subclass of TargetSubtarget. +// +//===----------------------------------------------------------------------===// + +#include "X86Subtarget.h" +#include "llvm/Module.h" +using namespace llvm; + +X86Subtarget::X86Subtarget(const Module &M) + : TargetSubtarget(M), stackAlignment(8), + indirectExternAndWeakGlobals(false), asmDarwinLinkerStubs(false), + asmLeadingUnderscore(false), asmAlignmentIsInBytes(false), + asmPrintDotLocalConstants(false), asmPrintDotLCommConstants(false), + asmPrintConstantAlignment(false) { + // Declare a boolean for each platform + bool forCygwin = false; + bool forDarwin = false; + bool forWindows = false; + + // Set the boolean corresponding to the current target triple, or the default + // if one cannot be determined, to true. + const std::string& TT = M.getTargetTriple(); + if (TT.length() > 5) { + forCygwin = TT.find("cygwin") != std::string::npos || + TT.find("mingw") != std::string::npos; + forDarwin = TT.find("darwin") != std::string::npos; + forWindows = TT.find("win32") != std::string::npos; + } else if (TT.empty()) { +#if defined(__CYGWIN__) || defined(__MINGW32__) + forCygwin = true; +#elif defined(__APPLE__) + forDarwin = true; +#elif defined(_WIN32) + forWindws = true; +#endif + } + + if (forCygwin) { + asmLeadingUnderscore = true; + } + if (forDarwin) { + stackAlignment = 16; + indirectExternAndWeakGlobals = true; + asmDarwinLinkerStubs = true; + asmLeadingUnderscore = true; + asmPrintDotLCommConstants = true; + } + if (forWindows) { + } +} diff --git a/lib/Target/X86/X86Subtarget.h b/lib/Target/X86/X86Subtarget.h new file mode 100644 index 00000000000..96a1bb2cc0b --- /dev/null +++ b/lib/Target/X86/X86Subtarget.h @@ -0,0 +1,55 @@ +//=====-- X86Subtarget.h - Define TargetMachine for the X86 ---*- C++ -*--====// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Nate Begeman and is distributed under the +// University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the X86 specific subclass of TargetSubtarget. +// +//===----------------------------------------------------------------------===// + +#ifndef X86SUBTARGET_H +#define X86SUBTARGET_H + +#include "llvm/Target/TargetSubtarget.h" + +namespace llvm { +class Module; + +class X86Subtarget : public TargetSubtarget { +protected: + /// Used by the target machine to set up the target frame info + unsigned stackAlignment; + + /// Used by instruction selector + bool indirectExternAndWeakGlobals; + + /// Used by the asm printer + bool asmDarwinLinkerStubs; + bool asmLeadingUnderscore; + bool asmAlignmentIsInBytes; + bool asmPrintDotLocalConstants; + bool asmPrintDotLCommConstants; + bool asmPrintConstantAlignment; +public: + /// This constructor initializes the data members to match that + /// of the specified module. + /// + X86Subtarget(const Module &M); + + /// Returns the preferred stack alignment for the current target triple, or + /// the default if no target triple is set. + unsigned getStackAlignment() const { return stackAlignment; } + + /// Returns true if the instruction selector should treat global values + /// referencing external or weak symbols as indirect rather than direct + /// references. + bool getIndirectExternAndWeakGlobals() const { + return indirectExternAndWeakGlobals; } +}; +} // End llvm namespace + +#endif diff --git a/lib/Target/X86/X86TargetMachine.cpp b/lib/Target/X86/X86TargetMachine.cpp index a0537f529c1..f4d5ba40ec4 100644 --- a/lib/Target/X86/X86TargetMachine.cpp +++ b/lib/Target/X86/X86TargetMachine.cpp @@ -92,7 +92,9 @@ unsigned X86TargetMachine::getModuleMatchQuality(const Module &M) { /// X86TargetMachine::X86TargetMachine(const Module &M, IntrinsicLowering *IL) : TargetMachine("X86", IL, true, 4, 4, 4, 4, 4), - FrameInfo(TargetFrameInfo::StackGrowsDown, 8, -4), + Subtarget(M), + FrameInfo(TargetFrameInfo::StackGrowsDown, + Subtarget.getStackAlignment(), -4), JITInfo(*this) { // Scalar SSE FP requires at least SSE2 X86ScalarSSE &= X86Vector >= SSE2; diff --git a/lib/Target/X86/X86TargetMachine.h b/lib/Target/X86/X86TargetMachine.h index 70b111c38bf..955f8556028 100644 --- a/lib/Target/X86/X86TargetMachine.h +++ b/lib/Target/X86/X86TargetMachine.h @@ -19,12 +19,14 @@ #include "llvm/PassManager.h" #include "X86InstrInfo.h" #include "X86JITInfo.h" +#include "X86Subtarget.h" namespace llvm { class IntrinsicLowering; class X86TargetMachine : public TargetMachine { X86InstrInfo InstrInfo; + X86Subtarget Subtarget; TargetFrameInfo FrameInfo; X86JITInfo JITInfo; public: @@ -33,6 +35,7 @@ public: virtual const X86InstrInfo *getInstrInfo() const { return &InstrInfo; } virtual const TargetFrameInfo *getFrameInfo() const { return &FrameInfo; } virtual TargetJITInfo *getJITInfo() { return &JITInfo; } + virtual const TargetSubtarget *getSubtargetImpl() const{ return &Subtarget; } virtual const MRegisterInfo *getRegisterInfo() const { return &InstrInfo.getRegisterInfo(); }