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

0 commit comments

Comments
 (0)