Skip to content

[Clang] Enable AIX local-dynamic TLS mode #66972

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 5 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion clang/include/clang/Basic/DiagnosticDriverKinds.td
Original file line number Diff line number Diff line change
@@ -653,7 +653,6 @@ def err_drv_cannot_mix_options : Error<"cannot specify '%1' along with '%0'">;
def err_drv_invalid_object_mode : Error<
"OBJECT_MODE setting %0 is not recognized and is not a valid setting">;

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

8 changes: 0 additions & 8 deletions clang/lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
@@ -1967,14 +1967,6 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args,
Opts.LinkBitcodeFiles.push_back(F);
}

if (Arg *A = Args.getLastArg(OPT_ftlsmodel_EQ)) {
if (T.isOSAIX()) {
StringRef Name = A->getValue();
if (Name == "local-dynamic")
Diags.Report(diag::err_aix_unsupported_tls_model) << Name;
}
}

if (Arg *A = Args.getLastArg(OPT_fdenormal_fp_math_EQ)) {
StringRef Val = A->getValue();
Opts.FPDenormalMode = llvm::parseDenormalFPAttribute(Val);
6 changes: 0 additions & 6 deletions clang/lib/Sema/SemaDeclAttr.cpp
Original file line number Diff line number Diff line change
@@ -2053,12 +2053,6 @@ static void handleTLSModelAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
return;
}

if (S.Context.getTargetInfo().getTriple().isOSAIX() &&
Model == "local-dynamic") {
S.Diag(LiteralLoc, diag::err_aix_attr_unsupported_tls_model) << Model;
return;
}

D->addAttr(::new (S.Context) TLSModelAttr(S.Context, AL, Model));
}

9 changes: 6 additions & 3 deletions clang/test/CodeGen/PowerPC/aix-tls-model.cpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
// RUN: %clang_cc1 %s -triple powerpc-unknown-aix -target-cpu pwr8 -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-GD
// RUN: %clang_cc1 %s -triple powerpc-unknown-aix -target-cpu pwr8 -ftls-model=global-dynamic -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-GD
// 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
// RUN: %clang_cc1 %s -triple powerpc-unknown-aix -target-cpu pwr8 -ftls-model=local-dynamic -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-LD
// RUN: %clang_cc1 %s -triple powerpc-unknown-aix -target-cpu pwr8 -ftls-model=initial-exec -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-IE
// RUN: %clang_cc1 %s -triple powerpc-unknown-aix -target-cpu pwr8 -ftls-model=local-exec -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-LE
// RUN: %clang_cc1 %s -triple powerpc64-unknown-aix -target-cpu pwr8 -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-GD
// RUN: %clang_cc1 %s -triple powerpc64-unknown-aix -target-cpu pwr8 -ftls-model=global-dynamic -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-GD
// 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
// RUN: %clang_cc1 %s -triple powerpc64-unknown-aix -target-cpu pwr8 -ftls-model=local-dynamic -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-LD
// RUN: %clang_cc1 %s -triple powerpc64-unknown-aix -target-cpu pwr8 -ftls-model=initial-exec -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-IE
// RUN: %clang_cc1 %s -triple powerpc64-unknown-aix -target-cpu pwr8 -ftls-model=local-exec -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-LE

