@@ -4591,6 +4591,97 @@ AArch64TargetLowering::LowerDarwinGlobalTLSAddress(SDValue Op,
45914591 return DAG.getCopyFromReg(Chain, DL, AArch64::X0, PtrVT, Chain.getValue(1));
45924592}
45934593
4594+ /// Convert a thread-local variable reference into a sequence of instructions to
4595+ /// compute the variable's address for the local exec TLS model of ELF targets.
4596+ /// The sequence depends on the maximum TLS area size.
4597+ SDValue AArch64TargetLowering::LowerELFTLSLocalExec(const GlobalValue *GV,
4598+ SDValue ThreadBase,
4599+ const SDLoc &DL,
4600+ SelectionDAG &DAG) const {
4601+ EVT PtrVT = getPointerTy(DAG.getDataLayout());
4602+ SDValue TPOff, Addr;
4603+
4604+ switch (DAG.getTarget().Options.TLSSize) {
4605+ default:
4606+ llvm_unreachable("Unexpected TLS size");
4607+
4608+ case 12: {
4609+ // mrs x0, TPIDR_EL0
4610+ // add x0, x0, :tprel_lo12:a
4611+ SDValue Var = DAG.getTargetGlobalAddress(
4612+ GV, DL, PtrVT, 0, AArch64II::MO_TLS | AArch64II::MO_PAGEOFF);
4613+ return SDValue(DAG.getMachineNode(AArch64::ADDXri, DL, PtrVT, ThreadBase,
4614+ Var,
4615+ DAG.getTargetConstant(0, DL, MVT::i32)),
4616+ 0);
4617+ }
4618+
4619+ case 24: {
4620+ // mrs x0, TPIDR_EL0
4621+ // add x0, x0, :tprel_hi12:a
4622+ // add x0, x0, :tprel_lo12_nc:a
4623+ SDValue HiVar = DAG.getTargetGlobalAddress(
4624+ GV, DL, PtrVT, 0, AArch64II::MO_TLS | AArch64II::MO_HI12);
4625+ SDValue LoVar = DAG.getTargetGlobalAddress(
4626+ GV, DL, PtrVT, 0,
4627+ AArch64II::MO_TLS | AArch64II::MO_PAGEOFF | AArch64II::MO_NC);
4628+ Addr = SDValue(DAG.getMachineNode(AArch64::ADDXri, DL, PtrVT, ThreadBase,
4629+ HiVar,
4630+ DAG.getTargetConstant(0, DL, MVT::i32)),
4631+ 0);
4632+ return SDValue(DAG.getMachineNode(AArch64::ADDXri, DL, PtrVT, Addr,
4633+ LoVar,
4634+ DAG.getTargetConstant(0, DL, MVT::i32)),
4635+ 0);
4636+ }
4637+
4638+ case 32: {
4639+ // mrs x1, TPIDR_EL0
4640+ // movz x0, #:tprel_g1:a
4641+ // movk x0, #:tprel_g0_nc:a
4642+ // add x0, x1, x0
4643+ SDValue HiVar = DAG.getTargetGlobalAddress(
4644+ GV, DL, PtrVT, 0, AArch64II::MO_TLS | AArch64II::MO_G1);
4645+ SDValue LoVar = DAG.getTargetGlobalAddress(
4646+ GV, DL, PtrVT, 0,
4647+ AArch64II::MO_TLS | AArch64II::MO_G0 | AArch64II::MO_NC);
4648+ TPOff = SDValue(DAG.getMachineNode(AArch64::MOVZXi, DL, PtrVT, HiVar,
4649+ DAG.getTargetConstant(16, DL, MVT::i32)),
4650+ 0);
4651+ TPOff = SDValue(DAG.getMachineNode(AArch64::MOVKXi, DL, PtrVT, TPOff, LoVar,
4652+ DAG.getTargetConstant(0, DL, MVT::i32)),
4653+ 0);
4654+ return DAG.getNode(ISD::ADD, DL, PtrVT, ThreadBase, TPOff);
4655+ }
4656+
4657+ case 48: {
4658+ // mrs x1, TPIDR_EL0
4659+ // movz x0, #:tprel_g2:a
4660+ // movk x0, #:tprel_g1_nc:a
4661+ // movk x0, #:tprel_g0_nc:a
4662+ // add x0, x1, x0
4663+ SDValue HiVar = DAG.getTargetGlobalAddress(
4664+ GV, DL, PtrVT, 0, AArch64II::MO_TLS | AArch64II::MO_G2);
4665+ SDValue MiVar = DAG.getTargetGlobalAddress(
4666+ GV, DL, PtrVT, 0,
4667+ AArch64II::MO_TLS | AArch64II::MO_G1 | AArch64II::MO_NC);
4668+ SDValue LoVar = DAG.getTargetGlobalAddress(
4669+ GV, DL, PtrVT, 0,
4670+ AArch64II::MO_TLS | AArch64II::MO_G0 | AArch64II::MO_NC);
4671+ TPOff = SDValue(DAG.getMachineNode(AArch64::MOVZXi, DL, PtrVT, HiVar,
4672+ DAG.getTargetConstant(32, DL, MVT::i32)),
4673+ 0);
4674+ TPOff = SDValue(DAG.getMachineNode(AArch64::MOVKXi, DL, PtrVT, TPOff, MiVar,
4675+ DAG.getTargetConstant(16, DL, MVT::i32)),
4676+ 0);
4677+ TPOff = SDValue(DAG.getMachineNode(AArch64::MOVKXi, DL, PtrVT, TPOff, LoVar,
4678+ DAG.getTargetConstant(0, DL, MVT::i32)),
4679+ 0);
4680+ return DAG.getNode(ISD::ADD, DL, PtrVT, ThreadBase, TPOff);
4681+ }
4682+ }
4683+ }
4684+
45944685/// When accessing thread-local variables under either the general-dynamic or
45954686/// local-dynamic system, we make a "TLS-descriptor" call. The variable will
45964687/// have a descriptor, accessible via a PC-relative ADRP, and whose first entry
@@ -4628,15 +4719,7 @@ SDValue
46284719AArch64TargetLowering::LowerELFGlobalTLSAddress(SDValue Op,
46294720 SelectionDAG &DAG) const {
46304721 assert(Subtarget->isTargetELF() && "This function expects an ELF target");
4631- if (getTargetMachine().getCodeModel() == CodeModel::Large)
4632- report_fatal_error("ELF TLS only supported in small memory model");
4633- // Different choices can be made for the maximum size of the TLS area for a
4634- // module. For the small address model, the default TLS size is 16MiB and the
4635- // maximum TLS size is 4GiB.
4636- // FIXME: add -mtls-size command line option and make it control the 16MiB
4637- // vs. 4GiB code sequence generation.
4638- // FIXME: add tiny codemodel support. We currently generate the same code as
4639- // small, which may be larger than needed.
4722+
46404723 const GlobalAddressSDNode *GA = cast<GlobalAddressSDNode>(Op);
46414724
46424725 TLSModel::Model Model = getTargetMachine().getTLSModel(GA->getGlobal());
@@ -4646,6 +4729,17 @@ AArch64TargetLowering::LowerELFGlobalTLSAddress(SDValue Op,
46464729 Model = TLSModel::GeneralDynamic;
46474730 }
46484731
4732+ if (getTargetMachine().getCodeModel() == CodeModel::Large &&
4733+ Model != TLSModel::LocalExec)
4734+ report_fatal_error("ELF TLS only supported in small memory model or "
4735+ "in local exec TLS model");
4736+ // Different choices can be made for the maximum size of the TLS area for a
4737+ // module. For the small address model, the default TLS size is 16MiB and the
4738+ // maximum TLS size is 4GiB.
4739+ // FIXME: add tiny and large code model support for TLS access models other
4740+ // than local exec. We currently generate the same code as small for tiny,
4741+ // which may be larger than needed.
4742+
46494743 SDValue TPOff;
46504744 EVT PtrVT = getPointerTy(DAG.getDataLayout());
46514745 SDLoc DL(Op);
@@ -4654,23 +4748,7 @@ AArch64TargetLowering::LowerELFGlobalTLSAddress(SDValue Op,
46544748 SDValue ThreadBase = DAG.getNode(AArch64ISD::THREAD_POINTER, DL, PtrVT);
46554749
46564750 if (Model == TLSModel::LocalExec) {
4657- SDValue HiVar = DAG.getTargetGlobalAddress(
4658- GV, DL, PtrVT, 0, AArch64II::MO_TLS | AArch64II::MO_HI12);
4659- SDValue LoVar = DAG.getTargetGlobalAddress(
4660- GV, DL, PtrVT, 0,
4661- AArch64II::MO_TLS | AArch64II::MO_PAGEOFF | AArch64II::MO_NC);
4662-
4663- SDValue TPWithOff_lo =
4664- SDValue(DAG.getMachineNode(AArch64::ADDXri, DL, PtrVT, ThreadBase,
4665- HiVar,
4666- DAG.getTargetConstant(0, DL, MVT::i32)),
4667- 0);
4668- SDValue TPWithOff =
4669- SDValue(DAG.getMachineNode(AArch64::ADDXri, DL, PtrVT, TPWithOff_lo,
4670- LoVar,
4671- DAG.getTargetConstant(0, DL, MVT::i32)),
4672- 0);
4673- return TPWithOff;
4751+ return LowerELFTLSLocalExec(GV, ThreadBase, DL, DAG);
46744752 } else if (Model == TLSModel::InitialExec) {
46754753 TPOff = DAG.getTargetGlobalAddress(GV, DL, PtrVT, 0, AArch64II::MO_TLS);
46764754 TPOff = DAG.getNode(AArch64ISD::LOADgot, DL, PtrVT, TPOff);
0 commit comments