mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-13 07:00:59 +00:00
Implement "general dynamic", "initial exec" and "local exec" TLS models for
X86 32 bits. llvm-svn: 36283
This commit is contained in:
parent
1835371d44
commit
bc32d90b46
@ -398,6 +398,9 @@ public:
|
||||
SDNode *getTargetNode(unsigned Opcode, MVT::ValueType VT1,
|
||||
MVT::ValueType VT2, MVT::ValueType VT3,
|
||||
SDOperand Op1, SDOperand Op2);
|
||||
SDNode *getTargetNode(unsigned Opcode, MVT::ValueType VT1,
|
||||
MVT::ValueType VT2, MVT::ValueType VT3,
|
||||
SDOperand Op1, SDOperand Op2, SDOperand Op3);
|
||||
SDNode *getTargetNode(unsigned Opcode, MVT::ValueType VT1,
|
||||
MVT::ValueType VT2, MVT::ValueType VT3,
|
||||
const SDOperand *Ops, unsigned NumOps);
|
||||
|
@ -19,6 +19,7 @@
|
||||
#ifndef LLVM_CODEGEN_SELECTIONDAGNODES_H
|
||||
#define LLVM_CODEGEN_SELECTIONDAGNODES_H
|
||||
|
||||
#include "llvm/GlobalVariable.h"
|
||||
#include "llvm/Value.h"
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
#include "llvm/ADT/GraphTraits.h"
|
||||
@ -95,7 +96,8 @@ namespace ISD {
|
||||
// Various leaf nodes.
|
||||
STRING, BasicBlock, VALUETYPE, CONDCODE, Register,
|
||||
Constant, ConstantFP,
|
||||
GlobalAddress, FrameIndex, JumpTable, ConstantPool, ExternalSymbol,
|
||||
GlobalAddress, GlobalTLSAddress, FrameIndex,
|
||||
JumpTable, ConstantPool, ExternalSymbol,
|
||||
|
||||
// The address of the GOT
|
||||
GLOBAL_OFFSET_TABLE,
|
||||
@ -124,6 +126,7 @@ namespace ISD {
|
||||
// anything else with this node, and this is valid in the target-specific
|
||||
// dag, turning into a GlobalAddress operand.
|
||||
TargetGlobalAddress,
|
||||
TargetGlobalTLSAddress,
|
||||
TargetFrameIndex,
|
||||
TargetJumpTable,
|
||||
TargetConstantPool,
|
||||
@ -1164,7 +1167,12 @@ protected:
|
||||
friend class SelectionDAG;
|
||||
GlobalAddressSDNode(bool isTarget, const GlobalValue *GA, MVT::ValueType VT,
|
||||
int o = 0)
|
||||
: SDNode(isTarget ? ISD::TargetGlobalAddress : ISD::GlobalAddress,
|
||||
: SDNode(dyn_cast<GlobalVariable>(GA) &&
|
||||
dyn_cast<GlobalVariable>(GA)->isThreadLocal() ?
|
||||
// Thread Local
|
||||
(isTarget ? ISD::TargetGlobalTLSAddress : ISD::GlobalTLSAddress) :
|
||||
// Non Thread Local
|
||||
(isTarget ? ISD::TargetGlobalAddress : ISD::GlobalAddress),
|
||||
getSDVTList(VT)), Offset(o) {
|
||||
TheGlobal = const_cast<GlobalValue*>(GA);
|
||||
}
|
||||
@ -1176,11 +1184,12 @@ public:
|
||||
static bool classof(const GlobalAddressSDNode *) { return true; }
|
||||
static bool classof(const SDNode *N) {
|
||||
return N->getOpcode() == ISD::GlobalAddress ||
|
||||
N->getOpcode() == ISD::TargetGlobalAddress;
|
||||
N->getOpcode() == ISD::TargetGlobalAddress ||
|
||||
N->getOpcode() == ISD::GlobalTLSAddress ||
|
||||
N->getOpcode() == ISD::TargetGlobalTLSAddress;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class FrameIndexSDNode : public SDNode {
|
||||
int FI;
|
||||
virtual void ANCHOR(); // Out-of-line virtual method to give class a home.
|
||||
|
@ -43,7 +43,15 @@ namespace llvm {
|
||||
/// target doesn't support a BSS section.
|
||||
///
|
||||
const char *BSSSection; // Default to ".bss".
|
||||
|
||||
|
||||
/// TLSDataSection - Section directive for Thread Local data.
|
||||
///
|
||||
const char *TLSDataSection;// Defaults to ".section .tdata,"awT",@progbits".
|
||||
|
||||
/// TLSBSSSection - Section directive for Thread Local uninitialized data.
|
||||
/// Null if this target doesn't support a BSS section.
|
||||
///
|
||||
const char *TLSBSSSection;// Default to ".section .tbss,"awT",@nobits".
|
||||
/// ZeroFillDirective - Directive for emitting a global to the ZeroFill
|
||||
/// section on this target. Null if this target doesn't support zerofill.
|
||||
const char *ZeroFillDirective; // Default is null.
|
||||
@ -362,6 +370,12 @@ namespace llvm {
|
||||
const char *getBSSSection() const {
|
||||
return BSSSection;
|
||||
}
|
||||
const char *getTLSDataSection() const {
|
||||
return TLSDataSection;
|
||||
}
|
||||
const char *getTLSBSSSection() const {
|
||||
return TLSBSSSection;
|
||||
}
|
||||
const char *getZeroFillDirective() const {
|
||||
return ZeroFillDirective;
|
||||
}
|
||||
|
@ -622,6 +622,7 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
|
||||
case ISD::TargetConstantFP:
|
||||
case ISD::TargetConstantPool:
|
||||
case ISD::TargetGlobalAddress:
|
||||
case ISD::TargetGlobalTLSAddress:
|
||||
case ISD::TargetExternalSymbol:
|
||||
case ISD::VALUETYPE:
|
||||
case ISD::SRCVALUE:
|
||||
@ -653,6 +654,7 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
|
||||
assert(0 && "Do not know how to legalize this operator!");
|
||||
abort();
|
||||
case ISD::GlobalAddress:
|
||||
case ISD::GlobalTLSAddress:
|
||||
case ISD::ExternalSymbol:
|
||||
case ISD::ConstantPool:
|
||||
case ISD::JumpTable: // Nothing to do.
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "llvm/CodeGen/SelectionDAG.h"
|
||||
#include "llvm/Constants.h"
|
||||
#include "llvm/GlobalValue.h"
|
||||
#include "llvm/GlobalVariable.h"
|
||||
#include "llvm/Intrinsics.h"
|
||||
#include "llvm/Assembly/Writer.h"
|
||||
#include "llvm/CodeGen/MachineBasicBlock.h"
|
||||
@ -296,7 +297,9 @@ static void AddNodeIDNode(FoldingSetNodeID &ID, SDNode *N) {
|
||||
ID.AddDouble(cast<ConstantFPSDNode>(N)->getValue());
|
||||
break;
|
||||
case ISD::TargetGlobalAddress:
|
||||
case ISD::GlobalAddress: {
|
||||
case ISD::GlobalAddress:
|
||||
case ISD::TargetGlobalTLSAddress:
|
||||
case ISD::GlobalTLSAddress: {
|
||||
GlobalAddressSDNode *GA = cast<GlobalAddressSDNode>(N);
|
||||
ID.AddPointer(GA->getGlobal());
|
||||
ID.AddInteger(GA->getOffset());
|
||||
@ -692,7 +695,12 @@ SDOperand SelectionDAG::getConstantFP(double Val, MVT::ValueType VT,
|
||||
SDOperand SelectionDAG::getGlobalAddress(const GlobalValue *GV,
|
||||
MVT::ValueType VT, int Offset,
|
||||
bool isTargetGA) {
|
||||
unsigned Opc = isTargetGA ? ISD::TargetGlobalAddress : ISD::GlobalAddress;
|
||||
const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV);
|
||||
unsigned Opc;
|
||||
if (GVar && GVar->isThreadLocal())
|
||||
Opc = isTargetGA ? ISD::TargetGlobalTLSAddress : ISD::GlobalTLSAddress;
|
||||
else
|
||||
Opc = isTargetGA ? ISD::TargetGlobalAddress : ISD::GlobalAddress;
|
||||
FoldingSetNodeID ID;
|
||||
AddNodeIDNode(ID, Opc, getVTList(VT), 0, 0);
|
||||
ID.AddPointer(GV);
|
||||
@ -2282,6 +2290,14 @@ SDNode *SelectionDAG::getTargetNode(unsigned Opcode, MVT::ValueType VT1,
|
||||
SDOperand Ops[] = { Op1, Op2 };
|
||||
return getNode(ISD::BUILTIN_OP_END+Opcode, VTs, 3, Ops, 2).Val;
|
||||
}
|
||||
SDNode *SelectionDAG::getTargetNode(unsigned Opcode, MVT::ValueType VT1,
|
||||
MVT::ValueType VT2, MVT::ValueType VT3,
|
||||
SDOperand Op1, SDOperand Op2,
|
||||
SDOperand Op3) {
|
||||
const MVT::ValueType *VTs = getNodeValueTypes(VT1, VT2, VT3);
|
||||
SDOperand Ops[] = { Op1, Op2, Op3 };
|
||||
return getNode(ISD::BUILTIN_OP_END+Opcode, VTs, 3, Ops, 3).Val;
|
||||
}
|
||||
SDNode *SelectionDAG::getTargetNode(unsigned Opcode, MVT::ValueType VT1,
|
||||
MVT::ValueType VT2, MVT::ValueType VT3,
|
||||
const SDOperand *Ops, unsigned NumOps) {
|
||||
@ -2702,6 +2718,7 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const {
|
||||
case ISD::Constant: return "Constant";
|
||||
case ISD::ConstantFP: return "ConstantFP";
|
||||
case ISD::GlobalAddress: return "GlobalAddress";
|
||||
case ISD::GlobalTLSAddress: return "GlobalTLSAddress";
|
||||
case ISD::FrameIndex: return "FrameIndex";
|
||||
case ISD::JumpTable: return "JumpTable";
|
||||
case ISD::GLOBAL_OFFSET_TABLE: return "GLOBAL_OFFSET_TABLE";
|
||||
@ -2725,6 +2742,7 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const {
|
||||
case ISD::TargetConstant: return "TargetConstant";
|
||||
case ISD::TargetConstantFP:return "TargetConstantFP";
|
||||
case ISD::TargetGlobalAddress: return "TargetGlobalAddress";
|
||||
case ISD::TargetGlobalTLSAddress: return "TargetGlobalTLSAddress";
|
||||
case ISD::TargetFrameIndex: return "TargetFrameIndex";
|
||||
case ISD::TargetJumpTable: return "TargetJumpTable";
|
||||
case ISD::TargetConstantPool: return "TargetConstantPool";
|
||||
|
@ -20,6 +20,8 @@ TargetAsmInfo::TargetAsmInfo() :
|
||||
TextSection(".text"),
|
||||
DataSection(".data"),
|
||||
BSSSection(".bss"),
|
||||
TLSDataSection("\t.section .tdata,\"awT\",@progbits"),
|
||||
TLSBSSSection("\t.section .tbss,\"awT\",@nobits"),
|
||||
ZeroFillDirective(0),
|
||||
AddressSize(4),
|
||||
NeedsSet(false),
|
||||
|
@ -211,6 +211,10 @@ def globaladdr : SDNode<"ISD::GlobalAddress", SDTPtrLeaf, [],
|
||||
"GlobalAddressSDNode">;
|
||||
def tglobaladdr : SDNode<"ISD::TargetGlobalAddress", SDTPtrLeaf, [],
|
||||
"GlobalAddressSDNode">;
|
||||
def globaltlsaddr : SDNode<"ISD::GlobalTLSAddress", SDTPtrLeaf, [],
|
||||
"GlobalAddressSDNode">;
|
||||
def tglobaltlsaddr : SDNode<"ISD::TargetGlobalTLSAddress", SDTPtrLeaf, [],
|
||||
"GlobalAddressSDNode">;
|
||||
def constpool : SDNode<"ISD::ConstantPool", SDTPtrLeaf, [],
|
||||
"ConstantPoolSDNode">;
|
||||
def tconstpool : SDNode<"ISD::TargetConstantPool", SDTPtrLeaf, [],
|
||||
|
@ -272,9 +272,13 @@ 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 << '$';
|
||||
|
||||
GlobalValue *GV = MO.getGlobal();
|
||||
GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV);
|
||||
bool isThreadLocal = GVar && GVar->isThreadLocal();
|
||||
|
||||
if (!isMemOp && !isCallOp && !isThreadLocal) O << '$';
|
||||
|
||||
std::string Name = Mang->getValueName(GV);
|
||||
X86SharedAsmPrinter::decorateName(Name, GV);
|
||||
|
||||
@ -328,7 +332,15 @@ void X86ATTAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
|
||||
else if (Offset < 0)
|
||||
O << Offset;
|
||||
|
||||
if (isMemOp) {
|
||||
if (isThreadLocal) {
|
||||
if (TM.getRelocationModel() == Reloc::PIC_)
|
||||
O << "@TLSGD"; // general dynamic TLS model
|
||||
else
|
||||
if (GV->isDeclaration())
|
||||
O << "@INDNTPOFF"; // initial exec TLS model
|
||||
else
|
||||
O << "@NTPOFF"; // local exec TLS model
|
||||
} else if (isMemOp) {
|
||||
if (printGOT(TM, Subtarget)) {
|
||||
if (Subtarget->GVRequiresExtraLoad(GV, TM, false))
|
||||
O << "@GOT";
|
||||
|
@ -171,7 +171,7 @@ bool X86SharedAsmPrinter::doFinalization(Module &M) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!I->hasSection() &&
|
||||
if (!I->hasSection() && !I->isThreadLocal() &&
|
||||
(I->hasInternalLinkage() || I->hasWeakLinkage() ||
|
||||
I->hasLinkOnceLinkage())) {
|
||||
if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
|
||||
@ -256,9 +256,13 @@ bool X86SharedAsmPrinter::doFinalization(Module &M) {
|
||||
SwitchToDataSection(SectionName.c_str());
|
||||
} else {
|
||||
if (C->isNullValue() && !NoZerosInBSS && TAI->getBSSSection())
|
||||
SwitchToDataSection(TAI->getBSSSection(), I);
|
||||
SwitchToDataSection(I->isThreadLocal() ? TAI->getTLSBSSSection() :
|
||||
TAI->getBSSSection(), I);
|
||||
else if (!I->isConstant())
|
||||
SwitchToDataSection(TAI->getDataSection(), I);
|
||||
SwitchToDataSection(I->isThreadLocal() ? TAI->getTLSDataSection() :
|
||||
TAI->getDataSection(), I);
|
||||
else if (I->isThreadLocal())
|
||||
SwitchToDataSection(TAI->getTLSDataSection());
|
||||
else {
|
||||
// Read-only data.
|
||||
bool HasReloc = C->ContainsRelocations();
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "llvm/CallingConv.h"
|
||||
#include "llvm/Constants.h"
|
||||
#include "llvm/DerivedTypes.h"
|
||||
#include "llvm/GlobalVariable.h"
|
||||
#include "llvm/Function.h"
|
||||
#include "llvm/Intrinsics.h"
|
||||
#include "llvm/ADT/VectorExtras.h"
|
||||
@ -200,6 +201,7 @@ X86TargetLowering::X86TargetLowering(TargetMachine &TM)
|
||||
setOperationAction(ISD::ConstantPool , MVT::i32 , Custom);
|
||||
setOperationAction(ISD::JumpTable , MVT::i32 , Custom);
|
||||
setOperationAction(ISD::GlobalAddress , MVT::i32 , Custom);
|
||||
setOperationAction(ISD::GlobalTLSAddress, MVT::i32 , Custom);
|
||||
setOperationAction(ISD::ExternalSymbol , MVT::i32 , Custom);
|
||||
if (Subtarget->is64Bit()) {
|
||||
setOperationAction(ISD::ConstantPool , MVT::i64 , Custom);
|
||||
@ -2943,6 +2945,76 @@ X86TargetLowering::LowerGlobalAddress(SDOperand Op, SelectionDAG &DAG) {
|
||||
return Result;
|
||||
}
|
||||
|
||||
// Lower ISD::GlobalTLSAddress using the "general dynamic" model
|
||||
static SDOperand
|
||||
LowerToTLSGeneralDynamicModel(GlobalAddressSDNode *GA, SelectionDAG &DAG,
|
||||
const MVT::ValueType PtrVT) {
|
||||
SDOperand InFlag;
|
||||
SDOperand Chain = DAG.getCopyToReg(DAG.getEntryNode(), X86::EBX,
|
||||
DAG.getNode(X86ISD::GlobalBaseReg,
|
||||
PtrVT), InFlag);
|
||||
InFlag = Chain.getValue(1);
|
||||
|
||||
// emit leal symbol@TLSGD(,%ebx,1), %eax
|
||||
SDVTList NodeTys = DAG.getVTList(PtrVT, MVT::Other, MVT::Flag);
|
||||
SDOperand TGA = DAG.getTargetGlobalAddress(GA->getGlobal(),
|
||||
GA->getValueType(0),
|
||||
GA->getOffset());
|
||||
SDOperand Ops[] = { Chain, TGA, InFlag };
|
||||
SDOperand Result = DAG.getNode(X86ISD::TLSADDR, NodeTys, Ops, 3);
|
||||
InFlag = Result.getValue(2);
|
||||
Chain = Result.getValue(1);
|
||||
|
||||
// call ___tls_get_addr. This function receives its argument in
|
||||
// the register EAX.
|
||||
Chain = DAG.getCopyToReg(Chain, X86::EAX, Result, InFlag);
|
||||
InFlag = Chain.getValue(1);
|
||||
|
||||
NodeTys = DAG.getVTList(MVT::Other, MVT::Flag);
|
||||
SDOperand Ops1[] = { Chain,
|
||||
DAG.getTargetExternalSymbol("___tls_get_addr",
|
||||
PtrVT),
|
||||
DAG.getRegister(X86::EAX, PtrVT),
|
||||
DAG.getRegister(X86::EBX, PtrVT),
|
||||
InFlag };
|
||||
Chain = DAG.getNode(X86ISD::CALL, NodeTys, Ops1, 5);
|
||||
InFlag = Chain.getValue(1);
|
||||
|
||||
return DAG.getCopyFromReg(Chain, X86::EAX, PtrVT, InFlag);
|
||||
}
|
||||
|
||||
// Lower ISD::GlobalTLSAddress using the "initial exec" (for no-pic) or
|
||||
// "local exec" model.
|
||||
static SDOperand
|
||||
LowerToTLSExecModel(GlobalAddressSDNode *GA, SelectionDAG &DAG,
|
||||
const MVT::ValueType PtrVT) {
|
||||
// Get the Thread Pointer
|
||||
SDOperand ThreadPointer = DAG.getNode(X86ISD::THREAD_POINTER, PtrVT);
|
||||
// emit "addl x@ntpoff,%eax" (local exec) or "addl x@indntpoff,%eax" (initial
|
||||
// exec)
|
||||
SDOperand TGA = DAG.getTargetGlobalAddress(GA->getGlobal(),
|
||||
GA->getValueType(0),
|
||||
GA->getOffset());
|
||||
SDOperand Offset = DAG.getNode(X86ISD::Wrapper, PtrVT, TGA);
|
||||
// The address of the thread local variable is the add of the thread
|
||||
// pointer with the offset of the variable.
|
||||
return DAG.getNode(ISD::ADD, PtrVT, ThreadPointer, Offset);
|
||||
}
|
||||
|
||||
SDOperand
|
||||
X86TargetLowering::LowerGlobalTLSAddress(SDOperand Op, SelectionDAG &DAG) {
|
||||
// TODO: implement the "local dynamic" model
|
||||
// TODO: implement the "initial exec"model for pic executables
|
||||
assert(!Subtarget->is64Bit() && "TLS not implemented for X86_64");
|
||||
GlobalAddressSDNode *GA = cast<GlobalAddressSDNode>(Op);
|
||||
// If the relocation model is PIC, use the "General Dynamic" TLS Model,
|
||||
// otherwise use the "Local Exec"TLS Model
|
||||
if (getTargetMachine().getRelocationModel() == Reloc::PIC_)
|
||||
return LowerToTLSGeneralDynamicModel(GA, DAG, getPointerTy());
|
||||
else
|
||||
return LowerToTLSExecModel(GA, DAG, getPointerTy());
|
||||
}
|
||||
|
||||
SDOperand
|
||||
X86TargetLowering::LowerExternalSymbol(SDOperand Op, SelectionDAG &DAG) {
|
||||
const char *Sym = cast<ExternalSymbolSDNode>(Op)->getSymbol();
|
||||
@ -4022,6 +4094,7 @@ SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
|
||||
case ISD::SCALAR_TO_VECTOR: return LowerSCALAR_TO_VECTOR(Op, DAG);
|
||||
case ISD::ConstantPool: return LowerConstantPool(Op, DAG);
|
||||
case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG);
|
||||
case ISD::GlobalTLSAddress: return LowerGlobalTLSAddress(Op, DAG);
|
||||
case ISD::ExternalSymbol: return LowerExternalSymbol(Op, DAG);
|
||||
case ISD::SHL_PARTS:
|
||||
case ISD::SRA_PARTS:
|
||||
@ -4090,6 +4163,8 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const {
|
||||
case X86ISD::PINSRW: return "X86ISD::PINSRW";
|
||||
case X86ISD::FMAX: return "X86ISD::FMAX";
|
||||
case X86ISD::FMIN: return "X86ISD::FMIN";
|
||||
case X86ISD::TLSADDR: return "X86ISD::TLSADDR";
|
||||
case X86ISD::THREAD_POINTER: return "X86ISD::THREAD_POINTER";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -176,7 +176,9 @@ namespace llvm {
|
||||
|
||||
/// FMAX, FMIN - Floating point max and min.
|
||||
///
|
||||
FMAX, FMIN
|
||||
FMAX, FMIN,
|
||||
// Thread Local Storage
|
||||
TLSADDR, THREAD_POINTER
|
||||
};
|
||||
}
|
||||
|
||||
@ -386,6 +388,7 @@ namespace llvm {
|
||||
SDOperand LowerSCALAR_TO_VECTOR(SDOperand Op, SelectionDAG &DAG);
|
||||
SDOperand LowerConstantPool(SDOperand Op, SelectionDAG &DAG);
|
||||
SDOperand LowerGlobalAddress(SDOperand Op, SelectionDAG &DAG);
|
||||
SDOperand LowerGlobalTLSAddress(SDOperand Op, SelectionDAG &DAG);
|
||||
SDOperand LowerExternalSymbol(SDOperand Op, SelectionDAG &DAG);
|
||||
SDOperand LowerShift(SDOperand Op, SelectionDAG &DAG);
|
||||
SDOperand LowerSINT_TO_FP(SDOperand Op, SelectionDAG &DAG);
|
||||
|
@ -47,6 +47,10 @@ def SDTX86RdTsc : SDTypeProfile<0, 0, []>;
|
||||
|
||||
def SDTX86Wrapper : SDTypeProfile<1, 1, [SDTCisSameAs<0, 1>, SDTCisPtrTy<0>]>;
|
||||
|
||||
def SDT_X86TLSADDR : SDTypeProfile<1, 1, [SDTCisPtrTy<0>, SDTCisInt<1>]>;
|
||||
|
||||
def SDT_X86TLSTP : SDTypeProfile<1, 0, [SDTCisPtrTy<0>]>;
|
||||
|
||||
def X86shld : SDNode<"X86ISD::SHLD", SDTIntShiftDOp>;
|
||||
def X86shrd : SDNode<"X86ISD::SHRD", SDTIntShiftDOp>;
|
||||
|
||||
@ -87,6 +91,11 @@ def X86rdtsc : SDNode<"X86ISD::RDTSC_DAG",SDTX86RdTsc,
|
||||
def X86Wrapper : SDNode<"X86ISD::Wrapper", SDTX86Wrapper>;
|
||||
def X86WrapperRIP : SDNode<"X86ISD::WrapperRIP", SDTX86Wrapper>;
|
||||
|
||||
def X86tlsaddr : SDNode<"X86ISD::TLSADDR", SDT_X86TLSADDR,
|
||||
[SDNPHasChain, SDNPInFlag, SDNPOutFlag]>;
|
||||
def X86TLStp : SDNode<"X86ISD::THREAD_POINTER", SDT_X86TLSTP, []>;
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// X86 Operand Definitions.
|
||||
//
|
||||
@ -2448,6 +2457,19 @@ def MOV16_mr : I<0x89, MRMDestMem, (ops i16mem:$dst, GR16_:$src),
|
||||
def MOV32_mr : I<0x89, MRMDestMem, (ops i32mem:$dst, GR32_:$src),
|
||||
"mov{l} {$src, $dst|$dst, $src}", []>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Thread Local Storage Instructions
|
||||
//
|
||||
|
||||
def TLS_addr : I<0, Pseudo, (ops GR32:$dst, i32imm:$sym),
|
||||
"leal $sym(,%ebx,1), $dst",
|
||||
[(set GR32:$dst, (X86tlsaddr tglobaltlsaddr:$sym))]>,
|
||||
Imp<[EBX],[]>;
|
||||
|
||||
def TLS_tp : I<0, Pseudo, (ops GR32:$dst),
|
||||
"movl %gs:0, $dst",
|
||||
[(set GR32:$dst, X86TLStp)]>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// DWARF Pseudo Instructions
|
||||
//
|
||||
|
@ -2654,10 +2654,12 @@ public:
|
||||
} else {
|
||||
NodeOps.push_back(Val);
|
||||
}
|
||||
} else if (!N->isLeaf() && N->getOperator()->getName() == "tglobaladdr") {
|
||||
} else if (!N->isLeaf() && (N->getOperator()->getName() == "tglobaladdr"
|
||||
|| N->getOperator()->getName() == "tglobaltlsaddr")) {
|
||||
Record *Op = OperatorMap[N->getName()];
|
||||
// Transform GlobalAddress to TargetGlobalAddress
|
||||
if (Op && Op->getName() == "globaladdr") {
|
||||
if (Op && (Op->getName() == "globaladdr" ||
|
||||
Op->getName() == "globaltlsaddr")) {
|
||||
emitCode("SDOperand Tmp" + utostr(ResNo) + " = CurDAG->getTarget"
|
||||
"GlobalAddress(cast<GlobalAddressSDNode>(" + Val +
|
||||
")->getGlobal(), " + getEnumName(N->getTypeNum(0)) +
|
||||
@ -3716,6 +3718,7 @@ void DAGISelEmitter::EmitInstructionSelector(std::ostream &OS) {
|
||||
<< " case ISD::TargetConstantPool:\n"
|
||||
<< " case ISD::TargetFrameIndex:\n"
|
||||
<< " case ISD::TargetJumpTable:\n"
|
||||
<< " case ISD::TargetGlobalTLSAddress:\n"
|
||||
<< " case ISD::TargetGlobalAddress: {\n"
|
||||
<< " return NULL;\n"
|
||||
<< " }\n"
|
||||
|
Loading…
x
Reference in New Issue
Block a user