@@ -21,7 +21,10 @@ int f() {
// CHECK-GD: @z2 ={{.*}} global i32 0
// CHECK-GD: @x ={{.*}} thread_local global i32 0
// CHECK-GD: @_ZZ1fvE1y = internal thread_local global i32 0
// CHECK-LD-ERROR: error: TLS model 'local-dynamic' is not yet supported on AIX
// CHECK-LD: @z1 ={{.*}} global i32 0
// CHECK-LD: @z2 ={{.*}} global i32 0
// CHECK-LD: @x ={{.*}} thread_local(localdynamic) global i32 0
// CHECK-LD: @_ZZ1fvE1y = internal thread_local(localdynamic) global i32 0
// CHECK-IE: @z1 ={{.*}} global i32 0
// CHECK-IE: @z2 ={{.*}} global i32 0
// CHECK-IE: @x ={{.*}} thread_local(initialexec) global i32 0
2 changes: 1 addition & 1 deletion clang/test/Sema/aix-attr-tls_model.c
Original file line number Diff line number Diff line change
@@ -6,6 +6,6 @@
#endif

static __thread int y __attribute((tls_model("global-dynamic"))); // no-warning
static __thread int y __attribute((tls_model("local-dynamic"))); // expected-error {{TLS model 'local-dynamic' is not yet supported on AIX}}
static __thread int y __attribute((tls_model("local-dynamic"))); // expected-no-diagnostics
static __thread int y __attribute((tls_model("initial-exec"))); // no-warning
static __thread int y __attribute((tls_model("local-exec"))); // no-warning
2 changes: 2 additions & 0 deletions llvm/include/llvm/MC/MCExpr.h
Original file line number Diff line number Diff line change
@@ -301,6 +301,8 @@ class MCSymbolRefExpr : public MCExpr {
VK_PPC_AIX_TLSGDM, // symbol@m
VK_PPC_AIX_TLSIE, // symbol@ie
VK_PPC_AIX_TLSLE, // symbol@le
VK_PPC_AIX_TLSLD, // symbol@ld
VK_PPC_AIX_TLSML, // symbol@ml
VK_PPC_GOT_TLSLD, // symbol@got@tlsld
VK_PPC_GOT_TLSLD_LO, // symbol@got@tlsld@l
VK_PPC_GOT_TLSLD_HI, // symbol@got@tlsld@h
4 changes: 4 additions & 0 deletions llvm/lib/MC/MCExpr.cpp
Original file line number Diff line number Diff line change
@@ -331,6 +331,10 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) {
return "ie";
case VK_PPC_AIX_TLSLE:
return "le";
case VK_PPC_AIX_TLSLD:
return "ld";
case VK_PPC_AIX_TLSML:
return "ml";
case VK_PPC_GOT_TLSLD: return "got@tlsld";
case VK_PPC_GOT_TLSLD_LO: return "got@tlsld@l";
case VK_PPC_GOT_TLSLD_HI: return "got@tlsld@h";
9 changes: 6 additions & 3 deletions llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp
Original file line number Diff line number Diff line change
@@ -231,12 +231,15 @@ class PPCTargetAsmStreamer : public PPCTargetStreamer {
MCSymbolXCOFF *TCSym =
cast<MCSectionXCOFF>(Streamer.getCurrentSectionOnly())
->getQualNameSymbol();
// On AIX, we have a region handle (symbol@m) and the variable offset
// (symbol@{gd|ie|le}) for TLS variables, depending on the TLS model.
// On AIX, we have a region handle (symbol@m), module handle
// (__TLSML[TC]@ml) and the variable offset (symbol@{gd|ie|le|ld}) for TLS
// variables, depending on the TLS model.
if (Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSGD ||
Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSGDM ||
Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSIE ||
Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSLE)
Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSLE ||
Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSLD ||
Kind == MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSML)
OS << "\t.tc " << TCSym->getName() << "," << XSym->getName() << "@"
<< MCSymbolRefExpr::getVariantKindName(Kind) << '\n';
else
4 changes: 4 additions & 0 deletions llvm/lib/Target/PowerPC/MCTargetDesc/PPCXCOFFObjectWriter.cpp
Original file line number Diff line number Diff line change
@@ -116,6 +116,10 @@ std::pair<uint8_t, uint8_t> PPCXCOFFObjectWriter::getRelocTypeAndSignSize(
return {XCOFF::RelocationType::R_TLS_IE, SignAndSizeForFKData};
case MCSymbolRefExpr::VK_PPC_AIX_TLSLE:
return {XCOFF::RelocationType::R_TLS_LE, SignAndSizeForFKData};
case MCSymbolRefExpr::VK_PPC_AIX_TLSLD:
return {XCOFF::RelocationType::R_TLS_LD, SignAndSizeForFKData};
case MCSymbolRefExpr::VK_PPC_AIX_TLSML:
return {XCOFF::RelocationType::R_TLSML, SignAndSizeForFKData};
case MCSymbolRefExpr::VK_None:
return {XCOFF::RelocationType::R_POS, SignAndSizeForFKData};
}
91 changes: 72 additions & 19 deletions llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
Original file line number Diff line number Diff line change
@@ -613,12 +613,23 @@ void PPCAsmPrinter::LowerPATCHPOINT(StackMaps &SM, const MachineInstr &MI) {
EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::NOP));
}

