Skip to content

Commit 5b05870

Browse files
Felix (Ting Wang)tingwangtingwang
authored
[PowerPC] Support local-dynamic TLS relocation on AIX (#66316)
Supports TLS local-dynamic on AIX, generates below sequence of code: ``` .tc foo[TC],foo[TL]@ld # Variable offset, ld relocation specifier .tc mh[TC],mh[TC]@ml # Module handle for the caller lwz 3,mh[TC]\(2\) $$ For 64-bit: ld 3,mh[TC]\(2\) bla .__tls_get_mod # Modifies r0,r3,r4,r5,r11,lr,cr0 #r3 = &TLS for module lwz 4,foo[TC]\(2\) $$ For 64-bit: ld 4,foo[TC]\(2\) add 5,3,4 # Compute &foo .rename mh[TC], "\_$TLSML" # Symbol for the module handle must have the name "_$TLSML" ``` --------- Co-authored-by: tingwang <[email protected]> Co-authored-by: tingwang <[email protected]>
1 parent 7d7d475 commit 5b05870

26 files changed

+1545
-521
lines changed

clang/include/clang/Basic/DiagnosticDriverKinds.td

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -693,7 +693,6 @@ def err_drv_cannot_mix_options : Error<"cannot specify '%1' along with '%0'">;
693693
def err_drv_invalid_object_mode : Error<
694694
"OBJECT_MODE setting %0 is not recognized and is not a valid setting">;
695695

696-
def err_aix_unsupported_tls_model : Error<"TLS model '%0' is not yet supported on AIX">;
697696
def err_roptr_requires_data_sections: Error<"-mxcoff-roptr is supported only with -fdata-sections">;
698697
def err_roptr_cannot_build_shared: Error<"-mxcoff-roptr is not supported with -shared">;
699698

clang/lib/Frontend/CompilerInvocation.cpp

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1975,14 +1975,6 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args,
19751975
Opts.LinkBitcodeFiles.push_back(F);
19761976
}
19771977

1978-
if (Arg *A = Args.getLastArg(OPT_ftlsmodel_EQ)) {
1979-
if (T.isOSAIX()) {
1980-
StringRef Name = A->getValue();
1981-
if (Name == "local-dynamic")
1982-
Diags.Report(diag::err_aix_unsupported_tls_model) << Name;
1983-
}
1984-
}
1985-
19861978
if (Arg *A = Args.getLastArg(OPT_fdenormal_fp_math_EQ)) {
19871979
StringRef Val = A->getValue();
19881980
Opts.FPDenormalMode = llvm::parseDenormalFPAttribute(Val);

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2053,12 +2053,6 @@ static void handleTLSModelAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
20532053
return;
20542054
}
20552055

2056-
if (S.Context.getTargetInfo().getTriple().isOSAIX() &&
2057-
Model == "local-dynamic") {
2058-
S.Diag(LiteralLoc, diag::err_aix_attr_unsupported_tls_model) << Model;
2059-
return;
2060-
}
2061-
20622056
D->addAttr(::new (S.Context) TLSModelAttr(S.Context, AL, Model));
20632057
}
20642058

clang/test/CodeGen/PowerPC/aix-tls-model.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
// RUN: %clang_cc1 %s -triple powerpc-unknown-aix -target-cpu pwr8 -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-GD
22
// RUN: %clang_cc1 %s -triple powerpc-unknown-aix -target-cpu pwr8 -ftls-model=global-dynamic -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-GD
3-
// RUN: not %clang_cc1 %s -triple powerpc-unknown-aix -target-cpu pwr8 -ftls-model=local-dynamic -emit-llvm 2>&1 | FileCheck %s -check-prefix=CHECK-LD-ERROR
3+
// RUN: %clang_cc1 %s -triple powerpc-unknown-aix -target-cpu pwr8 -ftls-model=local-dynamic -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-LD
44
// RUN: %clang_cc1 %s -triple powerpc-unknown-aix -target-cpu pwr8 -ftls-model=initial-exec -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-IE
55
// RUN: %clang_cc1 %s -triple powerpc-unknown-aix -target-cpu pwr8 -ftls-model=local-exec -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-LE
66
// RUN: %clang_cc1 %s -triple powerpc64-unknown-aix -target-cpu pwr8 -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-GD
77
// RUN: %clang_cc1 %s -triple powerpc64-unknown-aix -target-cpu pwr8 -ftls-model=global-dynamic -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-GD
8-
// RUN: not %clang_cc1 %s -triple powerpc64-unknown-aix -target-cpu pwr8 -ftls-model=local-dynamic -emit-llvm 2>&1 | FileCheck %s -check-prefix=CHECK-LD-ERROR
8+
// RUN: %clang_cc1 %s -triple powerpc64-unknown-aix -target-cpu pwr8 -ftls-model=local-dynamic -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-LD
99
// RUN: %clang_cc1 %s -triple powerpc64-unknown-aix -target-cpu pwr8 -ftls-model=initial-exec -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-IE
1010
// RUN: %clang_cc1 %s -triple powerpc64-unknown-aix -target-cpu pwr8 -ftls-model=local-exec -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-LE
1111

