diff --git a/llvm/include/llvm/BinaryFormat/ELFRelocs/PowerPC64.def b/llvm/include/llvm/BinaryFormat/ELFRelocs/PowerPC64.def --- a/llvm/include/llvm/BinaryFormat/ELFRelocs/PowerPC64.def +++ b/llvm/include/llvm/BinaryFormat/ELFRelocs/PowerPC64.def @@ -100,6 +100,7 @@ #undef R_PPC64_PCREL_OPT #undef R_PPC64_PCREL34 #undef R_PPC64_GOT_PCREL34 +#undef R_PPC64_GOT_TLSGD_PCREL34 #undef R_PPC64_IRELATIVE #undef R_PPC64_REL16 #undef R_PPC64_REL16_LO @@ -198,6 +199,7 @@ ELF_RELOC(R_PPC64_PCREL_OPT, 123) ELF_RELOC(R_PPC64_PCREL34, 132) ELF_RELOC(R_PPC64_GOT_PCREL34, 133) +ELF_RELOC(R_PPC64_GOT_TLSGD_PCREL34, 148) ELF_RELOC(R_PPC64_IRELATIVE, 248) ELF_RELOC(R_PPC64_REL16, 249) ELF_RELOC(R_PPC64_REL16_LO, 250) diff --git a/llvm/include/llvm/MC/MCExpr.h b/llvm/include/llvm/MC/MCExpr.h --- a/llvm/include/llvm/MC/MCExpr.h +++ b/llvm/include/llvm/MC/MCExpr.h @@ -299,6 +299,7 @@ VK_PPC_GOT_TLSLD_HI, // symbol@got@tlsld@h VK_PPC_GOT_TLSLD_HA, // symbol@got@tlsld@ha VK_PPC_GOT_PCREL, // symbol@got@pcrel + VK_PPC_GOT_TLSGD_PCREL, // symbol@got@tlsgd@pcrel VK_PPC_TLSLD, // symbol@tlsld VK_PPC_LOCAL, // symbol@local VK_PPC_NOTOC, // symbol@notoc diff --git a/llvm/lib/MC/MCExpr.cpp b/llvm/lib/MC/MCExpr.cpp --- a/llvm/lib/MC/MCExpr.cpp +++ b/llvm/lib/MC/MCExpr.cpp @@ -322,6 +322,8 @@ case VK_PPC_GOT_TLSLD_HA: return "got@tlsld@ha"; case VK_PPC_GOT_PCREL: return "got@pcrel"; + case VK_PPC_GOT_TLSGD_PCREL: + return "got@tlsgd@pcrel"; case VK_PPC_TLSLD: return "tlsld"; case VK_PPC_LOCAL: return "local"; case VK_PPC_NOTOC: return "notoc"; @@ -454,6 +456,7 @@ .Case("got@tlsld@h", VK_PPC_GOT_TLSLD_HI) .Case("got@tlsld@ha", VK_PPC_GOT_TLSLD_HA) .Case("got@pcrel", VK_PPC_GOT_PCREL) + .Case("got@tlsgd@pcrel", VK_PPC_GOT_TLSGD_PCREL) .Case("notoc", VK_PPC_NOTOC) .Case("gdgot", VK_Hexagon_GD_GOT) .Case("gdplt", VK_Hexagon_GD_PLT) diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp --- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp +++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp @@ -138,6 +138,9 @@ case MCSymbolRefExpr::VK_PPC_GOT_PCREL: Type = ELF::R_PPC64_GOT_PCREL34; break; + case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_PCREL: + Type = ELF::R_PPC64_GOT_TLSGD_PCREL34; + break; } break; case FK_Data_4: diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.cpp --- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.cpp +++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCInstPrinter.cpp @@ -531,10 +531,17 @@ RefExp = cast(Op.getExpr()); O << RefExp->getSymbol().getName(); + // The variant kind VK_PPC_NOTOC needs to be handled as a special case + // because we do not want the assembly to print out the @notoc at the + // end like __tls_get_addr(x@tlsgd)@notoc. Instead we want it to look + // like __tls_get_addr@notoc(x@tlsgd). + if (RefExp->getKind() == MCSymbolRefExpr::VK_PPC_NOTOC) + O << '@' << MCSymbolRefExpr::getVariantKindName(RefExp->getKind()); O << '('; printOperand(MI, OpNo+1, O); O << ')'; - if (RefExp->getKind() != MCSymbolRefExpr::VK_None) + if (RefExp->getKind() != MCSymbolRefExpr::VK_None && + RefExp->getKind() != MCSymbolRefExpr::VK_PPC_NOTOC) O << '@' << MCSymbolRefExpr::getVariantKindName(RefExp->getKind()); if (ConstExp != nullptr) O << '+' << ConstExp->getValue(); diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp --- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp +++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp @@ -44,11 +44,13 @@ SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const { const MCOperand &MO = MI.getOperand(OpNo); - if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups, STI); + if (MO.isReg() || MO.isImm()) + return getMachineOpValue(MI, MO, Fixups, STI); // Add a fixup for the branch target. Fixups.push_back(MCFixup::create(0, MO.getExpr(), - ((MI.getOpcode() == PPC::BL8_NOTOC) + ((MI.getOpcode() == PPC::BL8_NOTOC || + MI.getOpcode() == PPC::BL8_NOTOC_TLS) ? (MCFixupKind)PPC::fixup_ppc_br24_notoc : (MCFixupKind)PPC::fixup_ppc_br24))); return 0; @@ -229,8 +231,10 @@ (void)SRE; // Currently these are the only valid PCRelative Relocations. assert((SRE->getKind() == MCSymbolRefExpr::VK_PCREL || - SRE->getKind() == MCSymbolRefExpr::VK_PPC_GOT_PCREL) && - "VariantKind must be VK_PCREL or VK_PPC_GOT_PCREL"); + SRE->getKind() == MCSymbolRefExpr::VK_PPC_GOT_PCREL || + SRE->getKind() == MCSymbolRefExpr::VK_PPC_GOT_TLSGD_PCREL) && + "VariantKind must be VK_PCREL or VK_PPC_GOT_PCREL or " + "VK_PPC_GOT_TLSGD_PCREL"); // Generate the fixup for the relocation. Fixups.push_back( MCFixup::create(0, Expr, diff --git a/llvm/lib/Target/PowerPC/PPC.h b/llvm/lib/Target/PowerPC/PPC.h --- a/llvm/lib/Target/PowerPC/PPC.h +++ b/llvm/lib/Target/PowerPC/PPC.h @@ -109,6 +109,15 @@ // PC Relative linker optimization. MO_PCREL_OPT_FLAG = 16, + /// MO_TLSGD_FLAG - If this bit is set the symbol reference is relative to + /// TLS General Dynamic model. + MO_TLSGD_FLAG = 32, + + /// MO_GOT_TLSGD_PCREL_FLAG - A combintaion of flags, if these bits are set + /// they should produce the relocation @got@tlsgd@pcrel. + /// Fix up is VK_PPC_GOT_TLSGD_PCREL + MO_GOT_TLSGD_PCREL_FLAG = MO_PCREL_FLAG | MO_GOT_FLAG | MO_TLSGD_FLAG, + /// The next are not flags but distinct values. MO_ACCESS_MASK = 0xf00, 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 @@ -488,6 +488,13 @@ StringRef Name = "__tls_get_addr"; MCSymbol *TlsGetAddr = OutContext.getOrCreateSymbol(Name); MCSymbolRefExpr::VariantKind Kind = MCSymbolRefExpr::VK_None; + unsigned Opcode = PPC::BL8_NOP_TLS; + + assert(MI->getNumOperands() >= 3 && "Expecting at least 3 operands from MI"); + if (MI->getOperand(2).getTargetFlags() == PPCII::MO_GOT_TLSGD_PCREL_FLAG) { + Kind = MCSymbolRefExpr::VK_PPC_NOTOC; + Opcode = PPC::BL8_NOTOC_TLS; + } const Module *M = MF->getFunction().getParent(); assert(MI->getOperand(0).isReg() && @@ -515,10 +522,9 @@ MCSymbol *MOSymbol = getSymbol(GValue); const MCExpr *SymVar = MCSymbolRefExpr::create(MOSymbol, VK, OutContext); EmitToStreamer(*OutStreamer, - MCInstBuilder(Subtarget->isPPC64() ? - PPC::BL8_NOP_TLS : PPC::BL_TLS) - .addExpr(TlsRef) - .addExpr(SymVar)); + MCInstBuilder(Subtarget->isPPC64() ? Opcode : PPC::BL_TLS) + .addExpr(TlsRef) + .addExpr(SymVar)); } /// Map a machine operand for a TOC pseudo-machine instruction to its diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.h b/llvm/lib/Target/PowerPC/PPCISelLowering.h --- a/llvm/lib/Target/PowerPC/PPCISelLowering.h +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.h @@ -436,6 +436,11 @@ /// PLD. MAT_PCREL_ADDR, + /// TLS_DYNAMIC_MAT_PCREL_ADDR = Materialize a PC Relative address for + /// TLS global address when using dynamic access models. This can be done + /// through an add like PADDI. + TLS_DYNAMIC_MAT_PCREL_ADDR, + // Constrained conversion from floating point to int STRICT_FCTIDZ = ISD::FIRST_TARGET_STRICTFP_OPCODE, STRICT_FCTIWZ, diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp --- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp @@ -1472,6 +1472,8 @@ case PPCISD::LD_VSX_LH: return "PPCISD::LD_VSX_LH"; case PPCISD::FP_EXTEND_HALF: return "PPCISD::FP_EXTEND_HALF"; case PPCISD::MAT_PCREL_ADDR: return "PPCISD::MAT_PCREL_ADDR"; + case PPCISD::TLS_DYNAMIC_MAT_PCREL_ADDR: + return "PPCISD::TLS_DYNAMIC_MAT_PCREL_ADDR"; case PPCISD::LD_SPLAT: return "PPCISD::LD_SPLAT"; case PPCISD::FNMSUB: return "PPCISD::FNMSUB"; case PPCISD::STRICT_FCTIDZ: @@ -2999,6 +3001,12 @@ } if (Model == TLSModel::GeneralDynamic) { + if (Subtarget.isUsingPCRelativeCalls()) { + SDValue TGA = DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0, + PPCII::MO_GOT_TLSGD_PCREL_FLAG); + return DAG.getNode(PPCISD::TLS_DYNAMIC_MAT_PCREL_ADDR, dl, PtrVT, TGA); + } + SDValue TGA = DAG.getTargetGlobalAddress(GV, dl, PtrVT, 0, 0); SDValue GOTPtr; if (is64bit) { diff --git a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td --- a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td +++ b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td @@ -148,6 +148,9 @@ def BL8_NOTOC : IForm<18, 0, 1, (outs), (ins calltarget:$func), "bl $func", IIC_BrB, []>; + def BL8_NOTOC_TLS : IForm<18, 0, 1, (outs), + (ins tlscall:$func), + "bl $func", IIC_BrB, []>; } } let Uses = [CTR8, RM] in { diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp b/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp --- a/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp +++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp @@ -2272,7 +2272,9 @@ {MO_PIC_FLAG, "ppc-pic"}, {MO_PCREL_FLAG, "ppc-pcrel"}, {MO_GOT_FLAG, "ppc-got"}, - {MO_PCREL_OPT_FLAG, "ppc-opt-pcrel"}}; + {MO_PCREL_OPT_FLAG, "ppc-opt-pcrel"}, + {MO_TLSGD_FLAG, "ppc-tlsgd"}, + {MO_GOT_TLSGD_PCREL_FLAG, "ppc-got-tlsgd-pcrel"}}; return makeArrayRef(TargetFlags); } diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.td b/llvm/lib/Target/PowerPC/PPCInstrInfo.td --- a/llvm/lib/Target/PowerPC/PPCInstrInfo.td +++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.td @@ -339,6 +339,8 @@ // PC Relative Specific Nodes def PPCmatpcreladdr : SDNode<"PPCISD::MAT_PCREL_ADDR", SDTIntUnaryOp, []>; +def PPCtlsdynamatpcreladdr : SDNode<"PPCISD::TLS_DYNAMIC_MAT_PCREL_ADDR", + SDTIntUnaryOp, []>; //===----------------------------------------------------------------------===// // PowerPC specific transformation functions and pattern fragments. diff --git a/llvm/lib/Target/PowerPC/PPCInstrPrefix.td b/llvm/lib/Target/PowerPC/PPCInstrPrefix.td --- a/llvm/lib/Target/PowerPC/PPCInstrPrefix.td +++ b/llvm/lib/Target/PowerPC/PPCInstrPrefix.td @@ -811,6 +811,9 @@ // If the PPCmatpcreladdr node is not caught by any other pattern it should be // caught here and turned into a paddi instruction to materialize the address. def : Pat<(PPCmatpcreladdr pcreladdr:$addr), (PADDI8pc 0, $addr)>; + // PPCtlsdynamatpcreladdr node is used for TLS dynamic models to materialize + // tls global address with paddi instruction. + def : Pat<(PPCtlsdynamatpcreladdr pcreladdr:$addr), (PADDI8pc 0, $addr)>; } let Predicates = [PrefixInstrs] in { diff --git a/llvm/lib/Target/PowerPC/PPCMCInstLower.cpp b/llvm/lib/Target/PowerPC/PPCMCInstLower.cpp --- a/llvm/lib/Target/PowerPC/PPCMCInstLower.cpp +++ b/llvm/lib/Target/PowerPC/PPCMCInstLower.cpp @@ -84,6 +84,8 @@ RefKind = MCSymbolRefExpr::VK_PCREL; else if (MO.getTargetFlags() == (PPCII::MO_PCREL_FLAG | PPCII::MO_GOT_FLAG)) RefKind = MCSymbolRefExpr::VK_PPC_GOT_PCREL; + else if (MO.getTargetFlags() == PPCII::MO_GOT_TLSGD_PCREL_FLAG) + RefKind = MCSymbolRefExpr::VK_PPC_GOT_TLSGD_PCREL; const MachineInstr *MI = MO.getParent(); const MachineFunction *MF = MI->getMF(); diff --git a/llvm/lib/Target/PowerPC/PPCTLSDynamicCall.cpp b/llvm/lib/Target/PowerPC/PPCTLSDynamicCall.cpp --- a/llvm/lib/Target/PowerPC/PPCTLSDynamicCall.cpp +++ b/llvm/lib/Target/PowerPC/PPCTLSDynamicCall.cpp @@ -50,16 +50,17 @@ bool Changed = false; bool NeedFence = true; bool Is64Bit = MBB.getParent()->getSubtarget().isPPC64(); + bool IsTLSGDPCREL = false; for (MachineBasicBlock::iterator I = MBB.begin(), IE = MBB.end(); I != IE;) { MachineInstr &MI = *I; + IsTLSGDPCREL = isTLSGDPCREL(MI); if (MI.getOpcode() != PPC::ADDItlsgdLADDR && MI.getOpcode() != PPC::ADDItlsldLADDR && MI.getOpcode() != PPC::ADDItlsgdLADDR32 && - MI.getOpcode() != PPC::ADDItlsldLADDR32) { - + MI.getOpcode() != PPC::ADDItlsldLADDR32 && !IsTLSGDPCREL) { // Although we create ADJCALLSTACKDOWN and ADJCALLSTACKUP // as scheduling fences, we skip creating fences if we already // have existing ADJCALLSTACKDOWN/UP to avoid nesting, @@ -76,12 +77,16 @@ LLVM_DEBUG(dbgs() << "TLS Dynamic Call Fixup:\n " << MI); Register OutReg = MI.getOperand(0).getReg(); - Register InReg = MI.getOperand(1).getReg(); - DebugLoc DL = MI.getDebugLoc(); + Register InReg = PPC::NoRegister; Register GPR3 = Is64Bit ? PPC::X3 : PPC::R3; - unsigned Opc1, Opc2; - const Register OrigRegs[] = {OutReg, InReg, GPR3}; + SmallVector OrigRegs = {OutReg, GPR3}; + if (!IsTLSGDPCREL) { + InReg = MI.getOperand(1).getReg(); + OrigRegs.push_back(InReg); + } + DebugLoc DL = MI.getDebugLoc(); + unsigned Opc1, Opc2; switch (MI.getOpcode()) { default: llvm_unreachable("Opcode inconsistency error"); @@ -101,6 +106,10 @@ Opc1 = PPC::ADDItlsldL32; Opc2 = PPC::GETtlsldADDR32; break; + case PPC::PADDI8pc: + assert(IsTLSGDPCREL && "Expecting General Dynamic PCRel"); + Opc1 = PPC::PADDI8pc; + Opc2 = PPC::GETtlsADDR; } // We create ADJCALLSTACKUP and ADJCALLSTACKDOWN around _tls_get_addr @@ -113,9 +122,15 @@ BuildMI(MBB, I, DL, TII->get(PPC::ADJCALLSTACKDOWN)).addImm(0) .addImm(0); - // Expand into two ops built prior to the existing instruction. - MachineInstr *Addi = BuildMI(MBB, I, DL, TII->get(Opc1), GPR3) - .addReg(InReg); + MachineInstr *Addi; + if (IsTLSGDPCREL) { + Addi = BuildMI(MBB, I, DL, TII->get(Opc1), GPR3).addImm(0); + } else { + // Expand into two ops built prior to the existing instruction. + assert(InReg != PPC::NoRegister && "Operand must be a register"); + Addi = BuildMI(MBB, I, DL, TII->get(Opc1), GPR3).addReg(InReg); + } + Addi->addOperand(MI.getOperand(2)); // The ADDItls* instruction is the first instruction in the @@ -125,7 +140,10 @@ MachineInstr *Call = (BuildMI(MBB, I, DL, TII->get(Opc2), GPR3) .addReg(GPR3)); - Call->addOperand(MI.getOperand(3)); + if (IsTLSGDPCREL) + Call->addOperand(MI.getOperand(2)); + else + Call->addOperand(MI.getOperand(3)); if (NeedFence) BuildMI(MBB, I, DL, TII->get(PPC::ADJCALLSTACKUP)).addImm(0).addImm(0); @@ -150,6 +168,11 @@ } public: + bool isTLSGDPCREL(const MachineInstr &MI) { + return (MI.getOpcode() == PPC::PADDI8pc) && + (MI.getOperand(2).getTargetFlags() == + PPCII::MO_GOT_TLSGD_PCREL_FLAG); + } bool runOnMachineFunction(MachineFunction &MF) override { TII = MF.getSubtarget().getInstrInfo(); LIS = &getAnalysis(); diff --git a/llvm/test/CodeGen/PowerPC/pcrel-tls-general-dynamic.ll b/llvm/test/CodeGen/PowerPC/pcrel-tls-general-dynamic.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/pcrel-tls-general-dynamic.ll @@ -0,0 +1,51 @@ +; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu \ +; RUN: --relocation-model=pic -mcpu=pwr10 -ppc-asm-full-reg-names \ +; RUN: -enable-ppc-pcrel-tls < %s | FileCheck %s --check-prefix=CHECK-S +; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu \ +; RUN: --relocation-model=pic -mcpu=pwr10 -ppc-asm-full-reg-names \ +; RUN: -enable-ppc-pcrel-tls --filetype=obj < %s | \ +; RUN: llvm-objdump --mcpu=pwr10 -dr - | FileCheck %s --check-prefix=CHECK-O + +; These test cases are to ensure that when using pc relative memory operations +; ABI correct code and relocations are produced for General Dynamic TLS Model. + +@x = external thread_local global i32, align 4 + +define nonnull i32* @GeneralDynamicAddressLoad() { + ; CHECK-S-LABEL: GeneralDynamicAddressLoad: + ; CHECK-S: paddi r3, 0, x@got@tlsgd@pcrel, 1 + ; CHECK-S-NEXT: bl __tls_get_addr@notoc(x@tlsgd) + ; CHECK-S-NEXT: addi r1, r1, 32 + ; CHECK-S-NEXT: ld r0, 16(r1) + ; CHECK-S-NEXT: mtlr r0 + ; CHECK-S-NEXT: blr + ; CHECK-O-LABEL: : + ; CHECK-O: c: 00 00 10 06 00 00 60 38 paddi 3, 0, 0, 1 + ; CHECK-O-NEXT: 000000000000000c: R_PPC64_GOT_TLSGD_PCREL34 x + ; CHECK-O-NEXT: 14: 01 00 00 48 bl 0x14 + ; CHECK-O-NEXT: 0000000000000014: R_PPC64_TLSGD x + ; CHECK-O-NEXT: 0000000000000014: R_PPC64_REL24_NOTOC __tls_get_addr + entry: + ret i32* @x +} + +define i32 @GeneralDynamicValueLoad() { + ; CHECK-S-LABEL: GeneralDynamicValueLoad: + ; CHECK-S: paddi r3, 0, x@got@tlsgd@pcrel, 1 + ; CHECK-S-NEXT: bl __tls_get_addr@notoc(x@tlsgd) + ; CHECK-S-NEXT: lwz r3, 0(r3) + ; CHECK-S-NEXT: addi r1, r1, 32 + ; CHECK-S-NEXT: ld r0, 16(r1) + ; CHECK-S-NEXT: mtlr r0 + ; CHECK-S-NEXT: blr + ; CHECK-O-LABEL: : + ; CHECK-O: 4c: 00 00 10 06 00 00 60 38 paddi 3, 0, 0, 1 + ; CHECK-O-NEXT: 000000000000004c: R_PPC64_GOT_TLSGD_PCREL34 x + ; CHECK-O-NEXT: 54: 01 00 00 48 bl 0x54 + ; CHECK-O-NEXT: 0000000000000054: R_PPC64_TLSGD x + ; CHECK-O-NEXT: 0000000000000054: R_PPC64_REL24_NOTOC __tls_get_addr + ; CHECK-O-NEXT: 58: 00 00 63 80 lwz 3, 0(3) + entry: + %0 = load i32, i32* @x, align 4 + ret i32 %0 +} diff --git a/llvm/test/MC/PowerPC/pcrel-tls-general-dynamic-address-load-reloc.s b/llvm/test/MC/PowerPC/pcrel-tls-general-dynamic-address-load-reloc.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/PowerPC/pcrel-tls-general-dynamic-address-load-reloc.s @@ -0,0 +1,25 @@ +# RUN: llvm-mc -triple=powerpc64le-unknown-unknown -filetype=obj %s 2>&1 | \ +# RUN: FileCheck %s -check-prefix=MC +# RUN: llvm-mc -triple=powerpc64le-unknown-unknown -filetype=obj %s | \ +# RUN: llvm-readobj -r - | FileCheck %s -check-prefix=READOBJ + +# This test checks that on Power PC we can correctly convert @got@tlsgd@pcrel +# x@tlsgd and __tls_get_addr@notoc into R_PPC64_GOT_TLSGD_PCREL34, R_PPC64_TLSGD +# and R_PPC64_REL24_NOTOC for general dynamic relocations with address loaded + +# MC-NOT: error: invalid variant + +# READOBJ: 0xC R_PPC64_GOT_TLSGD_PCREL34 x 0x0 +# READOBJ-NEXT: 0x14 R_PPC64_TLSGD x 0x0 +# READOBJ-NEXT: 0x14 R_PPC64_REL24_NOTOC __tls_get_addr 0x0 + +GeneralDynamicAddrLoad: # @GeneralDynamicAddrLoad + mflr 0 + std 0, 16(1) + stdu 1, -32(1) + paddi 3, 0, x@got@tlsgd@pcrel, 1 + bl __tls_get_addr@notoc(x@tlsgd) + addi 1, 1, 32 + ld 0, 16(1) + mtlr 0 + blr diff --git a/llvm/test/MC/PowerPC/pcrel-tls-general-dynamic-value-load-reloc.s b/llvm/test/MC/PowerPC/pcrel-tls-general-dynamic-value-load-reloc.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/PowerPC/pcrel-tls-general-dynamic-value-load-reloc.s @@ -0,0 +1,26 @@ +# RUN: llvm-mc -triple=powerpc64le-unknown-unknown -filetype=obj %s 2>&1 | \ +# RUN: FileCheck %s -check-prefix=MC +# RUN: llvm-mc -triple=powerpc64le-unknown-unknown -filetype=obj %s | \ +# RUN: llvm-readobj -r - | FileCheck %s -check-prefix=READOBJ + +# This test checks that on Power PC we can correctly convert @got@tlsgd@pcrel +# x@tlsgd and __tls_get_addr@notoc into R_PPC64_GOT_TLSGD_PCREL34, R_PPC64_TLSGD +# and R_PPC64_REL24_NOTOC for general dynamic relocations with value loaded + +# MC-NOT: error: invalid variant + +# READOBJ: 0xC R_PPC64_GOT_TLSGD_PCREL34 x 0x0 +# READOBJ-NEXT: 0x14 R_PPC64_TLSGD x 0x0 +# READOBJ-NEXT: 0x14 R_PPC64_REL24_NOTOC __tls_get_addr 0x0 + +GeneralDynamicValueLoad: # @GeneralDynamicValueLoad + mflr 0 + std 0, 16(1) + stdu 1, -32(1) + paddi 3, 0, x@got@tlsgd@pcrel, 1 + bl __tls_get_addr@notoc(x@tlsgd) + lwz 3, 0(3) + addi 1, 1, 32 + ld 0, 16(1) + mtlr 0 + blr