llvm.org GIT mirror llvm / c8b2a4c
[AArch64] Implement native TLS for Windows Differential Revision: https://reviews.llvm.org/D43971 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@327220 91177308-0d34-0410-b5e6-96231b3b80d8 Martin Storsjo 2 years ago
5 changed file(s) with 148 addition(s) and 2 deletion(s). Raw diff Collapse all Expand all
39753975 return DAG.getNode(ISD::ADD, DL, PtrVT, ThreadBase, TPOff);
39763976 }
39773977
3978 SDValue
3979 AArch64TargetLowering::LowerWindowsGlobalTLSAddress(SDValue Op,
3980 SelectionDAG &DAG) const {
3981 assert(Subtarget->isTargetWindows() && "Windows specific TLS lowering");
3982
3983 SDValue Chain = DAG.getEntryNode();
3984 EVT PtrVT = getPointerTy(DAG.getDataLayout());
3985 SDLoc DL(Op);
3986
3987 SDValue TEB = DAG.getRegister(AArch64::X18, MVT::i64);
3988
3989 // Load the ThreadLocalStoragePointer from the TEB
3990 // A pointer to the TLS array is located at offset 0x58 from the TEB.
3991 SDValue TLSArray =
3992 DAG.getNode(ISD::ADD, DL, PtrVT, TEB, DAG.getIntPtrConstant(0x58, DL));
3993 TLSArray = DAG.getLoad(PtrVT, DL, Chain, TLSArray, MachinePointerInfo());
3994 Chain = TLSArray.getValue(1);
3995
3996 // Load the TLS index from the C runtime;
3997 // This does the same as getAddr(), but without having a GlobalAddressSDNode.
3998 // This also does the same as LOADgot, but using a generic i32 load,
3999 // while LOADgot only loads i64.
4000 SDValue TLSIndexHi =
4001 DAG.getTargetExternalSymbol("_tls_index", PtrVT, AArch64II::MO_PAGE);
4002 SDValue TLSIndexLo = DAG.getTargetExternalSymbol(
4003 "_tls_index", PtrVT, AArch64II::MO_PAGEOFF | AArch64II::MO_NC);
4004 SDValue ADRP = DAG.getNode(AArch64ISD::ADRP, DL, PtrVT, TLSIndexHi);
4005 SDValue TLSIndex =
4006 DAG.getNode(AArch64ISD::ADDlow, DL, PtrVT, ADRP, TLSIndexLo);
4007 TLSIndex = DAG.getLoad(MVT::i32, DL, Chain, TLSIndex, MachinePointerInfo());
4008 Chain = TLSIndex.getValue(1);
4009
4010 // The pointer to the thread's TLS data area is at the TLS Index scaled by 8
4011 // offset into the TLSArray.
4012 TLSIndex = DAG.getNode(ISD::ZERO_EXTEND, DL, PtrVT, TLSIndex);
4013 SDValue Slot = DAG.getNode(ISD::SHL, DL, PtrVT, TLSIndex,
4014 DAG.getConstant(3, DL, PtrVT));
4015 SDValue TLS = DAG.getLoad(PtrVT, DL, Chain,
4016 DAG.getNode(ISD::ADD, DL, PtrVT, TLSArray, Slot),
4017 MachinePointerInfo());
4018 Chain = TLS.getValue(1);
4019
4020 const GlobalAddressSDNode *GA = cast(Op);
4021 const GlobalValue *GV = GA->getGlobal();
4022 SDValue TGAHi = DAG.getTargetGlobalAddress(
4023 GV, DL, PtrVT, 0, AArch64II::MO_TLS | AArch64II::MO_HI12);
4024 SDValue TGALo = DAG.getTargetGlobalAddress(
4025 GV, DL, PtrVT, 0,
4026 AArch64II::MO_TLS | AArch64II::MO_PAGEOFF | AArch64II::MO_NC);
4027
4028 // Add the offset from the start of the .tls section (section base).
4029 SDValue Addr =
4030 SDValue(DAG.getMachineNode(AArch64::ADDXri, DL, PtrVT, TLS, TGAHi,
4031 DAG.getTargetConstant(0, DL, MVT::i32)),
4032 0);
4033 Addr = SDValue(DAG.getMachineNode(AArch64::ADDXri, DL, PtrVT, Addr, TGALo,
4034 DAG.getTargetConstant(0, DL, MVT::i32)),
4035 0);
4036 return Addr;
4037 }
4038
39784039 SDValue AArch64TargetLowering::LowerGlobalTLSAddress(SDValue Op,
39794040 SelectionDAG &DAG) const {
39804041 const GlobalAddressSDNode *GA = cast(Op);
39854046 return LowerDarwinGlobalTLSAddress(Op, DAG);
39864047 if (Subtarget->isTargetELF())
39874048 return LowerELFGlobalTLSAddress(Op, DAG);
4049 if (Subtarget->isTargetWindows())
4050 return LowerWindowsGlobalTLSAddress(Op, DAG);
39884051
39894052 llvm_unreachable("Unexpected platform trying to use TLS");
39904053 }
559559 SDValue LowerELFGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const;
560560 SDValue LowerELFTLSDescCallSeq(SDValue SymAddr, const SDLoc &DL,
561561 SelectionDAG &DAG) const;
562 SDValue LowerWindowsGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const;
562563 SDValue LowerSETCC(SDValue Op, SelectionDAG &DAG) const;
563564 SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG) const;
564565 SDValue LowerSELECT(SDValue Op, SelectionDAG &DAG) const;
13301330 // page address of a constant pool entry, block address
13311331 def : Pat<(AArch64adrp tconstpool:$cp), (ADRP tconstpool:$cp)>;
13321332 def : Pat<(AArch64adrp tblockaddress:$cp), (ADRP tblockaddress:$cp)>;
1333 def : Pat<(AArch64adrp texternalsym:$sym), (ADRP texternalsym:$sym)>;
13331334
13341335 //===----------------------------------------------------------------------===//
13351336 // Unconditional branch (register) instructions.
172172
173173 MCOperand AArch64MCInstLower::lowerSymbolOperandCOFF(const MachineOperand &MO,
174174 MCSymbol *Sym) const {
175 MCSymbolRefExpr::VariantKind RefKind = MCSymbolRefExpr::VK_None;
176 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, RefKind, Ctx);
175 AArch64MCExpr::VariantKind RefKind = AArch64MCExpr::VK_NONE;
176 if (MO.getTargetFlags() & AArch64II::MO_TLS) {
177 if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGEOFF)
178 RefKind = AArch64MCExpr::VK_SECREL_LO12;
179 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
180 AArch64II::MO_HI12)
181 RefKind = AArch64MCExpr::VK_SECREL_HI12;
182 }
183 const MCExpr *Expr =
184 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, Ctx);
177185 if (!MO.isJTI() && MO.getOffset())
178186 Expr = MCBinaryExpr::createAdd(
179187 Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
188 Expr = AArch64MCExpr::create(Expr, RefKind, Ctx);
180189 return MCOperand::createExpr(Expr);
181190 }
182191
0 ; RUN: llc -mtriple aarch64-windows %s -o - | FileCheck %s
1
2 @tlsVar = thread_local global i32 0
3 @tlsVar8 = thread_local global i8 0
4 @tlsVar64 = thread_local global i64 0
5
6 define i32 @getVar() {
7 %1 = load i32, i32* @tlsVar
8 ret i32 %1
9 }
10
11 define i32* @getPtr() {
12 ret i32* @tlsVar
13 }
14
15 define void @setVar(i32 %val) {
16 store i32 %val, i32* @tlsVar
17 ret void
18 }
19
20 define i8 @getVar8() {
21 %1 = load i8, i8* @tlsVar8
22 ret i8 %1
23 }
24
25 define i64 @getVar64() {
26 %1 = load i64, i64* @tlsVar64
27 ret i64 %1
28 }
29
30 ; CHECK-LABEL: getVar
31 ; CHECK: adrp [[TLS_INDEX_ADDR:x[0-9]+]], _tls_index
32 ; CHECK: ldr w[[TLS_INDEX:[0-9]+]], {{\[}}[[TLS_INDEX_ADDR]], _tls_index]
33 ; CHECK: ldr [[TLS_POINTER:x[0-9]+]], [x18, #88]
34
35 ; CHECK: ldr [[TLS:x[0-9]+]], {{\[}}[[TLS_POINTER]], x[[TLS_INDEX]], lsl #3]
36 ; CHECK: add [[TLS]], [[TLS]], :secrel_hi12:tlsVar
37 ; This add+ldr could also be folded into a single ldr with a :secrel_lo12:
38 ; offset.
39 ; CHECK: add [[TLS]], [[TLS]], :secrel_lo12:tlsVar
40 ; CHECK: ldr w0, {{\[}}[[TLS]]{{\]}}
41
42 ; CHECK-LABEL: getPtr
43 ; CHECK: adrp [[TLS_INDEX_ADDR:x[0-9]+]], _tls_index
44 ; CHECK: ldr w[[TLS_INDEX:[0-9]+]], {{\[}}[[TLS_INDEX_ADDR]], _tls_index]
45 ; CHECK: ldr [[TLS_POINTER:x[0-9]+]], [x18, #88]
46
47 ; CHECK: ldr [[TLS:x[0-9]+]], {{\[}}[[TLS_POINTER]], x[[TLS_INDEX]], lsl #3]
48 ; CHECK: add [[TLS]], [[TLS]], :secrel_hi12:tlsVar
49 ; CHECK: add x0, [[TLS]], :secrel_lo12:tlsVar
50
51 ; CHECK-LABEL: setVar
52 ; CHECK: adrp [[TLS_INDEX_ADDR:x[0-9]+]], _tls_index
53 ; CHECK: ldr w[[TLS_INDEX:[0-9]+]], {{\[}}[[TLS_INDEX_ADDR]], _tls_index]
54 ; CHECK: ldr [[TLS_POINTER:x[0-9]+]], [x18, #88]
55
56 ; CHECK: ldr [[TLS:x[0-9]+]], {{\[}}[[TLS_POINTER]], x[[TLS_INDEX]], lsl #3]
57 ; CHECK: add [[TLS]], [[TLS]], :secrel_hi12:tlsVar
58 ; This add+ldr could also be folded into a single ldr with a :secrel_lo12:
59 ; offset.
60 ; CHECK: add [[TLS]], [[TLS]], :secrel_lo12:tlsVar
61 ; CHECK: str w0, {{\[}}[[TLS]]{{\]}}
62
63 ; CHECK-LABEL: getVar8
64 ; CHECK: add [[TLS:x[0-9]+]], [[TLS]], :secrel_hi12:tlsVar8
65 ; CHECK: add [[TLS]], [[TLS]], :secrel_lo12:tlsVar8
66 ; CHECK: ldrb w0, {{\[}}[[TLS]]{{\]}}
67
68 ; CHECK-LABEL: getVar64
69 ; CHECK: add [[TLS:x[0-9]+]], [[TLS]], :secrel_hi12:tlsVar64
70 ; CHECK: add [[TLS]], [[TLS]], :secrel_lo12:tlsVar64
71 ; CHECK: ldr x0, {{\[}}[[TLS]]{{\]}}