diff --git a/llvm/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp b/llvm/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp --- a/llvm/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp +++ b/llvm/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp @@ -444,13 +444,22 @@ // On PPC64, VariantKind is VK_None, but on PPC32, it's VK_PLT, and it must // come at the _end_ of the expression. const MCOperand &Op = MI->getOperand(OpNo); - const MCSymbolRefExpr &refExp = cast(*Op.getExpr()); - O << refExp.getSymbol().getName(); + const MCSymbolRefExpr *RefExp = nullptr; + const MCConstantExpr *ConstExp = nullptr; + if (const MCBinaryExpr *BinExpr = dyn_cast(Op.getExpr())) { + RefExp = cast(BinExpr->getLHS()); + ConstExp = cast(BinExpr->getRHS()); + } else + RefExp = cast(Op.getExpr()); + + O << RefExp->getSymbol().getName(); O << '('; printOperand(MI, OpNo+1, O); O << ')'; - if (refExp.getKind() != MCSymbolRefExpr::VK_None) - O << '@' << MCSymbolRefExpr::getVariantKindName(refExp.getKind()); + if (RefExp->getKind() != MCSymbolRefExpr::VK_None) + O << '@' << MCSymbolRefExpr::getVariantKindName(RefExp->getKind()); + if (ConstExp != nullptr) + O << '+' << ConstExp->getValue(); } /// showRegistersWithPercentPrefix - Check if this register name should be diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp --- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -472,8 +472,14 @@ if (!Subtarget->isPPC64() && !Subtarget->isDarwin() && isPositionIndependent()) Kind = MCSymbolRefExpr::VK_PLT; - const MCSymbolRefExpr *TlsRef = + const MCExpr *TlsRef = MCSymbolRefExpr::create(TlsGetAddr, Kind, OutContext); + + // Add 32768 offset to the symbol so we follow up the latest GOT/PLT ABI. + if (Kind == MCSymbolRefExpr::VK_PLT && Subtarget->isSecurePlt()) + TlsRef = MCBinaryExpr::createAdd(TlsRef, + MCConstantExpr::create(32768, OutContext), + OutContext); const MachineOperand &MO = MI->getOperand(2); const GlobalValue *GValue = MO.getGlobal(); MCSymbol *MOSymbol = getSymbol(GValue); diff --git a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp --- a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -4353,7 +4353,20 @@ if (trySETCC(N)) return; break; - + // These nodes will be transformed into GETtlsADDR32 node, which + // later becomes BL_TLS __tls_get_addr(sym at tlsgd)@PLT + case PPCISD::ADDI_TLSLD_L_ADDR: + case PPCISD::ADDI_TLSGD_L_ADDR: { + const Module *Mod = MF->getFunction().getParent(); + if (PPCLowering->getPointerTy(CurDAG->getDataLayout()) != MVT::i32 || + !PPCSubTarget->isSecurePlt() || !PPCSubTarget->isTargetELF() || + Mod->getPICLevel() == PICLevel::SmallPIC) + break; + // Attach global base pointer on GETtlsADDR32 node in order to + // generate secure plt code for TLS symbols. + getGlobalBaseReg(); + } + break; case PPCISD::CALL: { const Module *M = MF->getFunction().getParent(); diff --git a/llvm/test/CodeGen/PowerPC/ppc32-secure-plt-tls.ll b/llvm/test/CodeGen/PowerPC/ppc32-secure-plt-tls.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/ppc32-secure-plt-tls.ll @@ -0,0 +1,18 @@ +; RUN: llc < %s -mtriple=powerpc-unknown-linux-gnu -mattr=+secure-plt -relocation-model=pic | FileCheck -check-prefix=SECURE-PLT-TLS %s + +@a = thread_local local_unnamed_addr global i32 6, align 4 +define i32 @main() local_unnamed_addr #0 { +entry: + %0 = load i32, i32* @a, align 4 + ret i32 %0 +} + + +!llvm.module.flags = !{!0} +!0 = !{i32 7, !"PIC Level", i32 2} + +; SECURE-PLT-TLS: mflr 30 +; SECURE-PLT-TLS-NEXT: addis 30, 30, .LTOC-.L0$pb@ha +; SECURE-PLT-TLS-NEXT: addi 30, 30, .LTOC-.L0$pb@l +; SECURE-PLT-TLS-NEXT: bl .L{{.*}} +; SECURE-PLT-TLS: bl __tls_get_addr(a@tlsgd)@PLT+32768 \ No newline at end of file