/// This helper function creates the TlsGetAddr MCSymbol for AIX. We will
/// create the csect and use the qual-name symbol instead of creating just the
/// external symbol.
/// This helper function creates the TlsGetAddr/TlsGetMod MCSymbol for AIX. We
/// will create the csect and use the qual-name symbol instead of creating just
/// the external symbol.
static MCSymbol *createMCSymbolForTlsGetAddr(MCContext &Ctx, unsigned MIOpc) {
StringRef SymName =
MIOpc == PPC::GETtlsTpointer32AIX ? ".__get_tpointer" : ".__tls_get_addr";
StringRef SymName;
switch (MIOpc) {
default:
SymName = ".__tls_get_addr";
break;
case PPC::GETtlsTpointer32AIX:
SymName = ".__get_tpointer";
break;
case PPC::GETtlsMOD32AIX:
case PPC::GETtlsMOD64AIX:
SymName = ".__tls_get_mod";
break;
}
return Ctx
.getXCOFFSection(SymName, SectionKind::getText(),
XCOFF::CsectProperties(XCOFF::XMC_PR, XCOFF::XTY_ER))
@@ -660,14 +671,16 @@ void PPCAsmPrinter::EmitTlsCall(const MachineInstr *MI,
"GETtls[ld]ADDR[32] must read GPR3");

if (Subtarget->isAIXABI()) {
// On AIX, the variable offset should already be in R4 and the region handle
// should already be in R3.
// For TLSGD, which currently is the only supported access model, we only
// need to generate an absolute branch to .__tls_get_addr.
// For TLSGD, the variable offset should already be in R4 and the region
// handle should already be in R3, generate absolute branch to
// .__tls_get_addr. For TLSLD, the module handle should already be in R3,
// generate branch to .__tls_get_mod.
Register VarOffsetReg = Subtarget->isPPC64() ? PPC::X4 : PPC::R4;
(void)VarOffsetReg;
assert(MI->getOperand(2).isReg() &&
MI->getOperand(2).getReg() == VarOffsetReg &&
assert((MI->getOpcode() == PPC::GETtlsMOD32AIX ||
MI->getOpcode() == PPC::GETtlsMOD64AIX ||
(MI->getOperand(2).isReg() &&
MI->getOperand(2).getReg() == VarOffsetReg)) &&
"GETtls[ld]ADDR[32] must read GPR4");
EmitAIXTlsCallHelper(MI);
return;
@@ -710,6 +723,8 @@ static MCSymbol *getMCSymbolForTOCPseudoMO(const MachineOperand &MO,
return AP.GetJTISymbol(MO.getIndex());
case MachineOperand::MO_BlockAddress:
return AP.GetBlockAddressSymbol(MO.getBlockAddress());
case MachineOperand::MO_ExternalSymbol:
return AP.OutContext.getOrCreateSymbol(MO.getSymbolName());
default:
llvm_unreachable("Unexpected operand type to get symbol.");
}
@@ -757,6 +772,16 @@ getTOCEntryTypeForMO(const MachineOperand &MO) {
llvm_unreachable("Unexpected operand type to get TOC type.");
}
}

// On AIX, TLS-local-dynamic requires that symbol for the module handle must
// have the name "_$TLSML". This symbol is used as one TOC symbol reference
// itself with ML relocation type, thus it has "[TC]" attached to its name.
static inline bool isSpecialAIXSymbolTLSML(const MachineOperand &MO,
const bool IsAIX) {
return IsAIX && MO.isSymbol() &&
(std::strcmp(MO.getSymbolName(), "_$TLSML[TC]") == 0);
}

/// EmitInstruction -- Print out a single PowerPC MI in Darwin syntax to
/// the current output stream.
///
@@ -846,6 +871,15 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) {
return MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSGDM;
if (MO.getTargetFlags() & PPCII::MO_TLSGD_FLAG)
return MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSGD;
if (MO.getTargetFlags() & PPCII::MO_TLSLD_FLAG) {
if (isSpecialAIXSymbolTLSML(MO, IsAIX))
// FIXME: On AIX the ML relocation type is only valid for a reference to
// a TOC symbol from the symbol itself, and right now its only user is
// symbol "_$TLSML". Use symbol name to decide that R_TLSML is expected.
return MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSML;
if (IsAIX)
return MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSLD;
}
return MCSymbolRefExpr::VariantKind::VK_None;
};

@@ -964,7 +998,8 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) {
TmpInst.setOpcode(PPC::LWZ);

const MachineOperand &MO = MI->getOperand(1);
assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) &&
assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress() ||
isSpecialAIXSymbolTLSML(MO, IsAIX)) &&
"Invalid operand for LWZtoc.");

// Map the operand to its corresponding MCSymbol.
@@ -1053,7 +1088,8 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) {
TmpInst.setOpcode(PPC::LD);

const MachineOperand &MO = MI->getOperand(1);
assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) &&
assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress() ||
isSpecialAIXSymbolTLSML(MO, IsAIX)) &&
"Invalid operand!");

