From def9e129cab586da107b1ab4ed44fab7202247ad Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Tue, 7 Jun 2016 03:15:07 +0000 Subject: [PATCH] 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 --- lib/Target/ARM/ARMAsmPrinter.cpp | 2 ++ lib/Target/ARM/ARMConstantPoolValue.cpp | 2 ++ lib/Target/ARM/ARMConstantPoolValue.h | 1 + lib/Target/ARM/ARMISelLowering.cpp | 14 ++++++-- lib/Target/ARM/MCTargetDesc/ARMBaseInfo.h | 10 ++++-- test/CodeGen/ARM/Windows/tls.ll | 44 +++++++++++++++-------- 6 files changed, 54 insertions(+), 19 deletions(-) diff --git a/lib/Target/ARM/ARMAsmPrinter.cpp b/lib/Target/ARM/ARMAsmPrinter.cpp index 71fa0a51ac9..27bf01b5dff 100644 --- a/lib/Target/ARM/ARMAsmPrinter.cpp +++ b/lib/Target/ARM/ARMAsmPrinter.cpp @@ -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!"); } diff --git a/lib/Target/ARM/ARMConstantPoolValue.cpp b/lib/Target/ARM/ARMConstantPoolValue.cpp index 2dbe236cc77..c0db001cb6f 100644 --- a/lib/Target/ARM/ARMConstantPoolValue.cpp +++ b/lib/Target/ARM/ARMConstantPoolValue.cpp @@ -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!"); } diff --git a/lib/Target/ARM/ARMConstantPoolValue.h b/lib/Target/ARM/ARMConstantPoolValue.h index f719df8fe04..c07331d71da 100644 --- a/lib/Target/ARM/ARMConstantPoolValue.h +++ b/lib/Target/ARM/ARMConstantPoolValue.h @@ -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) }; } diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index 6a05e5473bb..a5c698bc4ed 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -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(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 diff --git a/lib/Target/ARM/MCTargetDesc/ARMBaseInfo.h b/lib/Target/ARM/MCTargetDesc/ARMBaseInfo.h index 4289a73e9d6..5bc10d613a3 100644 --- a/lib/Target/ARM/MCTargetDesc/ARMBaseInfo.h +++ b/lib/Target/ARM/MCTargetDesc/ARMBaseInfo.h @@ -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 diff --git a/test/CodeGen/ARM/Windows/tls.ll b/test/CodeGen/ARM/Windows/tls.ll index 9022f8af9f5..689f4e29187 100644 --- a/test/CodeGen/ARM/Windows/tls.ll +++ b/test/CodeGen/ARM/Windows/tls.ll @@ -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) +