mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 12:41:49 +01:00
ARM: correct TLS access on WoA
TLS access requires an offset from the TLS index. The index itself is the section-relative distance of the symbol. For ARM, the relevant relocation (IMAGE_REL_ARM_SECREL) is applied as a constant. This means that the value may not be an immediate and must be lowered into a constant pool. This offset will not be base relocated. We were previously emitting the actual address of the symbol which would be base relocated and would therefore be the vaue offset by the ImageBase + TLS Offset. llvm-svn: 271974
This commit is contained in:
parent
2807ed1c8c
commit
def9e129ca
@ -902,6 +902,8 @@ getModifierVariantKind(ARMCP::ARMCPModifier Modifier) {
|
||||
return MCSymbolRefExpr::VK_GOTTPOFF;
|
||||
case ARMCP::GOT_PREL:
|
||||
return MCSymbolRefExpr::VK_ARM_GOT_PREL;
|
||||
case ARMCP::SECREL:
|
||||
return MCSymbolRefExpr::VK_SECREL;
|
||||
}
|
||||
llvm_unreachable("Invalid ARMCPModifier!");
|
||||
}
|
||||
|
@ -60,6 +60,8 @@ const char *ARMConstantPoolValue::getModifierText() const {
|
||||
return "gottpoff";
|
||||
case ARMCP::TPOFF:
|
||||
return "tpoff";
|
||||
case ARMCP::SECREL:
|
||||
return "secrel32";
|
||||
}
|
||||
llvm_unreachable("Unknown modifier!");
|
||||
}
|
||||
|
@ -42,6 +42,7 @@ namespace ARMCP {
|
||||
GOT_PREL, /// Global Offset Table, PC Relative
|
||||
GOTTPOFF, /// Global Offset Table, Thread Pointer Offset
|
||||
TPOFF, /// Thread Pointer Offset
|
||||
SECREL, /// Section Relative (Windows TLS)
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -2622,6 +2622,7 @@ SDValue
|
||||
ARMTargetLowering::LowerGlobalTLSAddressWindows(SDValue Op,
|
||||
SelectionDAG &DAG) const {
|
||||
assert(Subtarget->isTargetWindows() && "Windows specific TLS lowering");
|
||||
|
||||
SDValue Chain = DAG.getEntryNode();
|
||||
EVT PtrVT = getPointerTy(DAG.getDataLayout());
|
||||
SDLoc DL(Op);
|
||||
@ -2663,8 +2664,17 @@ ARMTargetLowering::LowerGlobalTLSAddressWindows(SDValue Op,
|
||||
DAG.getNode(ISD::ADD, DL, PtrVT, TLSArray, Slot),
|
||||
MachinePointerInfo(), false, false, false, 0);
|
||||
|
||||
return DAG.getNode(ISD::ADD, DL, PtrVT, TLS,
|
||||
LowerGlobalAddressWindows(Op, DAG));
|
||||
// Get the offset of the start of the .tls section (section base)
|
||||
const auto *GA = cast<GlobalAddressSDNode>(Op);
|
||||
auto *CPV = ARMConstantPoolConstant::Create(GA->getGlobal(), ARMCP::SECREL);
|
||||
SDValue Offset =
|
||||
DAG.getLoad(PtrVT, DL, Chain,
|
||||
DAG.getNode(ARMISD::Wrapper, DL, MVT::i32,
|
||||
DAG.getTargetConstantPool(CPV, PtrVT, 4)),
|
||||
MachinePointerInfo::getConstantPool(DAG.getMachineFunction()),
|
||||
false, false, false, 0);
|
||||
|
||||
return DAG.getNode(ISD::ADD, DL, PtrVT, TLS, Offset);
|
||||
}
|
||||
|
||||
// Lower ISD::GlobalTLSAddress using the "general dynamic" model
|
||||
|
@ -295,12 +295,18 @@ namespace ARMII {
|
||||
|
||||
/// MO_OPTION_MASK - Most flags are mutually exclusive; this mask selects
|
||||
/// just that part of the flag set.
|
||||
MO_OPTION_MASK = 0x3f,
|
||||
MO_OPTION_MASK = 0x1f,
|
||||
|
||||
/// MO_DLLIMPORT - On a symbol operand, this represents that the reference
|
||||
/// to the symbol is for an import stub. This is used for DLL import
|
||||
/// storage class indication on Windows.
|
||||
MO_DLLIMPORT = 0x40,
|
||||
MO_DLLIMPORT = 0x20,
|
||||
|
||||
/// MO_SECREL - On a symbol operand this indicates that the immediate is
|
||||
/// the offset from beginning of section.
|
||||
///
|
||||
/// This is the TLS offset for the COFF/Windows TLS mechanism.
|
||||
MO_SECREL = 0x40,
|
||||
|
||||
/// MO_NONLAZY - This is an independent flag, on a symbol operand "FOO" it
|
||||
/// represents a symbol which, if indirect, will get special Darwin mangling
|
||||
|
@ -1,4 +1,4 @@
|
||||
; RUN: llc -mtriple thumbv7--windows %s -o - | FileCheck %s
|
||||
; RUN: llc -mtriple thumbv7--windows-itanium %s -o - | FileCheck %s
|
||||
|
||||
@i = thread_local global i32 0
|
||||
@j = external thread_local global i32
|
||||
@ -22,11 +22,13 @@ define i32 @f() {
|
||||
; CHECK: ldr [[TLS_POINTER:r[0-9]]], {{\[}}[[TEB]], #44]
|
||||
; CHECK-NEXT: ldr{{.w}} [[TLS:r[0-9]]], {{\[}}[[TLS_POINTER]], [[INDEX]], lsl #2]
|
||||
|
||||
; CHECK-NEXT: movw [[SLOT:r[0-9]]], :lower16:i
|
||||
; CHECK-NEXT: movt [[SLOT]], :upper16:i
|
||||
; CHECK-NEXT: ldr [[SLOT:r[0-9]]], [[CPI:LCPI[0-9]+_[0-9]+]]
|
||||
|
||||
; CHECK-NEXT: ldr r0, {{\[}}[[TLS]], [[SLOT]]]
|
||||
|
||||
; CHECK: [[CPI]]:
|
||||
; CHECK-NEXT: .long i(SECREL32)
|
||||
|
||||
define i32 @e() {
|
||||
%1 = load i32, i32* @j
|
||||
ret i32 %1
|
||||
@ -41,11 +43,13 @@ define i32 @e() {
|
||||
; CHECK: ldr [[TLS_POINTER:r[0-9]]], {{\[}}[[TEB]], #44]
|
||||
; CHECK-NEXT: ldr{{.w}} [[TLS:r[0-9]]], {{\[}}[[TLS_POINTER]], [[INDEX]], lsl #2]
|
||||
|
||||
; CHECK-NEXT: movw [[SLOT:r[0-9]]], :lower16:j
|
||||
; CHECK-NEXT: movt [[SLOT]], :upper16:j
|
||||
; CHECK-NEXT: ldr [[SLOT:r[0-9]]], [[CPI:LCPI[0-9]+_[0-9]+]]
|
||||
|
||||
; CHECK-NEXT: ldr r0, {{\[}}[[TLS]], [[SLOT]]]
|
||||
|
||||
; CHECK: [[CPI]]:
|
||||
; CHECK-NEXT: .long j(SECREL32)
|
||||
|
||||
define i32 @d() {
|
||||
%1 = load i32, i32* @k
|
||||
ret i32 %1
|
||||
@ -60,11 +64,13 @@ define i32 @d() {
|
||||
; CHECK: ldr [[TLS_POINTER:r[0-9]]], {{\[}}[[TEB]], #44]
|
||||
; CHECK-NEXT: ldr{{.w}} [[TLS:r[0-9]]], {{\[}}[[TLS_POINTER]], [[INDEX]], lsl #2]
|
||||
|
||||
; CHECK-NEXT: movw [[SLOT:r[0-9]]], :lower16:k
|
||||
; CHECK-NEXT: movt [[SLOT]], :upper16:k
|
||||
; CHECK-NEXT: ldr [[SLOT:r[0-9]]], [[CPI:LCPI[0-9]+_[0-9]+]]
|
||||
|
||||
; CHECK-NEXT: ldr r0, {{\[}}[[TLS]], [[SLOT]]]
|
||||
|
||||
; CHECK: [[CPI]]:
|
||||
; CHECK-NEXT: .long k(SECREL32)
|
||||
|
||||
define i32 @c() {
|
||||
%1 = load i32, i32* @l
|
||||
ret i32 %1
|
||||
@ -79,11 +85,13 @@ define i32 @c() {
|
||||
; CHECK: ldr [[TLS_POINTER:r[0-9]]], {{\[}}[[TEB]], #44]
|
||||
; CHECK-NEXT: ldr{{.w}} [[TLS:r[0-9]]], {{\[}}[[TLS_POINTER]], [[INDEX]], lsl #2]
|
||||
|
||||
; CHECK-NEXT: movw [[SLOT:r[0-9]]], :lower16:l
|
||||
; CHECK-NEXT: movt [[SLOT]], :upper16:l
|
||||
; CHECK-NEXT: ldr [[SLOT:r[0-9]]], [[CPI:LCPI[0-9]+_[0-9]+]]
|
||||
|
||||
; CHECK-NEXT: ldr r0, {{\[}}[[TLS]], [[SLOT]]]
|
||||
|
||||
; CHECK: [[CPI]]:
|
||||
; CHECK-NEXT: .long l(SECREL32)
|
||||
|
||||
define i32 @b() {
|
||||
%1 = load i32, i32* @m
|
||||
ret i32 %1
|
||||
@ -98,11 +106,13 @@ define i32 @b() {
|
||||
; CHECK: ldr [[TLS_POINTER:r[0-9]]], {{\[}}[[TEB]], #44]
|
||||
; CHECK-NEXT: ldr{{.w}} [[TLS:r[0-9]]], {{\[}}[[TLS_POINTER]], [[INDEX]], lsl #2]
|
||||
|
||||
; CHECK-NEXT: movw [[SLOT:r[0-9]]], :lower16:m
|
||||
; CHECK-NEXT: movt [[SLOT]], :upper16:m
|
||||
; CHECK-NEXT: ldr [[SLOT:r[0-9]]], [[CPI:LCPI[0-9]+_[0-9]+]]
|
||||
|
||||
; CHECK-NEXT: ldr r0, {{\[}}[[TLS]], [[SLOT]]]
|
||||
|
||||
; CHECK: [[CPI]]:
|
||||
; CHECK: .long m(SECREL32)
|
||||
|
||||
define i16 @a() {
|
||||
%1 = load i16, i16* @n
|
||||
ret i16 %1
|
||||
@ -117,11 +127,13 @@ define i16 @a() {
|
||||
; CHECK: ldr [[TLS_POINTER:r[0-9]]], {{\[}}[[TEB]], #44]
|
||||
; CHECK-NEXT: ldr{{.w}} [[TLS:r[0-9]]], {{\[}}[[TLS_POINTER]], [[INDEX]], lsl #2]
|
||||
|
||||
; CHECK-NEXT: movw [[SLOT:r[0-9]]], :lower16:n
|
||||
; CHECK-NEXT: movt [[SLOT]], :upper16:n
|
||||
; CHECK-NEXT: ldr [[SLOT:r[0-9]]], [[CPI:LCPI[0-9]+_[0-9]+]]
|
||||
|
||||
; CHECK-NEXT: ldrh r0, {{\[}}[[TLS]], [[SLOT]]]
|
||||
|
||||
; CHECK: [[CPI]]:
|
||||
; CHECK: .long n(SECREL32)
|
||||
|
||||
define i8 @Z() {
|
||||
%1 = load i8, i8* @o
|
||||
ret i8 %1
|
||||
@ -136,8 +148,10 @@ define i8 @Z() {
|
||||
; CHECK: ldr [[TLS_POINTER:r[0-9]]], {{\[}}[[TEB]], #44]
|
||||
; CHECK-NEXT: ldr{{.w}} [[TLS:r[0-9]]], {{\[}}[[TLS_POINTER]], [[INDEX]], lsl #2]
|
||||
|
||||
; CHECK-NEXT: movw [[SLOT:r[0-9]]], :lower16:o
|
||||
; CHECK-NEXT: movt [[SLOT]], :upper16:o
|
||||
; CHECK-NEXT: ldr [[SLOT:r[0-9]]], [[CPI:LCPI[0-9]+_[0-9]+]]
|
||||
|
||||
; CHECK-NEXT: ldrb r0, {{\[}}[[TLS]], [[SLOT]]]
|
||||
|
||||
; CHECK: [[CPI]]:
|
||||
; CHECK-NEXT: .long o(SECREL32)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user