// Map the operand to its corresponding MCSymbol.
@@ -1091,7 +1127,8 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) {
TmpInst.setOpcode(PPC::ADDIS);

const MachineOperand &MO = MI->getOperand(2);
assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) &&
assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress() ||
isSpecialAIXSymbolTLSML(MO, IsAIX)) &&
"Invalid operand for ADDIStocHA.");

// Map the machine operand to its corresponding MCSymbol.
@@ -1124,7 +1161,8 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) {
TmpInst.setOpcode(PPC::LWZ);

const MachineOperand &MO = MI->getOperand(1);
assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) &&
assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress() ||
isSpecialAIXSymbolTLSML(MO, IsAIX)) &&
"Invalid operand for LWZtocL.");

// Map the machine operand to its corresponding MCSymbol.
@@ -1156,7 +1194,8 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) {
TmpInst.setOpcode(PPC::ADDIS8);

const MachineOperand &MO = MI->getOperand(2);
assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) &&
assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress() ||
isSpecialAIXSymbolTLSML(MO, IsAIX)) &&
"Invalid operand for ADDIStocHA8!");

const MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);
@@ -1166,7 +1205,8 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) {
const bool GlobalToc =
MO.isGlobal() && Subtarget->isGVIndirectSymbol(MO.getGlobal());
if (GlobalToc || MO.isJTI() || MO.isBlockAddress() ||
(MO.isCPI() && TM.getCodeModel() == CodeModel::Large))
(MO.isCPI() && TM.getCodeModel() == CodeModel::Large) ||
isSpecialAIXSymbolTLSML(MO, IsAIX))
MOSymbol = lookUpOrCreateTOCEntry(MOSymbol, getTOCEntryTypeForMO(MO), VK);

VK = IsAIX ? MCSymbolRefExpr::VK_PPC_U : MCSymbolRefExpr::VK_PPC_TOC_HA;
@@ -1195,8 +1235,8 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) {
TmpInst.setOpcode(PPC::LD);

const MachineOperand &MO = MI->getOperand(1);
assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() ||
MO.isBlockAddress()) &&
assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress() ||
isSpecialAIXSymbolTLSML(MO, IsAIX)) &&
"Invalid operand for LDtocL!");

