forked from OSchip/llvm-project
Implement "general dynamic", "initial exec" and "local exec" TLS models for
X86 32 bits. llvm-svn: 36283
This commit is contained in:
parent
3bf93733b9
commit
2518889872
|
@ -398,6 +398,9 @@ public:
|
||||||
SDNode *getTargetNode(unsigned Opcode, MVT::ValueType VT1,
|
SDNode *getTargetNode(unsigned Opcode, MVT::ValueType VT1,
|
||||||
MVT::ValueType VT2, MVT::ValueType VT3,
|
MVT::ValueType VT2, MVT::ValueType VT3,
|
||||||
SDOperand Op1, SDOperand Op2);
|
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,
|
SDNode *getTargetNode(unsigned Opcode, MVT::ValueType VT1,
|
||||||
MVT::ValueType VT2, MVT::ValueType VT3,
|
MVT::ValueType VT2, MVT::ValueType VT3,
|
||||||
const SDOperand *Ops, unsigned NumOps);
|
const SDOperand *Ops, unsigned NumOps);
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#ifndef LLVM_CODEGEN_SELECTIONDAGNODES_H
|
#ifndef LLVM_CODEGEN_SELECTIONDAGNODES_H
|
||||||
#define LLVM_CODEGEN_SELECTIONDAGNODES_H
|
#define LLVM_CODEGEN_SELECTIONDAGNODES_H
|
||||||
|
|
||||||
|
#include "llvm/GlobalVariable.h"
|
||||||
#include "llvm/Value.h"
|
#include "llvm/Value.h"
|
||||||
#include "llvm/ADT/FoldingSet.h"
|
#include "llvm/ADT/FoldingSet.h"
|
||||||
#include "llvm/ADT/GraphTraits.h"
|
#include "llvm/ADT/GraphTraits.h"
|
||||||
|
@ -95,7 +96,8 @@ namespace ISD {
|
||||||
// Various leaf nodes.
|
// Various leaf nodes.
|
||||||
STRING, BasicBlock, VALUETYPE, CONDCODE, Register,
|
STRING, BasicBlock, VALUETYPE, CONDCODE, Register,
|
||||||
Constant, ConstantFP,
|
Constant, ConstantFP,
|
||||||
GlobalAddress, FrameIndex, JumpTable, ConstantPool, ExternalSymbol,
|
GlobalAddress, GlobalTLSAddress, FrameIndex,
|
||||||
|
JumpTable, ConstantPool, ExternalSymbol,
|
||||||
|
|
||||||
// The address of the GOT
|
// The address of the GOT
|
||||||
GLOBAL_OFFSET_TABLE,
|
GLOBAL_OFFSET_TABLE,
|
||||||
|
@ -124,6 +126,7 @@ namespace ISD {
|
||||||
// anything else with this node, and this is valid in the target-specific
|
// anything else with this node, and this is valid in the target-specific
|
||||||
// dag, turning into a GlobalAddress operand.
|
// dag, turning into a GlobalAddress operand.
|
||||||
TargetGlobalAddress,
|
TargetGlobalAddress,
|
||||||
|
TargetGlobalTLSAddress,
|
||||||
TargetFrameIndex,
|
TargetFrameIndex,
|
||||||
TargetJumpTable,
|
TargetJumpTable,
|
||||||
TargetConstantPool,
|
TargetConstantPool,
|
||||||
|
@ -1164,7 +1167,12 @@ protected:
|
||||||
friend class SelectionDAG;
|
friend class SelectionDAG;
|
||||||
GlobalAddressSDNode(bool isTarget, const GlobalValue *GA, MVT::ValueType VT,
|
GlobalAddressSDNode(bool isTarget, const GlobalValue *GA, MVT::ValueType VT,
|
||||||
int o = 0)
|
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) {
|
getSDVTList(VT)), Offset(o) {
|
||||||
TheGlobal = const_cast<GlobalValue*>(GA);
|
TheGlobal = const_cast<GlobalValue*>(GA);
|
||||||
}
|
}
|
||||||
|
@ -1176,11 +1184,12 @@ public:
|
||||||
static bool classof(const GlobalAddressSDNode *) { return true; }
|
static bool classof(const GlobalAddressSDNode *) { return true; }
|
||||||
static bool classof(const SDNode *N) {
|
static bool classof(const SDNode *N) {
|
||||||
return N->getOpcode() == ISD::GlobalAddress ||
|
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 {
|
class FrameIndexSDNode : public SDNode {
|
||||||
int FI;
|
int FI;
|
||||||
virtual void ANCHOR(); // Out-of-line virtual method to give class a home.
|
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.
|
/// target doesn't support a BSS section.
|
||||||
///
|
///
|
||||||
const char *BSSSection; // Default to ".bss".
|
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
|
/// ZeroFillDirective - Directive for emitting a global to the ZeroFill
|
||||||
/// section on this target. Null if this target doesn't support zerofill.
|
/// section on this target. Null if this target doesn't support zerofill.
|
||||||
const char *ZeroFillDirective; // Default is null.
|
const char *ZeroFillDirective; // Default is null.
|
||||||
|
@ -362,6 +370,12 @@ namespace llvm {
|
||||||
const char *getBSSSection() const {
|
const char *getBSSSection() const {
|
||||||
return BSSSection;
|
return BSSSection;
|
||||||
}
|
}
|
||||||
|
const char *getTLSDataSection() const {
|
||||||
|
return TLSDataSection;
|
||||||
|
}
|
||||||
|
const char *getTLSBSSSection() const {
|
||||||
|
return TLSBSSSection;
|
||||||
|
}
|
||||||
const char *getZeroFillDirective() const {
|
const char *getZeroFillDirective() const {
|
||||||
return ZeroFillDirective;
|
return ZeroFillDirective;
|
||||||
}
|
}
|
||||||
|
|
|
@ -622,6 +622,7 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
|
||||||
case ISD::TargetConstantFP:
|
case ISD::TargetConstantFP:
|
||||||
case ISD::TargetConstantPool:
|
case ISD::TargetConstantPool:
|
||||||
case ISD::TargetGlobalAddress:
|
case ISD::TargetGlobalAddress:
|
||||||
|
case ISD::TargetGlobalTLSAddress:
|
||||||
case ISD::TargetExternalSymbol:
|
case ISD::TargetExternalSymbol:
|
||||||
case ISD::VALUETYPE:
|
case ISD::VALUETYPE:
|
||||||
case ISD::SRCVALUE:
|
case ISD::SRCVALUE:
|
||||||
|
@ -653,6 +654,7 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
|
||||||
assert(0 && "Do not know how to legalize this operator!");
|
assert(0 && "Do not know how to legalize this operator!");
|
||||||
abort();
|
abort();
|
||||||
case ISD::GlobalAddress:
|
case ISD::GlobalAddress:
|
||||||
|
case ISD::GlobalTLSAddress:
|
||||||
case ISD::ExternalSymbol:
|
case ISD::ExternalSymbol:
|
||||||
case ISD::ConstantPool:
|
case ISD::ConstantPool:
|
||||||
case ISD::JumpTable: // Nothing to do.
|
case ISD::JumpTable: // Nothing to do.
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include "llvm/CodeGen/SelectionDAG.h"
|
#include "llvm/CodeGen/SelectionDAG.h"
|
||||||
#include "llvm/Constants.h"
|
#include "llvm/Constants.h"
|
||||||
#include "llvm/GlobalValue.h"
|
#include "llvm/GlobalValue.h"
|
||||||
|
#include "llvm/GlobalVariable.h"
|
||||||
#include "llvm/Intrinsics.h"
|
#include "llvm/Intrinsics.h"
|
||||||
#include "llvm/Assembly/Writer.h"
|
#include "llvm/Assembly/Writer.h"
|
||||||
#include "llvm/CodeGen/MachineBasicBlock.h"
|
#include "llvm/CodeGen/MachineBasicBlock.h"
|
||||||
|
@ -296,7 +297,9 @@ static void AddNodeIDNode(FoldingSetNodeID &ID, SDNode *N) {
|
||||||
ID.AddDouble(cast<ConstantFPSDNode>(N)->getValue());
|
ID.AddDouble(cast<ConstantFPSDNode>(N)->getValue());
|
||||||
break;
|
break;
|
||||||
case ISD::TargetGlobalAddress:
|
case ISD::TargetGlobalAddress:
|
||||||
case ISD::GlobalAddress: {
|
case ISD::GlobalAddress:
|
||||||
|
case ISD::TargetGlobalTLSAddress:
|
||||||
|
case ISD::GlobalTLSAddress: {
|
||||||
GlobalAddressSDNode *GA = cast<GlobalAddressSDNode>(N);
|
GlobalAddressSDNode *GA = cast<GlobalAddressSDNode>(N);
|
||||||
ID.AddPointer(GA->getGlobal());
|
ID.AddPointer(GA->getGlobal());
|
||||||
ID.AddInteger(GA->getOffset());
|
ID.AddInteger(GA->getOffset());
|
||||||
|
@ -692,7 +695,12 @@ SDOperand SelectionDAG::getConstantFP(double Val, MVT::ValueType VT,
|
||||||
SDOperand SelectionDAG::getGlobalAddress(const GlobalValue *GV,
|
SDOperand SelectionDAG::getGlobalAddress(const GlobalValue *GV,
|
||||||
MVT::ValueType VT, int Offset,
|
MVT::ValueType VT, int Offset,
|
||||||
bool isTargetGA) {
|
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;
|
FoldingSetNodeID ID;
|
||||||
AddNodeIDNode(ID, Opc, getVTList(VT), 0, 0);
|
AddNodeIDNode(ID, Opc, getVTList(VT), 0, 0);
|
||||||
ID.AddPointer(GV);
|
ID.AddPointer(GV);
|
||||||
|
@ -2282,6 +2290,14 @@ SDNode *SelectionDAG::getTargetNode(unsigned Opcode, MVT::ValueType VT1,
|
||||||
SDOperand Ops[] = { Op1, Op2 };
|
SDOperand Ops[] = { Op1, Op2 };
|
||||||
return getNode(ISD::BUILTIN_OP_END+Opcode, VTs, 3, Ops, 2).Val;
|
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,
|
SDNode *SelectionDAG::getTargetNode(unsigned Opcode, MVT::ValueType VT1,
|
||||||
MVT::ValueType VT2, MVT::ValueType VT3,
|
MVT::ValueType VT2, MVT::ValueType VT3,
|
||||||
const SDOperand *Ops, unsigned NumOps) {
|
const SDOperand *Ops, unsigned NumOps) {
|
||||||
|
@ -2702,6 +2718,7 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const {
|
||||||
case ISD::Constant: return "Constant";
|
case ISD::Constant: return "Constant";
|
||||||
case ISD::ConstantFP: return "ConstantFP";
|
case ISD::ConstantFP: return "ConstantFP";
|
||||||
case ISD::GlobalAddress: return "GlobalAddress";
|
case ISD::GlobalAddress: return "GlobalAddress";
|
||||||
|
case ISD::GlobalTLSAddress: return "GlobalTLSAddress";
|
||||||
case ISD::FrameIndex: return "FrameIndex";
|
case ISD::FrameIndex: return "FrameIndex";
|
||||||
case ISD::JumpTable: return "JumpTable";
|
case ISD::JumpTable: return "JumpTable";
|
||||||
case ISD::GLOBAL_OFFSET_TABLE: return "GLOBAL_OFFSET_TABLE";
|
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::TargetConstant: return "TargetConstant";
|
||||||
case ISD::TargetConstantFP:return "TargetConstantFP";
|
case ISD::TargetConstantFP:return "TargetConstantFP";
|
||||||
case ISD::TargetGlobalAddress: return "TargetGlobalAddress";
|
case ISD::TargetGlobalAddress: return "TargetGlobalAddress";
|
||||||
|
case ISD::TargetGlobalTLSAddress: return "TargetGlobalTLSAddress";
|
||||||
case ISD::TargetFrameIndex: return "TargetFrameIndex";
|
case ISD::TargetFrameIndex: return "TargetFrameIndex";
|
||||||
case ISD::TargetJumpTable: return "TargetJumpTable";
|
case ISD::TargetJumpTable: return "TargetJumpTable";
|
||||||
case ISD::TargetConstantPool: return "TargetConstantPool";
|
case ISD::TargetConstantPool: return "TargetConstantPool";
|
||||||
|
|
|
@ -20,6 +20,8 @@ TargetAsmInfo::TargetAsmInfo() :
|
||||||
TextSection(".text"),
|
TextSection(".text"),
|
||||||
DataSection(".data"),
|
DataSection(".data"),
|
||||||
BSSSection(".bss"),
|
BSSSection(".bss"),
|
||||||
|
TLSDataSection("\t.section .tdata,\"awT\",@progbits"),
|
||||||
|
TLSBSSSection("\t.section .tbss,\"awT\",@nobits"),
|
||||||
ZeroFillDirective(0),
|
ZeroFillDirective(0),
|
||||||
AddressSize(4),
|
AddressSize(4),
|
||||||
NeedsSet(false),
|
NeedsSet(false),
|
||||||
|
|
|
@ -211,6 +211,10 @@ def globaladdr : SDNode<"ISD::GlobalAddress", SDTPtrLeaf, [],
|
||||||
"GlobalAddressSDNode">;
|
"GlobalAddressSDNode">;
|
||||||
def tglobaladdr : SDNode<"ISD::TargetGlobalAddress", SDTPtrLeaf, [],
|
def tglobaladdr : SDNode<"ISD::TargetGlobalAddress", SDTPtrLeaf, [],
|
||||||
"GlobalAddressSDNode">;
|
"GlobalAddressSDNode">;
|
||||||
|
def globaltlsaddr : SDNode<"ISD::GlobalTLSAddress", SDTPtrLeaf, [],
|
||||||
|
"GlobalAddressSDNode">;
|
||||||
|
def tglobaltlsaddr : SDNode<"ISD::TargetGlobalTLSAddress", SDTPtrLeaf, [],
|
||||||
|
"GlobalAddressSDNode">;
|
||||||
def constpool : SDNode<"ISD::ConstantPool", SDTPtrLeaf, [],
|
def constpool : SDNode<"ISD::ConstantPool", SDTPtrLeaf, [],
|
||||||
"ConstantPoolSDNode">;
|
"ConstantPoolSDNode">;
|
||||||
def tconstpool : SDNode<"ISD::TargetConstantPool", SDTPtrLeaf, [],
|
def tconstpool : SDNode<"ISD::TargetConstantPool", SDTPtrLeaf, [],
|
||||||
|
|
|
@ -272,9 +272,13 @@ void X86ATTAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
|
||||||
case MachineOperand::MO_GlobalAddress: {
|
case MachineOperand::MO_GlobalAddress: {
|
||||||
bool isCallOp = Modifier && !strcmp(Modifier, "call");
|
bool isCallOp = Modifier && !strcmp(Modifier, "call");
|
||||||
bool isMemOp = Modifier && !strcmp(Modifier, "mem");
|
bool isMemOp = Modifier && !strcmp(Modifier, "mem");
|
||||||
if (!isMemOp && !isCallOp) O << '$';
|
|
||||||
|
|
||||||
GlobalValue *GV = MO.getGlobal();
|
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);
|
std::string Name = Mang->getValueName(GV);
|
||||||
X86SharedAsmPrinter::decorateName(Name, GV);
|
X86SharedAsmPrinter::decorateName(Name, GV);
|
||||||
|
|
||||||
|
@ -328,7 +332,15 @@ void X86ATTAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
|
||||||
else if (Offset < 0)
|
else if (Offset < 0)
|
||||||
O << Offset;
|
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 (printGOT(TM, Subtarget)) {
|
||||||
if (Subtarget->GVRequiresExtraLoad(GV, TM, false))
|
if (Subtarget->GVRequiresExtraLoad(GV, TM, false))
|
||||||
O << "@GOT";
|
O << "@GOT";
|
||||||
|
|
|
@ -171,7 +171,7 @@ bool X86SharedAsmPrinter::doFinalization(Module &M) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!I->hasSection() &&
|
if (!I->hasSection() && !I->isThreadLocal() &&
|
||||||
(I->hasInternalLinkage() || I->hasWeakLinkage() ||
|
(I->hasInternalLinkage() || I->hasWeakLinkage() ||
|
||||||
I->hasLinkOnceLinkage())) {
|
I->hasLinkOnceLinkage())) {
|
||||||
if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
|
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());
|
SwitchToDataSection(SectionName.c_str());
|
||||||
} else {
|
} else {
|
||||||
if (C->isNullValue() && !NoZerosInBSS && TAI->getBSSSection())
|
if (C->isNullValue() && !NoZerosInBSS && TAI->getBSSSection())
|
||||||
SwitchToDataSection(TAI->getBSSSection(), I);
|
SwitchToDataSection(I->isThreadLocal() ? TAI->getTLSBSSSection() :
|
||||||
|
TAI->getBSSSection(), I);
|
||||||
else if (!I->isConstant())
|
else if (!I->isConstant())
|
||||||
SwitchToDataSection(TAI->getDataSection(), I);
|
SwitchToDataSection(I->isThreadLocal() ? TAI->getTLSDataSection() :
|
||||||
|
TAI->getDataSection(), I);
|
||||||
|
else if (I->isThreadLocal())
|
||||||
|
SwitchToDataSection(TAI->getTLSDataSection());
|
||||||
else {
|
else {
|
||||||
// Read-only data.
|
// Read-only data.
|
||||||
bool HasReloc = C->ContainsRelocations();
|
bool HasReloc = C->ContainsRelocations();
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "llvm/CallingConv.h"
|
#include "llvm/CallingConv.h"
|
||||||
#include "llvm/Constants.h"
|
#include "llvm/Constants.h"
|
||||||
#include "llvm/DerivedTypes.h"
|
#include "llvm/DerivedTypes.h"
|
||||||
|
#include "llvm/GlobalVariable.h"
|
||||||
#include "llvm/Function.h"
|
#include "llvm/Function.h"
|
||||||
#include "llvm/Intrinsics.h"
|
#include "llvm/Intrinsics.h"
|
||||||
#include "llvm/ADT/VectorExtras.h"
|
#include "llvm/ADT/VectorExtras.h"
|
||||||
|
@ -200,6 +201,7 @@ X86TargetLowering::X86TargetLowering(TargetMachine &TM)
|
||||||
setOperationAction(ISD::ConstantPool , MVT::i32 , Custom);
|
setOperationAction(ISD::ConstantPool , MVT::i32 , Custom);
|
||||||
setOperationAction(ISD::JumpTable , MVT::i32 , Custom);
|
setOperationAction(ISD::JumpTable , MVT::i32 , Custom);
|
||||||
setOperationAction(ISD::GlobalAddress , MVT::i32 , Custom);
|
setOperationAction(ISD::GlobalAddress , MVT::i32 , Custom);
|
||||||
|
setOperationAction(ISD::GlobalTLSAddress, MVT::i32 , Custom);
|
||||||
setOperationAction(ISD::ExternalSymbol , MVT::i32 , Custom);
|
setOperationAction(ISD::ExternalSymbol , MVT::i32 , Custom);
|
||||||
if (Subtarget->is64Bit()) {
|
if (Subtarget->is64Bit()) {
|
||||||
setOperationAction(ISD::ConstantPool , MVT::i64 , Custom);
|
setOperationAction(ISD::ConstantPool , MVT::i64 , Custom);
|
||||||
|
@ -2943,6 +2945,76 @@ X86TargetLowering::LowerGlobalAddress(SDOperand Op, SelectionDAG &DAG) {
|
||||||
return Result;
|
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
|
SDOperand
|
||||||
X86TargetLowering::LowerExternalSymbol(SDOperand Op, SelectionDAG &DAG) {
|
X86TargetLowering::LowerExternalSymbol(SDOperand Op, SelectionDAG &DAG) {
|
||||||
const char *Sym = cast<ExternalSymbolSDNode>(Op)->getSymbol();
|
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::SCALAR_TO_VECTOR: return LowerSCALAR_TO_VECTOR(Op, DAG);
|
||||||
case ISD::ConstantPool: return LowerConstantPool(Op, DAG);
|
case ISD::ConstantPool: return LowerConstantPool(Op, DAG);
|
||||||
case ISD::GlobalAddress: return LowerGlobalAddress(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::ExternalSymbol: return LowerExternalSymbol(Op, DAG);
|
||||||
case ISD::SHL_PARTS:
|
case ISD::SHL_PARTS:
|
||||||
case ISD::SRA_PARTS:
|
case ISD::SRA_PARTS:
|
||||||
|
@ -4090,6 +4163,8 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const {
|
||||||
case X86ISD::PINSRW: return "X86ISD::PINSRW";
|
case X86ISD::PINSRW: return "X86ISD::PINSRW";
|
||||||
case X86ISD::FMAX: return "X86ISD::FMAX";
|
case X86ISD::FMAX: return "X86ISD::FMAX";
|
||||||
case X86ISD::FMIN: return "X86ISD::FMIN";
|
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 - 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 LowerSCALAR_TO_VECTOR(SDOperand Op, SelectionDAG &DAG);
|
||||||
SDOperand LowerConstantPool(SDOperand Op, SelectionDAG &DAG);
|
SDOperand LowerConstantPool(SDOperand Op, SelectionDAG &DAG);
|
||||||
SDOperand LowerGlobalAddress(SDOperand Op, SelectionDAG &DAG);
|
SDOperand LowerGlobalAddress(SDOperand Op, SelectionDAG &DAG);
|
||||||
|
SDOperand LowerGlobalTLSAddress(SDOperand Op, SelectionDAG &DAG);
|
||||||
SDOperand LowerExternalSymbol(SDOperand Op, SelectionDAG &DAG);
|
SDOperand LowerExternalSymbol(SDOperand Op, SelectionDAG &DAG);
|
||||||
SDOperand LowerShift(SDOperand Op, SelectionDAG &DAG);
|
SDOperand LowerShift(SDOperand Op, SelectionDAG &DAG);
|
||||||
SDOperand LowerSINT_TO_FP(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 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 X86shld : SDNode<"X86ISD::SHLD", SDTIntShiftDOp>;
|
||||||
def X86shrd : SDNode<"X86ISD::SHRD", 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 X86Wrapper : SDNode<"X86ISD::Wrapper", SDTX86Wrapper>;
|
||||||
def X86WrapperRIP : SDNode<"X86ISD::WrapperRIP", 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.
|
// 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),
|
def MOV32_mr : I<0x89, MRMDestMem, (ops i32mem:$dst, GR32_:$src),
|
||||||
"mov{l} {$src, $dst|$dst, $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
|
// DWARF Pseudo Instructions
|
||||||
//
|
//
|
||||||
|
|
|
@ -2654,10 +2654,12 @@ public:
|
||||||
} else {
|
} else {
|
||||||
NodeOps.push_back(Val);
|
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()];
|
Record *Op = OperatorMap[N->getName()];
|
||||||
// Transform GlobalAddress to TargetGlobalAddress
|
// Transform GlobalAddress to TargetGlobalAddress
|
||||||
if (Op && Op->getName() == "globaladdr") {
|
if (Op && (Op->getName() == "globaladdr" ||
|
||||||
|
Op->getName() == "globaltlsaddr")) {
|
||||||
emitCode("SDOperand Tmp" + utostr(ResNo) + " = CurDAG->getTarget"
|
emitCode("SDOperand Tmp" + utostr(ResNo) + " = CurDAG->getTarget"
|
||||||
"GlobalAddress(cast<GlobalAddressSDNode>(" + Val +
|
"GlobalAddress(cast<GlobalAddressSDNode>(" + Val +
|
||||||
")->getGlobal(), " + getEnumName(N->getTypeNum(0)) +
|
")->getGlobal(), " + getEnumName(N->getTypeNum(0)) +
|
||||||
|
@ -3716,6 +3718,7 @@ void DAGISelEmitter::EmitInstructionSelector(std::ostream &OS) {
|
||||||
<< " case ISD::TargetConstantPool:\n"
|
<< " case ISD::TargetConstantPool:\n"
|
||||||
<< " case ISD::TargetFrameIndex:\n"
|
<< " case ISD::TargetFrameIndex:\n"
|
||||||
<< " case ISD::TargetJumpTable:\n"
|
<< " case ISD::TargetJumpTable:\n"
|
||||||
|
<< " case ISD::TargetGlobalTLSAddress:\n"
|
||||||
<< " case ISD::TargetGlobalAddress: {\n"
|
<< " case ISD::TargetGlobalAddress: {\n"
|
||||||
<< " return NULL;\n"
|
<< " return NULL;\n"
|
||||||
<< " }\n"
|
<< " }\n"
|
||||||
|
|
Loading…
Reference in New Issue