@@ -21,7 +21,10 @@ int f() {
2121
// CHECK-GD: @z2 ={{.*}} global i32 0
2222
// CHECK-GD: @x ={{.*}} thread_local global i32 0
2323
// CHECK-GD: @_ZZ1fvE1y = internal thread_local global i32 0
24-
// CHECK-LD-ERROR: error: TLS model 'local-dynamic' is not yet supported on AIX
24+
// CHECK-LD: @z1 ={{.*}} global i32 0
25+
// CHECK-LD: @z2 ={{.*}} global i32 0
26+
// CHECK-LD: @x ={{.*}} thread_local(localdynamic) global i32 0
27+
// CHECK-LD: @_ZZ1fvE1y = internal thread_local(localdynamic) global i32 0
2528
// CHECK-IE: @z1 ={{.*}} global i32 0
2629
// CHECK-IE: @z2 ={{.*}} global i32 0
2730
// CHECK-IE: @x ={{.*}} thread_local(initialexec) global i32 0

clang/test/Sema/aix-attr-tls_model.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,6 @@
66
#endif
77

88
static __thread int y __attribute((tls_model("global-dynamic"))); // no-warning
9-
static __thread int y __attribute((tls_model("local-dynamic"))); // expected-error {{TLS model 'local-dynamic' is not yet supported on AIX}}
9+
static __thread int y __attribute((tls_model("local-dynamic"))); // expected-no-diagnostics
1010
static __thread int y __attribute((tls_model("initial-exec"))); // no-warning
1111
static __thread int y __attribute((tls_model("local-exec"))); // no-warning

llvm/include/llvm/MC/MCExpr.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,8 @@ class MCSymbolRefExpr : public MCExpr {
307307
VK_PPC_AIX_TLSGDM, // symbol@m
308308
VK_PPC_AIX_TLSIE, // symbol@ie
309309
VK_PPC_AIX_TLSLE, // symbol@le
310+
VK_PPC_AIX_TLSLD, // symbol@ld
311+
VK_PPC_AIX_TLSML, // symbol@ml
310312
VK_PPC_GOT_TLSLD, // symbol@got@tlsld
311313
VK_PPC_GOT_TLSLD_LO, // symbol@got@tlsld@l
312314
VK_PPC_GOT_TLSLD_HI, // symbol@got@tlsld@h

llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2418,6 +2418,15 @@ MCSection *TargetLoweringObjectFileXCOFF::getSectionForExternalReference(
24182418
SmallString<128> Name;
24192419
getNameWithPrefix(Name, GO, TM);
24202420

2421+
// AIX TLS local-dynamic does not need the external reference for the
2422+
// "_$TLSML" symbol.
2423+
if (GO->getThreadLocalMode() == GlobalVariable::LocalDynamicTLSModel &&
2424+
GO->hasName() && GO->getName() == "_$TLSML") {
2425+
return getContext().getXCOFFSection(
2426+
Name, SectionKind::getData(),
2427+
XCOFF::CsectProperties(XCOFF::XMC_TC, XCOFF::XTY_SD));
2428+
}
2429+
24212430
XCOFF::StorageMappingClass SMC =
24222431
isa<Function>(GO) ? XCOFF::XMC_DS : XCOFF::XMC_UA;
24232432
if (GO->isThreadLocal())
@@ -2675,13 +2684,17 @@ MCSection *TargetLoweringObjectFileXCOFF::getSectionForTOCEntry(
26752684
// the chance of needing -bbigtoc is decreased. Also, the toc-entry for
26762685
// EH info is never referenced directly using instructions so it can be
26772686
// allocated with TE storage-mapping class.
2687+
// The "_$TLSML" symbol for TLS local-dynamic mode requires XMC_TC, otherwise
2688+
// the AIX assembler will complain.
26782689
return getContext().getXCOFFSection(
26792690
cast<MCSymbolXCOFF>(Sym)->getSymbolTableName(), SectionKind::getData(),
2680-
XCOFF::CsectProperties((TM.getCodeModel() == CodeModel::Large ||
2681-
cast<MCSymbolXCOFF>(Sym)->isEHInfo())
2682-
? XCOFF::XMC_TE
2683-
: XCOFF::XMC_TC,
2684-
XCOFF::XTY_SD));
2691+
XCOFF::CsectProperties(
2692+
((TM.getCodeModel() == CodeModel::Large &&
2693+
cast<MCSymbolXCOFF>(Sym)->getSymbolTableName() != "_$TLSML") ||
2694+
cast<MCSymbolXCOFF>(Sym)->isEHInfo())
2695+
? XCOFF::XMC_TE
2696+
: XCOFF::XMC_TC,
2697+
XCOFF::XTY_SD));
26852698
}
26862699

26872700
MCSection *TargetLoweringObjectFileXCOFF::getSectionForLSDA(

llvm/lib/MC/MCExpr.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,10 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) {
338338
return "ie";
339339
case VK_PPC_AIX_TLSLE:
340340
return "le";
341+
case VK_PPC_AIX_TLSLD:
342+
return "ld";
343+
case VK_PPC_AIX_TLSML:
344+
return "ml";
341345
case VK_PPC_GOT_TLSLD: return "got@tlsld";
342346
case VK_PPC_GOT_TLSLD_LO: return "got@tlsld@l";
343347
case VK_PPC_GOT_TLSLD_HI: return "got@tlsld@h";

llvm/lib/MC/XCOFFObjectWriter.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -715,7 +715,8 @@ void XCOFFObjectWriter::recordRelocation(MCAssembler &Asm,
715715
if (Type == XCOFF::RelocationType::R_POS ||
716716
Type == XCOFF::RelocationType::R_TLS ||
717717
Type == XCOFF::RelocationType::R_TLS_LE ||
718-
Type == XCOFF::RelocationType::R_TLS_IE)
718+
Type == XCOFF::RelocationType::R_TLS_IE ||
719+
Type == XCOFF::RelocationType::R_TLS_LD)
719720
// The FixedValue should be symbol's virtual address in this object file
720721
// plus any constant value that we might get.
721722
FixedValue = getVirtualAddress(SymA, SymASec) + Target.getConstant();

llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -231,12 +231,19 @@ class PPCTargetAsmStreamer : public PPCTargetStreamer {
231231
MCSymbolXCOFF *TCSym =
232232
cast<MCSectionXCOFF>(Streamer.getCurrentSectionOnly())
233233
->getQualNameSymbol();
234-
// On AIX, we have a region handle (symbol@m) and the variable offset
235-
// (symbol@{gd|ie|le}) for TLS variables, depending on the TLS model.
234+
// On AIX, we have TLS variable offsets (symbol@({gd|ie|le|ld}) depending
235+
// on the TLS access method (or model). For the general-dynamic access
236+
// method, we also have region handle (symbol@m) for each variable. For
237+
// local-dynamic, there is a module handle (_$TLSML[TC]@ml) for all
238+
// variables. Finally for local-exec and initial-exec, we have a thread
239+
// pointer, in r13 for 64-bit mode and returned by .__get_tpointer for
240+
// 32-bit mode.
236241
if (Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSGD ||
237242
Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSGDM ||
238243
Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSIE ||
239-
Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSLE)
244+
Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSLE ||
245+
Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSLD ||
246+
Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSML)
240247
OS << "\t.tc " << TCSym->getName() << "," << XSym->getName() << "@"
241248
<< MCSymbolRefExpr::getVariantKindName(Kind) << '\n';
242249
else

llvm/lib/Target/PowerPC/MCTargetDesc/PPCXCOFFObjectWriter.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,10 @@ std::pair<uint8_t, uint8_t> PPCXCOFFObjectWriter::getRelocTypeAndSignSize(
116116
return {XCOFF::RelocationType::R_TLS_IE, SignAndSizeForFKData};
117117
case MCSymbolRefExpr::VK_PPC_AIX_TLSLE:
118118
return {XCOFF::RelocationType::R_TLS_LE, SignAndSizeForFKData};
119+
case MCSymbolRefExpr::VK_PPC_AIX_TLSLD:
120+
return {XCOFF::RelocationType::R_TLS_LD, SignAndSizeForFKData};
121+
case MCSymbolRefExpr::VK_PPC_AIX_TLSML:
122+
return {XCOFF::RelocationType::R_TLSML, SignAndSizeForFKData};
119123
case MCSymbolRefExpr::VK_None:
120124
return {XCOFF::RelocationType::R_POS, SignAndSizeForFKData};
121125
}

llvm/lib/Target/PowerPC/PPC.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,12 @@ class ModulePass;
139139
/// and Local Exec models.
140140
MO_TPREL_FLAG,
141141

142+
/// MO_TLSLDM_FLAG - on AIX the ML relocation type is only valid for a
143+
/// reference to a TOC symbol from the symbol itself, and right now its only
144+
/// user is the symbol "_$TLSML". The symbol name is used to decide that
145+
/// the R_TLSML relocation is expected.
146+
MO_TLSLDM_FLAG,
147+
142148
/// MO_TLSLD_FLAG - If this bit is set the symbol reference is relative to
143149
/// TLS Local Dynamic model.
144150
MO_TLSLD_FLAG,

llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp

Lines changed: 45 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -621,12 +621,23 @@ void PPCAsmPrinter::LowerPATCHPOINT(StackMaps &SM, const MachineInstr &MI) {
621621
EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::NOP));
622622
}
623623

624-
/// This helper function creates the TlsGetAddr MCSymbol for AIX. We will
625-
/// create the csect and use the qual-name symbol instead of creating just the
626-
/// external symbol.
624+
/// This helper function creates the TlsGetAddr/TlsGetMod MCSymbol for AIX. We
625+
/// will create the csect and use the qual-name symbol instead of creating just
626+
/// the external symbol.
627627
static MCSymbol *createMCSymbolForTlsGetAddr(MCContext &Ctx, unsigned MIOpc) {
628-
StringRef SymName =
629-
MIOpc == PPC::GETtlsTpointer32AIX ? ".__get_tpointer" : ".__tls_get_addr";
628+
StringRef SymName;
629+
switch (MIOpc) {
630+
default:
631+
SymName = ".__tls_get_addr";
632+
break;
633+
case PPC::GETtlsTpointer32AIX:
634+
SymName = ".__get_tpointer";
635+
break;
636+
case PPC::GETtlsMOD32AIX:
637+
case PPC::GETtlsMOD64AIX:
638+
SymName = ".__tls_get_mod";
639+
break;
640+
}
630641
return Ctx
631642
.getXCOFFSection(SymName, SectionKind::getText(),
632643
XCOFF::CsectProperties(XCOFF::XMC_PR, XCOFF::XTY_ER))
@@ -668,14 +679,16 @@ void PPCAsmPrinter::EmitTlsCall(const MachineInstr *MI,
668679
"GETtls[ld]ADDR[32] must read GPR3");
669680

670681
if (Subtarget->isAIXABI()) {
671-
// On AIX, the variable offset should already be in R4 and the region handle
672-
// should already be in R3.
673-
// For TLSGD, which currently is the only supported access model, we only
674-
// need to generate an absolute branch to .__tls_get_addr.
682+
// For TLSGD, the variable offset should already be in R4 and the region
683+
// handle should already be in R3. We generate an absolute branch to
684+
// .__tls_get_addr. For TLSLD, the module handle should already be in R3.
685+
// We generate an absolute branch to .__tls_get_mod.
675686
Register VarOffsetReg = Subtarget->isPPC64() ? PPC::X4 : PPC::R4;
676687
(void)VarOffsetReg;
677-
assert(MI->getOperand(2).isReg() &&
678-
MI->getOperand(2).getReg() == VarOffsetReg &&
688+
assert((MI->getOpcode() == PPC::GETtlsMOD32AIX ||
689+
MI->getOpcode() == PPC::GETtlsMOD64AIX ||
690+
(MI->getOperand(2).isReg() &&
691+
MI->getOperand(2).getReg() == VarOffsetReg)) &&
679692
"GETtls[ld]ADDR[32] must read GPR4");
680693
EmitAIXTlsCallHelper(MI);
681694
return;
@@ -844,6 +857,13 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) {
844857
return MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSGDM;
845858
if (Flag == PPCII::MO_TLSGD_FLAG || Flag == PPCII::MO_GOT_TLSGD_PCREL_FLAG)
846859
return MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSGD;
860+
// For local-dynamic TLS access on AIX, we have one TOC entry for the symbol
861+
// (the variable offset) and one shared TOC entry for the module handle.
862+
// They are differentiated by MO_TLSLD_FLAG and MO_TLSLDM_FLAG.
863+
if (Flag == PPCII::MO_TLSLD_FLAG && IsAIX)
864+
return MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSLD;
865+
if (Flag == PPCII::MO_TLSLDM_FLAG && IsAIX)
866+
return MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSML;
847867
return MCSymbolRefExpr::VariantKind::VK_None;
848868
};
849869

@@ -1354,6 +1374,11 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) {
13541374
.addExpr(SymGotTlsGD));
13551375
return;
13561376
}
1377+
case PPC::GETtlsMOD32AIX:
1378+
case PPC::GETtlsMOD64AIX:
1379+
// Transform: %r3 = GETtlsMODNNAIX %r3 (for NN == 32/64).
1380+
// Into: BLA .__tls_get_mod()
1381+
// Input parameter is a module handle (_$TLSML[TC]@ml) for all variables.
13571382
case PPC::GETtlsADDR:
13581383
// Transform: %x3 = GETtlsADDR %x3, @sym
13591384
// Into: BL8_NOP_TLS __tls_get_addr(sym at tlsgd)
@@ -2167,6 +2192,11 @@ void PPCAIXAsmPrinter::emitLinkage(const GlobalValue *GV,
21672192
}
21682193
}
21692194

