mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 11:13:28 +01:00
Implement initial-exec TLS model for 32-bit PIC x86
This fixes a TODO from 2007 :) Previously, LLVM would emit the wrong code here (see the update to test/CodeGen/X86/tls-pie.ll). llvm-svn: 156611
This commit is contained in:
parent
5138c169b1
commit
a5a417fcd3
@ -128,6 +128,13 @@ namespace X86II {
|
||||
/// SYMBOL_LABEL @NTPOFF
|
||||
MO_NTPOFF,
|
||||
|
||||
/// MO_GOTNTPOFF - On a symbol operand this indicates that the immediate is
|
||||
/// some TLS offset.
|
||||
///
|
||||
/// See 'ELF Handling for Thread-Local Storage' for more details.
|
||||
/// SYMBOL_LABEL @GOTNTPOFF
|
||||
MO_GOTNTPOFF,
|
||||
|
||||
/// MO_DLLIMPORT - On a symbol operand "FOO", this indicates that the
|
||||
/// reference is actually to the "__imp_FOO" symbol. This is used for
|
||||
/// dllimport linkage on windows.
|
||||
|
@ -190,6 +190,7 @@ void X86AsmPrinter::printSymbolOperand(const MachineOperand &MO,
|
||||
case X86II::MO_INDNTPOFF: O << "@INDNTPOFF"; break;
|
||||
case X86II::MO_TPOFF: O << "@TPOFF"; break;
|
||||
case X86II::MO_NTPOFF: O << "@NTPOFF"; break;
|
||||
case X86II::MO_GOTNTPOFF: O << "@GOTNTPOFF"; break;
|
||||
case X86II::MO_GOTPCREL: O << "@GOTPCREL"; break;
|
||||
case X86II::MO_GOT: O << "@GOT"; break;
|
||||
case X86II::MO_GOTOFF: O << "@GOTOFF"; break;
|
||||
|
@ -7286,11 +7286,10 @@ LowerToTLSGeneralDynamicModel64(GlobalAddressSDNode *GA, SelectionDAG &DAG,
|
||||
X86::RAX, X86II::MO_TLSGD);
|
||||
}
|
||||
|
||||
// Lower ISD::GlobalTLSAddress using the "initial exec" (for no-pic) or
|
||||
// "local exec" model.
|
||||
// Lower ISD::GlobalTLSAddress using the "initial exec" or "local exec" model.
|
||||
static SDValue LowerToTLSExecModel(GlobalAddressSDNode *GA, SelectionDAG &DAG,
|
||||
const EVT PtrVT, TLSModel::Model model,
|
||||
bool is64Bit) {
|
||||
bool is64Bit, bool isPIC) {
|
||||
DebugLoc dl = GA->getDebugLoc();
|
||||
|
||||
// Get the Thread Pointer, which is %gs:0 (32-bit) or %fs:0 (64-bit).
|
||||
@ -7308,25 +7307,36 @@ static SDValue LowerToTLSExecModel(GlobalAddressSDNode *GA, SelectionDAG &DAG,
|
||||
unsigned WrapperKind = X86ISD::Wrapper;
|
||||
if (model == TLSModel::LocalExec) {
|
||||
OperandFlags = is64Bit ? X86II::MO_TPOFF : X86II::MO_NTPOFF;
|
||||
} else if (is64Bit) {
|
||||
assert(model == TLSModel::InitialExec);
|
||||
OperandFlags = X86II::MO_GOTTPOFF;
|
||||
WrapperKind = X86ISD::WrapperRIP;
|
||||
} else if (model == TLSModel::InitialExec) {
|
||||
if (is64Bit) {
|
||||
OperandFlags = X86II::MO_GOTTPOFF;
|
||||
WrapperKind = X86ISD::WrapperRIP;
|
||||
} else {
|
||||
OperandFlags = isPIC ? X86II::MO_GOTNTPOFF : X86II::MO_INDNTPOFF;
|
||||
}
|
||||
} else {
|
||||
assert(model == TLSModel::InitialExec);
|
||||
OperandFlags = X86II::MO_INDNTPOFF;
|
||||
llvm_unreachable("Unexpected model");
|
||||
}
|
||||
|
||||
// emit "addl x@ntpoff,%eax" (local exec) or "addl x@indntpoff,%eax" (initial
|
||||
// exec)
|
||||
// emit "addl x@ntpoff,%eax" (local exec)
|
||||
// or "addl x@indntpoff,%eax" (initial exec)
|
||||
// or "addl x@gotntpoff(%ebx) ,%eax" (initial exec, 32-bit pic)
|
||||
SDValue TGA = DAG.getTargetGlobalAddress(GA->getGlobal(), dl,
|
||||
GA->getValueType(0),
|
||||
GA->getOffset(), OperandFlags);
|
||||
SDValue Offset = DAG.getNode(WrapperKind, dl, PtrVT, TGA);
|
||||
|
||||
if (model == TLSModel::InitialExec)
|
||||
Offset = DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), Offset,
|
||||
MachinePointerInfo::getGOT(), false, false, false, 0);
|
||||
if (model == TLSModel::InitialExec) {
|
||||
if (isPIC && !is64Bit) {
|
||||
Offset = DAG.getNode(ISD::ADD, dl, PtrVT,
|
||||
DAG.getNode(X86ISD::GlobalBaseReg, DebugLoc(), PtrVT),
|
||||
Offset);
|
||||
} else {
|
||||
Offset = DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), Offset,
|
||||
MachinePointerInfo::getGOT(), false, false, false,
|
||||
0);
|
||||
}
|
||||
}
|
||||
|
||||
// The address of the thread local variable is the add of the thread
|
||||
// pointer with the offset of the variable.
|
||||
@ -7341,7 +7351,6 @@ X86TargetLowering::LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const {
|
||||
|
||||
if (Subtarget->isTargetELF()) {
|
||||
// TODO: implement the "local dynamic" model
|
||||
// TODO: implement the "initial exec"model for pic executables
|
||||
|
||||
// If GV is an alias then use the aliasee for determining
|
||||
// thread-localness.
|
||||
@ -7360,7 +7369,8 @@ X86TargetLowering::LowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const {
|
||||
case TLSModel::InitialExec:
|
||||
case TLSModel::LocalExec:
|
||||
return LowerToTLSExecModel(GA, DAG, getPointerTy(), model,
|
||||
Subtarget->is64Bit());
|
||||
Subtarget->is64Bit(),
|
||||
getTargetMachine().getRelocationModel() == Reloc::PIC_);
|
||||
}
|
||||
llvm_unreachable("Unknown TLS model.");
|
||||
}
|
||||
|
@ -160,6 +160,7 @@ MCOperand X86MCInstLower::LowerSymbolOperand(const MachineOperand &MO,
|
||||
case X86II::MO_INDNTPOFF: RefKind = MCSymbolRefExpr::VK_INDNTPOFF; break;
|
||||
case X86II::MO_TPOFF: RefKind = MCSymbolRefExpr::VK_TPOFF; break;
|
||||
case X86II::MO_NTPOFF: RefKind = MCSymbolRefExpr::VK_NTPOFF; break;
|
||||
case X86II::MO_GOTNTPOFF: RefKind = MCSymbolRefExpr::VK_GOTNTPOFF; break;
|
||||
case X86II::MO_GOTPCREL: RefKind = MCSymbolRefExpr::VK_GOTPCREL; break;
|
||||
case X86II::MO_GOT: RefKind = MCSymbolRefExpr::VK_GOT; break;
|
||||
case X86II::MO_GOTOFF: RefKind = MCSymbolRefExpr::VK_GOTOFF; break;
|
||||
|
@ -35,8 +35,12 @@ entry:
|
||||
|
||||
define i32 @f3() {
|
||||
; X32: f3:
|
||||
; X32: movl i2@INDNTPOFF, %eax
|
||||
; X32-NEXT: movl %gs:(%eax), %eax
|
||||
; X32: calll .L{{[0-9]+}}$pb
|
||||
; X32-NEXT: .L{{[0-9]+}}$pb:
|
||||
; X32-NEXT: popl %eax
|
||||
; X32-NEXT: .Ltmp{{[0-9]+}}:
|
||||
; X32-NEXT: addl $_GLOBAL_OFFSET_TABLE_+(.Ltmp{{[0-9]+}}-.L{{[0-9]+}}$pb), %eax
|
||||
; X32-NEXT: leal %gs:i2@GOTNTPOFF(%eax), %eax
|
||||
; X32-NEXT: ret
|
||||
; X64: f3:
|
||||
; X64: movq i2@GOTTPOFF(%rip), %rax
|
||||
@ -50,8 +54,13 @@ entry:
|
||||
|
||||
define i32* @f4() {
|
||||
; X32: f4:
|
||||
; X32: movl %gs:0, %eax
|
||||
; X32-NEXT: addl i2@INDNTPOFF, %eax
|
||||
; X32: calll .L{{[0-9]+}}$pb
|
||||
; X32-NEXT: .L{{[0-9]+}}$pb:
|
||||
; X32-NEXT: popl %eax
|
||||
; X32-NEXT: .Ltmp{{[0-9]+}}:
|
||||
; X32-NEXT: addl $_GLOBAL_OFFSET_TABLE_+(.Ltmp{{[0-9]+}}-.L{{[0-9]+}}$pb), %eax
|
||||
; X32-NEXT: leal i2@GOTNTPOFF(%eax), %eax
|
||||
; X32-NEXT: addl %gs:0, %eax
|
||||
; X32-NEXT: ret
|
||||
; X64: f4:
|
||||
; X64: movq %fs:0, %rax
|
||||
|
Loading…
Reference in New Issue
Block a user