mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-11-04 22:07:27 +00:00
x86 / Darwin PIC support.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@26273 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
d2ee218b49
commit
7ccced634a
@ -18,6 +18,7 @@
|
||||
#include "X86TargetMachine.h"
|
||||
#include "llvm/Module.h"
|
||||
#include "llvm/Support/Mangler.h"
|
||||
#include "llvm/Target/TargetOptions.h"
|
||||
#include <iostream>
|
||||
using namespace llvm;
|
||||
using namespace x86;
|
||||
@ -116,9 +117,9 @@ void X86ATTAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
|
||||
case MachineOperand::MO_GlobalAddress: {
|
||||
bool isCallOp = Modifier && !strcmp(Modifier, "call");
|
||||
bool isMemOp = Modifier && !strcmp(Modifier, "mem");
|
||||
if (!isMemOp && !isCallOp) O << '$';
|
||||
// Darwin block shameless ripped from PPCAsmPrinter.cpp
|
||||
if (forDarwin) {
|
||||
if (!isMemOp && !isCallOp) O << '$';
|
||||
GlobalValue *GV = MO.getGlobal();
|
||||
std::string Name = Mang->getValueName(GV);
|
||||
// Link-once, External, or Weakly-linked global variables need
|
||||
@ -132,19 +133,14 @@ void X86ATTAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
|
||||
} else {
|
||||
GVStubs.insert(Name);
|
||||
O << "L" << Name << "$non_lazy_ptr";
|
||||
if (PICEnabled)
|
||||
O << "-\"L" << getFunctionNumber() << "$pb\"";
|
||||
}
|
||||
} else {
|
||||
O << Mang->getValueName(GV);
|
||||
}
|
||||
int Offset = MO.getOffset();
|
||||
if (Offset > 0)
|
||||
O << "+" << Offset;
|
||||
else if (Offset < 0)
|
||||
O << Offset;
|
||||
return;
|
||||
}
|
||||
if (!isMemOp && !isCallOp) O << '$';
|
||||
O << Mang->getValueName(MO.getGlobal());
|
||||
} else
|
||||
O << Mang->getValueName(MO.getGlobal());
|
||||
int Offset = MO.getOffset();
|
||||
if (Offset > 0)
|
||||
O << "+" << Offset;
|
||||
@ -202,6 +198,8 @@ void X86ATTAsmPrinter::printMemReference(const MachineInstr *MI, unsigned Op){
|
||||
} else if (BaseReg.isConstantPoolIndex()) {
|
||||
O << PrivateGlobalPrefix << "CPI" << getFunctionNumber() << "_"
|
||||
<< BaseReg.getConstantPoolIndex();
|
||||
if (forDarwin && PICEnabled)
|
||||
O << "-\"L" << getFunctionNumber() << "$pb\"";
|
||||
if (DispSpec.getImmedValue())
|
||||
O << "+" << DispSpec.getImmedValue();
|
||||
if (IndexReg.getReg()) {
|
||||
@ -238,6 +236,11 @@ void X86ATTAsmPrinter::printMemReference(const MachineInstr *MI, unsigned Op){
|
||||
}
|
||||
}
|
||||
|
||||
void X86ATTAsmPrinter::printPICLabel(const MachineInstr *MI, unsigned Op) {
|
||||
O << "\"L" << getFunctionNumber() << "$pb\"\n";
|
||||
O << "\"L" << getFunctionNumber() << "$pb\":";
|
||||
}
|
||||
|
||||
/// printMachineInstruction -- Print out a single X86 LLVM instruction
|
||||
/// MI in Intel syntax to the current output stream.
|
||||
///
|
||||
|
@ -62,6 +62,7 @@ struct X86ATTAsmPrinter : public X86SharedAsmPrinter {
|
||||
void printMachineInstruction(const MachineInstr *MI);
|
||||
void printSSECC(const MachineInstr *MI, unsigned Op);
|
||||
void printMemReference(const MachineInstr *MI, unsigned Op);
|
||||
void printPICLabel(const MachineInstr *MI, unsigned Op);
|
||||
bool runOnMachineFunction(MachineFunction &F);
|
||||
};
|
||||
|
||||
|
@ -85,12 +85,20 @@ namespace {
|
||||
/// 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;
|
||||
|
||||
unsigned GlobalBaseReg;
|
||||
public:
|
||||
X86DAGToDAGISel(TargetMachine &TM)
|
||||
: SelectionDAGISel(X86Lowering), X86Lowering(TM) {
|
||||
Subtarget = &TM.getSubtarget<X86Subtarget>();
|
||||
}
|
||||
|
||||
virtual bool runOnFunction(Function &Fn) {
|
||||
// Make sure we re-emit a set of the global base reg if necessary
|
||||
GlobalBaseReg = 0;
|
||||
return SelectionDAGISel::runOnFunction(Fn);
|
||||
}
|
||||
|
||||
virtual const char *getPassName() const {
|
||||
return "X86 DAG->DAG Instruction Selection";
|
||||
}
|
||||
@ -145,6 +153,10 @@ namespace {
|
||||
return CurDAG->getTargetConstant(Imm, MVT::i32);
|
||||
}
|
||||
|
||||
/// getGlobalBaseReg - insert code into the entry mbb to materialize the PIC
|
||||
/// base register. Return the virtual register that holds this value.
|
||||
SDOperand getGlobalBaseReg();
|
||||
|
||||
#ifndef NDEBUG
|
||||
unsigned Indent;
|
||||
#endif
|
||||
@ -283,6 +295,7 @@ bool X86DAGToDAGISel::MatchAddress(SDOperand N, X86ISelAddressMode &AM,
|
||||
break;
|
||||
|
||||
case ISD::ConstantPool:
|
||||
case ISD::TargetConstantPool:
|
||||
if (AM.BaseType == X86ISelAddressMode::RegBase && AM.Base.Reg.Val == 0) {
|
||||
if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(N)) {
|
||||
AM.BaseType = X86ISelAddressMode::ConstantPoolBase;
|
||||
@ -377,6 +390,10 @@ bool X86DAGToDAGISel::MatchAddress(SDOperand N, X86ISelAddressMode &AM,
|
||||
|
||||
// Is the base register already occupied?
|
||||
if (AM.BaseType != X86ISelAddressMode::RegBase || AM.Base.Reg.Val) {
|
||||
// TargetConstantPool cannot be anything but the base.
|
||||
if (N.getOpcode() == ISD::TargetConstantPool)
|
||||
return true;
|
||||
|
||||
// If so, check to see if the scale index register is set.
|
||||
if (AM.IndexReg.Val == 0) {
|
||||
AM.IndexReg = N;
|
||||
@ -478,6 +495,24 @@ bool X86DAGToDAGISel::SelectLEAAddr(SDOperand N, SDOperand &Base,
|
||||
return false;
|
||||
}
|
||||
|
||||
/// getGlobalBaseReg - Output the instructions required to put the
|
||||
/// base address to use for accessing globals into a register.
|
||||
///
|
||||
SDOperand X86DAGToDAGISel::getGlobalBaseReg() {
|
||||
if (!GlobalBaseReg) {
|
||||
// Insert the set of GlobalBaseReg into the first MBB of the function
|
||||
MachineBasicBlock &FirstMBB = BB->getParent()->front();
|
||||
MachineBasicBlock::iterator MBBI = FirstMBB.begin();
|
||||
SSARegMap *RegMap = BB->getParent()->getSSARegMap();
|
||||
// FIXME: when we get to LP64, we will need to create the appropriate
|
||||
// type of register here.
|
||||
GlobalBaseReg = RegMap->createVirtualRegister(X86::R32RegisterClass);
|
||||
BuildMI(FirstMBB, MBBI, X86::MovePCtoStack, 0);
|
||||
BuildMI(FirstMBB, MBBI, X86::POP32r, 1, GlobalBaseReg);
|
||||
}
|
||||
return CurDAG->getRegister(GlobalBaseReg, MVT::i32);
|
||||
}
|
||||
|
||||
void X86DAGToDAGISel::Select(SDOperand &Result, SDOperand N) {
|
||||
SDNode *Node = N.Val;
|
||||
MVT::ValueType NVT = Node->getValueType(0);
|
||||
@ -603,6 +638,10 @@ void X86DAGToDAGISel::Select(SDOperand &Result, SDOperand N) {
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
case X86ISD::GlobalBaseReg:
|
||||
Result = getGlobalBaseReg();
|
||||
return;
|
||||
|
||||
case ISD::SDIV:
|
||||
case ISD::UDIV:
|
||||
|
@ -162,6 +162,7 @@ X86TargetLowering::X86TargetLowering(TargetMachine &TM)
|
||||
// X86 ret instruction may pop stack.
|
||||
setOperationAction(ISD::RET , MVT::Other, Custom);
|
||||
// Darwin ABI issue.
|
||||
setOperationAction(ISD::ConstantPool , MVT::i32 , Custom);
|
||||
setOperationAction(ISD::GlobalAddress , MVT::i32 , Custom);
|
||||
// 64-bit addm sub, shl, sra, srl (iff 32-bit x86)
|
||||
setOperationAction(ISD::SHL_PARTS , MVT::i32 , Custom);
|
||||
@ -1788,21 +1789,43 @@ SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
|
||||
return DAG.getNode(X86ISD::REP_MOVS, MVT::Other, Chain,
|
||||
DAG.getValueType(AVT), InFlag);
|
||||
}
|
||||
case ISD::ConstantPool: {
|
||||
ConstantPoolSDNode *CP = cast<ConstantPoolSDNode>(Op);
|
||||
SDOperand Result =
|
||||
DAG.getTargetConstantPool(CP->get(), getPointerTy(), CP->getAlignment());
|
||||
// Only lower ConstantPool on Darwin.
|
||||
if (getTargetMachine().
|
||||
getSubtarget<X86Subtarget>().isTargetDarwin()) {
|
||||
// With PIC, the address is actually $g + Offset.
|
||||
if (PICEnabled)
|
||||
Result = DAG.getNode(ISD::ADD, getPointerTy(),
|
||||
DAG.getNode(X86ISD::GlobalBaseReg, getPointerTy()), Result);
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
case ISD::GlobalAddress: {
|
||||
SDOperand Result;
|
||||
GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->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.
|
||||
// Only lower GlobalAddress on Darwin.
|
||||
if (getTargetMachine().
|
||||
getSubtarget<X86Subtarget>().getIndirectExternAndWeakGlobals()) {
|
||||
getSubtarget<X86Subtarget>().isTargetDarwin()) {
|
||||
GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
|
||||
SDOperand Addr = DAG.getTargetGlobalAddress(GV, getPointerTy());
|
||||
// With PIC, the address is actually $g + Offset.
|
||||
if (PICEnabled)
|
||||
Addr = DAG.getNode(ISD::ADD, getPointerTy(),
|
||||
DAG.getNode(X86ISD::GlobalBaseReg, getPointerTy()), Addr);
|
||||
|
||||
// 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 (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage() ||
|
||||
(GV->isExternal() && !GV->hasNotBeenReadFromBytecode()))
|
||||
Result = DAG.getLoad(MVT::i32, DAG.getEntryNode(),
|
||||
DAG.getTargetGlobalAddress(GV, getPointerTy()),
|
||||
DAG.getSrcValue(NULL));
|
||||
Addr, DAG.getSrcValue(NULL));
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
case ISD::VASTART: {
|
||||
@ -1913,6 +1936,7 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const {
|
||||
case X86ISD::REP_STOS: return "X86ISD::RET_STOS";
|
||||
case X86ISD::REP_MOVS: return "X86ISD::RET_MOVS";
|
||||
case X86ISD::LOAD_PACK: return "X86ISD::LOAD_PACK";
|
||||
case X86ISD::GlobalBaseReg: return "X86ISD::GlobalBaseReg";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -137,6 +137,10 @@ namespace llvm {
|
||||
/// LOAD_PACK Load a 128-bit packed float / double value. It has the same
|
||||
/// operands as a normal load.
|
||||
LOAD_PACK,
|
||||
|
||||
/// GlobalBaseReg - On Darwin, this node represents the result of the popl
|
||||
/// at function entry, used for PIC code.
|
||||
GlobalBaseReg,
|
||||
};
|
||||
|
||||
// X86 specific condition code. These correspond to X86_*_COND in
|
||||
|
@ -144,6 +144,10 @@ def SSECC : Operand<i8> {
|
||||
let PrintMethod = "printSSECC";
|
||||
}
|
||||
|
||||
def piclabel: Operand<i32> {
|
||||
let PrintMethod = "printPICLabel";
|
||||
}
|
||||
|
||||
// A couple of more descriptive operand definitions.
|
||||
// 16-bits but only 8 bits are significant.
|
||||
def i16i8imm : Operand<i16>;
|
||||
@ -537,6 +541,9 @@ def LEAVE : I<0xC9, RawFrm,
|
||||
def POP32r : I<0x58, AddRegFrm,
|
||||
(ops R32:$reg), "pop{l} $reg", []>, Imp<[ESP],[ESP]>;
|
||||
|
||||
def MovePCtoStack : I<0, Pseudo, (ops piclabel:$label),
|
||||
"call $label", []>;
|
||||
|
||||
let isTwoAddress = 1 in // R32 = bswap R32
|
||||
def BSWAP32r : I<0xC8, AddRegFrm,
|
||||
(ops R32:$dst, R32:$src),
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "llvm/Module.h"
|
||||
#include "llvm/Assembly/Writer.h"
|
||||
#include "llvm/Support/Mangler.h"
|
||||
#include "llvm/Target/TargetOptions.h"
|
||||
using namespace llvm;
|
||||
using namespace x86;
|
||||
|
||||
@ -109,9 +110,32 @@ void X86IntelAsmPrinter::printOp(const MachineOperand &MO,
|
||||
abort ();
|
||||
return;
|
||||
case MachineOperand::MO_GlobalAddress: {
|
||||
if (!Modifier || strcmp(Modifier, "call") || strcmp(Modifier, "mem"))
|
||||
O << "OFFSET ";
|
||||
O << Mang->getValueName(MO.getGlobal());
|
||||
bool isCallOp = Modifier && !strcmp(Modifier, "call");
|
||||
bool isMemOp = Modifier && !strcmp(Modifier, "mem");
|
||||
if (!isMemOp && !isCallOp) O << "OFFSET ";
|
||||
if (forDarwin) {
|
||||
GlobalValue *GV = MO.getGlobal();
|
||||
std::string Name = Mang->getValueName(GV);
|
||||
if (!isMemOp && !isCallOp) O << '$';
|
||||
// Link-once, External, or Weakly-linked global variables need
|
||||
// non-lazily-resolved stubs
|
||||
if (GV->isExternal() || GV->hasWeakLinkage() ||
|
||||
GV->hasLinkOnceLinkage()) {
|
||||
// Dynamically-resolved functions need a stub for the function.
|
||||
if (isCallOp && isa<Function>(GV) && cast<Function>(GV)->isExternal()) {
|
||||
FnStubs.insert(Name);
|
||||
O << "L" << Name << "$stub";
|
||||
} else {
|
||||
GVStubs.insert(Name);
|
||||
O << "L" << Name << "$non_lazy_ptr";
|
||||
if (PICEnabled)
|
||||
O << "-\"L" << getFunctionNumber() << "$pb\"";
|
||||
}
|
||||
} else {
|
||||
O << Mang->getValueName(GV);
|
||||
}
|
||||
} else
|
||||
O << Mang->getValueName(MO.getGlobal());
|
||||
int Offset = MO.getOffset();
|
||||
if (Offset > 0)
|
||||
O << " + " << Offset;
|
||||
@ -119,9 +143,18 @@ void X86IntelAsmPrinter::printOp(const MachineOperand &MO,
|
||||
O << Offset;
|
||||
return;
|
||||
}
|
||||
case MachineOperand::MO_ExternalSymbol:
|
||||
case MachineOperand::MO_ExternalSymbol: {
|
||||
bool isCallOp = Modifier && !strcmp(Modifier, "call");
|
||||
bool isMemOp = Modifier && !strcmp(Modifier, "mem");
|
||||
if (isCallOp && forDarwin) {
|
||||
std::string Name(GlobalPrefix); Name += MO.getSymbolName();
|
||||
FnStubs.insert(Name);
|
||||
O << "L" << Name << "$stub";
|
||||
return;
|
||||
}
|
||||
O << GlobalPrefix << MO.getSymbolName();
|
||||
return;
|
||||
}
|
||||
default:
|
||||
O << "<unknown operand type>"; return;
|
||||
}
|
||||
@ -144,6 +177,8 @@ void X86IntelAsmPrinter::printMemReference(const MachineInstr *MI, unsigned Op){
|
||||
} else if (BaseReg.isConstantPoolIndex()) {
|
||||
O << "[" << PrivateGlobalPrefix << "CPI" << getFunctionNumber() << "_"
|
||||
<< BaseReg.getConstantPoolIndex();
|
||||
if (forDarwin && PICEnabled)
|
||||
O << "-\"L" << getFunctionNumber() << "$pb\"";
|
||||
|
||||
if (IndexReg.getReg()) {
|
||||
O << " + ";
|
||||
@ -193,6 +228,10 @@ void X86IntelAsmPrinter::printMemReference(const MachineInstr *MI, unsigned Op){
|
||||
O << "]";
|
||||
}
|
||||
|
||||
void X86IntelAsmPrinter::printPICLabel(const MachineInstr *MI, unsigned Op) {
|
||||
O << "\"L" << getFunctionNumber() << "$pb\"\n";
|
||||
O << "\"L" << getFunctionNumber() << "$pb\":";
|
||||
}
|
||||
|
||||
/// printMachineInstruction -- Print out a single X86 LLVM instruction
|
||||
/// MI in Intel syntax to the current output stream.
|
||||
|
@ -82,6 +82,7 @@ struct X86IntelAsmPrinter : public X86SharedAsmPrinter {
|
||||
void printOp(const MachineOperand &MO, const char *Modifier = 0);
|
||||
void printSSECC(const MachineInstr *MI, unsigned Op);
|
||||
void printMemReference(const MachineInstr *MI, unsigned Op);
|
||||
void printPICLabel(const MachineInstr *MI, unsigned Op);
|
||||
bool runOnMachineFunction(MachineFunction &F);
|
||||
bool doInitialization(Module &M);
|
||||
};
|
||||
|
@ -148,7 +148,6 @@ X86Subtarget::X86Subtarget(const Module &M, const std::string &FS) {
|
||||
stackAlignment = 8;
|
||||
// FIXME: this is a known good value for Yonah. Not sure about others.
|
||||
MinRepStrSizeThreshold = 128;
|
||||
indirectExternAndWeakGlobals = false;
|
||||
X86SSELevel = NoMMXSSE;
|
||||
X863DNowLevel = NoThreeDNow;
|
||||
Is64Bit = false;
|
||||
@ -183,8 +182,6 @@ X86Subtarget::X86Subtarget(const Module &M, const std::string &FS) {
|
||||
#endif
|
||||
}
|
||||
|
||||
if (TargetType == isDarwin) {
|
||||
if (TargetType == isDarwin)
|
||||
stackAlignment = 16;
|
||||
indirectExternAndWeakGlobals = true;
|
||||
}
|
||||
}
|
||||
|
@ -47,9 +47,6 @@ protected:
|
||||
/// Min. memset / memcpy size that is turned into rep/movs, rep/stos ops.
|
||||
unsigned MinRepStrSizeThreshold;
|
||||
|
||||
/// Used by instruction selector
|
||||
bool indirectExternAndWeakGlobals;
|
||||
|
||||
public:
|
||||
enum {
|
||||
isELF, isCygwin, isDarwin, isWindows
|
||||
@ -71,13 +68,6 @@ public:
|
||||
/// aligned.
|
||||
unsigned getMinRepStrSizeThreshold() const { return MinRepStrSizeThreshold; }
|
||||
|
||||
/// 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;
|
||||
}
|
||||
|
||||
/// ParseSubtargetFeatures - Parses features string setting specified
|
||||
/// subtarget options. Definition of function is auto generated by tblgen.
|
||||
void ParseSubtargetFeatures(const std::string &FS, const std::string &CPU);
|
||||
@ -90,6 +80,8 @@ public:
|
||||
bool hasSSE3() const { return X86SSELevel >= SSE3; }
|
||||
bool has3DNow() const { return X863DNowLevel >= ThreeDNow; }
|
||||
bool has3DNowA() const { return X863DNowLevel >= ThreeDNowA; }
|
||||
|
||||
bool isTargetDarwin() const { return TargetType == isDarwin; }
|
||||
};
|
||||
} // End llvm namespace
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user