2195+
// Do not emit the _$TLSML symbol.
2196+
if (GV->getThreadLocalMode() == GlobalVariable::LocalDynamicTLSModel &&
2197+
GV->hasName() && GV->getName() == "_$TLSML")
2198+
return;
2199+
21702200
OutStreamer->emitXCOFFSymbolLinkageWithVisibility(GVSym, LinkageAttr,
21712201
VisibilityAttr);
21722202
}
@@ -2981,11 +3011,13 @@ void PPCAIXAsmPrinter::emitInstruction(const MachineInstr *MI) {
29813011
MMI->hasDebugInfo());
29823012
break;
29833013
}
3014+
case PPC::GETtlsMOD32AIX:
3015+
case PPC::GETtlsMOD64AIX:
29843016
case PPC::GETtlsTpointer32AIX:
29853017
case PPC::GETtlsADDR64AIX:
29863018
case PPC::GETtlsADDR32AIX: {
2987-
// A reference to .__tls_get_addr/.__get_tpointer is unknown to the
2988-
// assembler so we need to emit an external symbol reference.
3019+
// A reference to .__tls_get_mod/.__tls_get_addr/.__get_tpointer is unknown
3020+
// to the assembler so we need to emit an external symbol reference.
29893021
MCSymbol *TlsGetAddr =
29903022
createMCSymbolForTlsGetAddr(OutContext, MI->getOpcode());
29913023
ExtSymSDNodeSymbols.insert(TlsGetAddr);

llvm/lib/Target/PowerPC/PPCISelLowering.cpp

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1774,9 +1774,11 @@ const char *PPCTargetLowering::getTargetNodeName(unsigned Opcode) const {
17741774
case PPCISD::ADDIS_TLSGD_HA: return "PPCISD::ADDIS_TLSGD_HA";
17751775
case PPCISD::ADDI_TLSGD_L: return "PPCISD::ADDI_TLSGD_L";
17761776
case PPCISD::GET_TLS_ADDR: return "PPCISD::GET_TLS_ADDR";
1777+
case PPCISD::GET_TLS_MOD_AIX: return "PPCISD::GET_TLS_MOD_AIX";
17771778
case PPCISD::GET_TPOINTER: return "PPCISD::GET_TPOINTER";
17781779
case PPCISD::ADDI_TLSGD_L_ADDR: return "PPCISD::ADDI_TLSGD_L_ADDR";
17791780
case PPCISD::TLSGD_AIX: return "PPCISD::TLSGD_AIX";
1781+
case PPCISD::TLSLD_AIX: return "PPCISD::TLSLD_AIX";
17801782
case PPCISD::ADDIS_TLSLD_HA: return "PPCISD::ADDIS_TLSLD_HA";
17811783
case PPCISD::ADDI_TLSLD_L: return "PPCISD::ADDI_TLSLD_L";
17821784
case PPCISD::GET_TLSLD_ADDR: return "PPCISD::GET_TLSLD_ADDR";
@@ -3415,13 +3417,36 @@ SDValue PPCTargetLowering::LowerGlobalTLSAddressAIX(SDValue Op,
34153417
return DAG.getNode(PPCISD::ADD_TLS, dl, PtrVT, TLSReg, VariableOffset);
34163418
}
34173419

3418-
// Only Local-Exec, Initial-Exec and General-Dynamic TLS models are currently
3419-
// supported models. If Local- or Initial-exec are not possible or specified,
3420-
// all GlobalTLSAddress nodes are lowered using the general-dynamic model.
3421-
// We need to generate two TOC entries, one for the variable offset, one for
3422-
// the region handle. The global address for the TOC entry of the region
3423-
// handle is created with the MO_TLSGDM_FLAG flag and the global address
3424-
// for the TOC entry of the variable offset is created with MO_TLSGD_FLAG.
3420+
if (Model == TLSModel::LocalDynamic) {
3421+
// For local-dynamic on AIX, we need to generate one TOC entry for each
3422+
// variable offset, and a single module-handle TOC entry for the entire
3423+
// file.
3424+
3425+
SDValue VariableOffsetTGA =
3426+
DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0, PPCII::MO_TLSLD_FLAG);
3427+
SDValue VariableOffset = getTOCEntry(DAG, dl, VariableOffsetTGA);
3428+
3429+
Module *M = DAG.getMachineFunction().getFunction().getParent();
3430+
GlobalVariable *TLSGV =
3431+
dyn_cast_or_null<GlobalVariable>(M->getOrInsertGlobal(
3432+
StringRef("_$TLSML"), PointerType::getUnqual(*DAG.getContext())));
3433+
TLSGV->setThreadLocalMode(GlobalVariable::LocalDynamicTLSModel);
3434+
assert(TLSGV && "Not able to create GV for _$TLSML.");
3435+
SDValue ModuleHandleTGA =
3436+
DAG.getTargetGlobalAddress(TLSGV, dl, PtrVT, 0, PPCII::MO_TLSLDM_FLAG);
3437+
SDValue ModuleHandleTOC = getTOCEntry(DAG, dl, ModuleHandleTGA);
3438+
SDValue ModuleHandle =
3439+
DAG.getNode(PPCISD::TLSLD_AIX, dl, PtrVT, ModuleHandleTOC);
3440+
3441+
return DAG.getNode(ISD::ADD, dl, PtrVT, ModuleHandle, VariableOffset);
3442+
}
3443+
3444+
// If Local- or Initial-exec or Local-dynamic is not possible or specified,
3445+
// all GlobalTLSAddress nodes are lowered using the general-dynamic model. We
3446+
// need to generate two TOC entries, one for the variable offset, one for the
3447+
// region handle. The global address for the TOC entry of the region handle is
3448+
// created with the MO_TLSGDM_FLAG flag and the global address for the TOC
3449+
// entry of the variable offset is created with MO_TLSGD_FLAG.
34253450
SDValue VariableOffsetTGA =
34263451
DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0, PPCII::MO_TLSGD_FLAG);
34273452
SDValue RegionHandleTGA =

