Commit f0b2f695 authored by Amy Kwan's avatar Amy Kwan
Browse files

[AIX][TLS] Generate .extern and .ref references to __tls_get_addr for local-exec accesses.

Compiling with TLS variables requires -pthread, but if the user omits this
option, the compiler will not show any obvious indication during compilation
that -pthread is needed for programs using TLS variables. Instead, the user will
experience a segmentation fault when running programs with TLS variables in them
and without specifying -pthread.

This patch aims to generate .extern/.ref references to __tls_get_addr[DS] for
local-exec accesses, in order to trigger an error from the linker to indicate
that there is an undefined symbol to __tls_get_addr. Doing so will remind the
user to compile/link with -pthread.

Differential Revision: https://reviews.llvm.org/D151335
parent be0e42c1
Loading
Loading
Loading
Loading
+34 −5
Original line number Diff line number Diff line
@@ -171,6 +171,11 @@ public:
    TOCType_EHBlock
  };

  // Controls whether or not to emit a .ref reference to __tls_get_addr.
  // This is currently used for TLS models that do not generate calls to
  // TLS functions, such as for the local-exec model on AIX 64-bit.
  bool HasRefGetTLSAddr = false;

  MCSymbol *lookUpOrCreateTOCEntry(const MCSymbol *Sym, TOCEntryType Type,
                                   MCSymbolRefExpr::VariantKind Kind =
                                       MCSymbolRefExpr::VariantKind::VK_None);
@@ -615,12 +620,17 @@ void PPCAsmPrinter::LowerPATCHPOINT(StackMaps &SM, const MachineInstr &MI) {
/// 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.
static MCSymbol *createMCSymbolForTlsGetAddr(MCContext &Ctx, unsigned MIOpc) {
  StringRef SymName =
      MIOpc == PPC::GETtlsTpointer32AIX ? ".__get_tpointer" : ".__tls_get_addr";
static MCSymbol *
createMCSymbolForTlsGetAddr(MCContext &Ctx, unsigned MIOpc,
                            XCOFF::StorageMappingClass SMC = XCOFF::XMC_PR) {
  StringRef SymName;
  if (MIOpc == PPC::GETtlsTpointer32AIX)
    SymName = ".__get_tpointer";
  else
    SymName = (SMC == XCOFF::XMC_DS) ? "__tls_get_addr" : ".__tls_get_addr";
  return Ctx
      .getXCOFFSection(SymName, SectionKind::getText(),
                       XCOFF::CsectProperties(XCOFF::XMC_PR, XCOFF::XTY_ER))
                       XCOFF::CsectProperties(SMC, XCOFF::XTY_ER))
      ->getQualNameSymbol();
}

@@ -832,8 +842,11 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) {
    if (MO.getTargetFlags() & PPCII::MO_TPREL_FLAG) {
      assert(MO.isGlobal() && "Only expecting a global MachineOperand here!\n");
      TLSModel::Model Model = TM.getTLSModel(MO.getGlobal());
      if (Model == TLSModel::LocalExec)
      if (Model == TLSModel::LocalExec) {
        if (IsPPC64)
          HasRefGetTLSAddr = true;
        return MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSLE;
      }
      if (Model == TLSModel::InitialExec)
        return MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSIE;
      llvm_unreachable("Only expecting local-exec or initial-exec accesses!");
@@ -2862,6 +2875,22 @@ bool PPCAIXAsmPrinter::doFinalization(Module &M) {
    OutStreamer->doFinalizationAtSectionEnd(
        OutStreamer->getContext().getObjectFileInfo()->getTextSection());

  // Add a single .ref reference to __tls_get_addr[DS] for the local-exec TLS
  // model on AIX 64-bit. For TLS models that do not generate calls to TLS
  // functions, this reference to __tls_get_addr helps generate a linker error
  // to an undefined symbol to __tls_get_addr, which indicates to the user that
  // compiling with -pthread is required for programs that use TLS variables.
  if (HasRefGetTLSAddr) {
    // Specifically for 64-bit AIX, a load from the TOC is generated to load
    // the variable offset needed for local-exec accesses.
    MCSymbol *TlsGetAddrDescriptor =
        createMCSymbolForTlsGetAddr(OutContext, PPC::GETtlsADDR64AIX,
                                    XCOFF::XMC_DS);

    ExtSymSDNodeSymbols.insert(TlsGetAddrDescriptor);
    OutStreamer->emitXCOFFRefDirective(TlsGetAddrDescriptor);
  }

  for (MCSymbol *Sym : ExtSymSDNodeSymbols)
    OutStreamer->emitSymbolAttribute(Sym, MCSA_Extern);
  return PPCAsmPrinter::doFinalization(M);
+7 −0
Original line number Diff line number Diff line
@@ -635,6 +635,13 @@ entry:
  ret double %add
}

; (64-bit only) External symbol reference checks for __tls_get_addr[DS]

; SMALL64: .ref __tls_get_addr[DS]
; SMALL64: .extern __tls_get_addr[DS]
; LARGE64: .ref __tls_get_addr[DS]
; LARGE64: .extern __tls_get_addr[DS]

; TOC Entry Checks.

; SMALL64-LABEL: .toc
+7 −0
Original line number Diff line number Diff line
@@ -635,6 +635,13 @@ entry:
  ret float %add
}

; (64-bit only) External symbol reference checks for __tls_get_addr[DS]

; SMALL64: .ref __tls_get_addr[DS]
; SMALL64: .extern __tls_get_addr[DS]
; LARGE64: .ref __tls_get_addr[DS]
; LARGE64: .extern __tls_get_addr[DS]

; TOC Entry Checks.

; SMALL64-LABEL: .toc
+7 −0
Original line number Diff line number Diff line
@@ -651,6 +651,13 @@ entry:
  ret i32 %add
}

; (64-bit only) External symbol reference checks for __tls_get_addr[DS]

; SMALL64: .ref __tls_get_addr[DS]
; SMALL64: .extern __tls_get_addr[DS]
; LARGE64: .ref __tls_get_addr[DS]
; LARGE64: .extern __tls_get_addr[DS]

; TOC Entry Checks.

; SMALL64-LABEL: .toc
+7 −0
Original line number Diff line number Diff line
@@ -707,6 +707,13 @@ entry:
  ret i64 %add
}

; (64-bit only) External symbol reference checks for __tls_get_addr[DS]

; SMALL64: .ref __tls_get_addr[DS]
; SMALL64: .extern __tls_get_addr[DS]
; LARGE64: .ref __tls_get_addr[DS]
; LARGE64: .extern __tls_get_addr[DS]

; TOC Entry Checks.

; SMALL64-LABEL: .toc
Loading