LLVM_DEBUG(assert(
@@ -1362,6 +1402,8 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) {
case PPC::GETtlsADDRPCREL:
case PPC::GETtlsADDR32AIX:
case PPC::GETtlsADDR64AIX:
case PPC::GETtlsMOD32AIX:
case PPC::GETtlsMOD64AIX:
// Transform: %r3 = GETtlsADDRNNAIX %r3, %r4 (for NN == 32/64).
// Into: BLA .__tls_get_addr()
// Unlike on Linux, there is no symbol or relocation needed for this call.
@@ -2710,6 +2752,15 @@ void PPCAIXAsmPrinter::emitEndOfAsmFile(Module &M) {
MCSymbol *S = OutContext.getOrCreateSymbol(Name);
TCEntry = cast<MCSectionXCOFF>(
getObjFileLowering().getSectionForTOCEntry(S, TM));
} else if (I.first.second ==
MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSML) {
// AIX assembler expects TC storage-mapping class for the "_$TLSML"
// symbol.
MCSection *MCSect = getObjFileLowering().getContext().getXCOFFSection(
cast<MCSymbolXCOFF>(I.first.first)->getSymbolTableName(),
SectionKind::getData(),
XCOFF::CsectProperties(XCOFF::XMC_TC, XCOFF::XTY_SD));
TCEntry = cast<MCSectionXCOFF>(MCSect);
} else {
TCEntry = cast<MCSectionXCOFF>(
getObjFileLowering().getSectionForTOCEntry(I.first.first, TM));
@@ -2826,6 +2877,8 @@ void PPCAIXAsmPrinter::emitInstruction(const MachineInstr *MI) {
MMI->hasDebugInfo());
break;
}
case PPC::GETtlsMOD32AIX:
case PPC::GETtlsMOD64AIX:
case PPC::GETtlsTpointer32AIX:
case PPC::GETtlsADDR64AIX:
case PPC::GETtlsADDR32AIX: {
28 changes: 21 additions & 7 deletions llvm/lib/Target/PowerPC/PPCISelLowering.cpp
Original file line number Diff line number Diff line change
@@ -1771,9 +1771,13 @@ const char *PPCTargetLowering::getTargetNodeName(unsigned Opcode) const {
case PPCISD::ADDIS_TLSGD_HA: return "PPCISD::ADDIS_TLSGD_HA";
case PPCISD::ADDI_TLSGD_L: return "PPCISD::ADDI_TLSGD_L";
case PPCISD::GET_TLS_ADDR: return "PPCISD::GET_TLS_ADDR";
case PPCISD::GET_TLS_MOD_AIX:
return "PPCISD::GET_TLS_MOD_AIX";
case PPCISD::GET_TPOINTER: return "PPCISD::GET_TPOINTER";
case PPCISD::ADDI_TLSGD_L_ADDR: return "PPCISD::ADDI_TLSGD_L_ADDR";
case PPCISD::TLSGD_AIX: return "PPCISD::TLSGD_AIX";
case PPCISD::TLSLD_AIX:
return "PPCISD::TLSLD_AIX";
case PPCISD::ADDIS_TLSLD_HA: return "PPCISD::ADDIS_TLSLD_HA";
case PPCISD::ADDI_TLSLD_L: return "PPCISD::ADDI_TLSLD_L";
case PPCISD::GET_TLSLD_ADDR: return "PPCISD::GET_TLSLD_ADDR";
@@ -3412,13 +3416,23 @@ SDValue PPCTargetLowering::LowerGlobalTLSAddressAIX(SDValue Op,
return DAG.getNode(PPCISD::ADD_TLS, dl, PtrVT, TLSReg, VariableOffset);
}

// Only Local-Exec, Initial-Exec and General-Dynamic TLS models are currently
// supported models. If Local- or Initial-exec are not possible or specified,
// all GlobalTLSAddress nodes are lowered using the general-dynamic model.
// We need to generate two TOC entries, one for the variable offset, one for
// the region handle. The global address for the TOC entry of the region
// handle is created with the MO_TLSGDM_FLAG flag and the global address
// for the TOC entry of the variable offset is created with MO_TLSGD_FLAG.
if (Model == TLSModel::LocalDynamic) {
// For local-dynamic on AIX, we need to generate two TOC entries, one for
// the variable offset, the other for the module handle. The module handle
// is encapsulated inside the TLSLD_AIX pseudo node, and will be expanded by
// PPCTLSDynamicCall.
SDValue VariableOffsetTGA =
DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0, PPCII::MO_TLSLD_FLAG);
SDValue VariableOffset = getTOCEntry(DAG, dl, VariableOffsetTGA);
return DAG.getNode(PPCISD::TLSLD_AIX, dl, PtrVT, VariableOffset);
}

// If Local- or Initial-exec or Local-dynamic is not possible or specified,
// all GlobalTLSAddress nodes are lowered using the general-dynamic model. We
// need to generate two TOC entries, one for the variable offset, one for the
// region handle. The global address for the TOC entry of the region handle is
// created with the MO_TLSGDM_FLAG flag and the global address for the TOC
// entry of the variable offset is created with MO_TLSGD_FLAG.
SDValue VariableOffsetTGA =
DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0, PPCII::MO_TLSGD_FLAG);
SDValue RegionHandleTGA =
14 changes: 13 additions & 1 deletion llvm/lib/Target/PowerPC/PPCISelLowering.h
Original file line number Diff line number Diff line change
@@ -370,11 +370,23 @@ namespace llvm {
/// G8RC = TLSGD_AIX, TOC_ENTRY, TOC_ENTRY
/// Op that combines two register copies of TOC entries
/// (region handle into R3 and variable offset into R4) followed by a
/// GET_TLS_ADDR node which will be expanded to a call to __get_tls_addr.
/// GET_TLS_ADDR node which will be expanded to a call to .__tls_get_addr.
/// This node is used in 64-bit mode as well (in which case the result is
/// G8RC and inputs are X3/X4).
TLSGD_AIX,

/// %x3 = GET_TLS_MOD_AIX _$TLSML - For the AIX local-dynamic TLS model,
/// produces a call to .__tls_get_mod(_$TLSML\@ml).
GET_TLS_MOD_AIX,

/// [GP|G8]RC = TLSLD_AIX, TOC_ENTRY(variable offset)
/// Op that internally creates TOC entry for the "_$TLSML" symbol, generates
/// GET_TLS_MOD_AIX node which will be expanded into a call to
/// .__tls_get_mod, and then add the variable offset with the result from
/// the call. This node is used in both 32-bit and 64-bit modes. The only
/// difference is register class.
TLSLD_AIX,

/// G8RC = ADDIS_TLSLD_HA %x2, Symbol - For the local-dynamic TLS
/// model, produces an ADDIS8 instruction that adds the GOT base
/// register to sym\@got\@tlsld\@ha.
Loading