llvm/lib/Target/PowerPC/PPCISelLowering.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -370,11 +370,22 @@ namespace llvm {
370370
/// G8RC = TLSGD_AIX, TOC_ENTRY, TOC_ENTRY
371371
/// Op that combines two register copies of TOC entries
372372
/// (region handle into R3 and variable offset into R4) followed by a
373-
/// GET_TLS_ADDR node which will be expanded to a call to __get_tls_addr.
373+
/// GET_TLS_ADDR node which will be expanded to a call to .__tls_get_addr.
374374
/// This node is used in 64-bit mode as well (in which case the result is
375375
/// G8RC and inputs are X3/X4).
376376
TLSGD_AIX,
377377

378+
/// %x3 = GET_TLS_MOD_AIX _$TLSML - For the AIX local-dynamic TLS model,
379+
/// produces a call to .__tls_get_mod(_$TLSML\@ml).
380+
GET_TLS_MOD_AIX,
381+
382+
/// [GP|G8]RC = TLSLD_AIX, TOC_ENTRY(module handle)
383+
/// Op that requires a single input of the module handle TOC entry in R3,
384+
/// and generates a GET_TLS_MOD_AIX node which will be expanded into a call
385+
/// to .__tls_get_mod. This node is used in both 32-bit and 64-bit modes.
386+
/// The only difference is the register class.
387+
TLSLD_AIX,
388+
378389
/// G8RC = ADDIS_TLSLD_HA %x2, Symbol - For the local-dynamic TLS
379390
/// model, produces an ADDIS8 instruction that adds the GOT base
380391
/// register to sym\@got\@tlsld\@ha.

0 commit comments

Comments
 (0)