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 @@ -80,6 +80,8 @@ class PPCAsmPrinter : public AsmPrinter { protected: MapVector TOC; + // PPC32 .got2 used in PIC. + MapVector Got2; const PPCSubtarget *Subtarget = nullptr; StackMaps SM; @@ -681,8 +683,6 @@ // storage allocated in the TOC which contains the address of // 'MOSymbol'. Said TOC entry will be synthesized later. MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(MOSymbol); - const MCExpr *Exp = - MCSymbolRefExpr::create(TOCEntry, MCSymbolRefExpr::VK_None, OutContext); // AIX uses the label directly as the lwz displacement operand for // references into the toc section. The displacement value will be generated @@ -691,16 +691,19 @@ assert( TM.getCodeModel() == CodeModel::Small && "This pseudo should only be selected for 32-bit small code model."); + const MCExpr *Exp = MCSymbolRefExpr::create( + TOCEntry, MCSymbolRefExpr::VK_None, OutContext); TmpInst.getOperand(1) = MCOperand::createExpr(Exp); EmitToStreamer(*OutStreamer, TmpInst); return; } - // Create an explicit subtract expression between the local symbol and - // '.LTOC' to manifest the toc-relative offset. - const MCExpr *PB = MCSymbolRefExpr::create( - OutContext.getOrCreateSymbol(Twine(".LTOC")), OutContext); - Exp = MCBinaryExpr::createSub(Exp, PB, OutContext); + // Subtract .LTOC from the local symbol to get the r30 relative offset. The + // local symbol and .LTOC may be in different .got2 sections (due to section + // groups), such a difference is not representable. Use a constant here. + int Ordinal = + Got2.insert(std::make_pair(MOSymbol, (int)Got2.size())).first->second; + const auto *Exp = MCConstantExpr::create(Ordinal * 4 - 0x8000, OutContext); TmpInst.getOperand(1) = MCOperand::createExpr(Exp); EmitToStreamer(*OutStreamer, TmpInst); return; @@ -1397,38 +1400,48 @@ } void PPCLinuxAsmPrinter::emitEndOfAsmFile(Module &M) { - const DataLayout &DL = getDataLayout(); - - bool isPPC64 = DL.getPointerSizeInBits() == 64; - PPCTargetStreamer &TS = static_cast(*OutStreamer->getTargetStreamer()); if (!TOC.empty()) { - const char *Name = isPPC64 ? ".toc" : ".got2"; MCSectionELF *CurSection = nullptr, *Section; + // Emit PPC32 .got2 entries. If the symbol is defined in a section group, + // create .got2 in that group. The ELF spec does not allow referencing a + // discarded symbol from outside the section group. + for (const auto &It : Got2) { + const MCSymbol *Sym = It.first; + const MCSymbolELF *Group = nullptr; + if (Sym->isInSection()) + Group = cast(Sym->getSection()).getGroup(); + Section = OutStreamer->getContext().getELFSection( + ".got2", ELF::SHT_PROGBITS, + ELF::SHF_WRITE | ELF::SHF_ALLOC | (Group ? ELF::SHF_GROUP : 0), 0, + Group, MCSection::NonUniqueID, nullptr); + if (Section != CurSection) { + OutStreamer->SwitchSection(Section); + CurSection = Section; + OutStreamer->emitValueToAlignment(4); + } + OutStreamer->emitSymbolValue(Sym, 4); + } + // Emit PPC64 .toc entries. for (const auto &TOCMapPair : TOC) { const MCSymbol *const TOCEntryTarget = TOCMapPair.first; MCSymbol *const TOCEntryLabel = TOCMapPair.second; const MCSymbolELF *Group = nullptr; - if (isPPC64 && TOCEntryTarget->isInSection()) + if (TOCEntryTarget->isInSection()) Group = cast(TOCEntryTarget->getSection()).getGroup(); Section = OutStreamer->getContext().getELFSection( - Name, ELF::SHT_PROGBITS, + ".toc", ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC | (Group ? ELF::SHF_GROUP : 0), 0, Group, MCSection::NonUniqueID, nullptr); if (Section != CurSection) { OutStreamer->SwitchSection(Section); CurSection = Section; - if (!isPPC64) - OutStreamer->emitValueToAlignment(4); } OutStreamer->emitLabel(TOCEntryLabel); - if (isPPC64) - TS.emitTCEntry(*TOCEntryTarget); - else - OutStreamer->emitSymbolValue(TOCEntryTarget, 4); + TS.emitTCEntry(*TOCEntryTarget); } } diff --git a/llvm/test/CodeGen/PowerPC/indirectbr.ll b/llvm/test/CodeGen/PowerPC/indirectbr.ll --- a/llvm/test/CodeGen/PowerPC/indirectbr.ll +++ b/llvm/test/CodeGen/PowerPC/indirectbr.ll @@ -71,8 +71,8 @@ L1: ; preds = %L2, %bb2 %res.3 = phi i32 [ %phitmp, %L2 ], [ 2, %bb2 ] ; [#uses=1] -; PIC: lwz r[[R0:[0-9]+]], .LC0-.LTOC(r30) -; PIC-NEXT: lwz r[[R1:[0-9]+]], .LC2-.LTOC(r30) +; PIC: lwz r[[R0:[0-9]+]], -32768(r30) +; PIC-NEXT: lwz r[[R1:[0-9]+]], -32760(r30) ; PIC-NEXT: stw r[[R1]], 0(r[[R0]]) ; STATIC: li r[[R0:[0-9]+]], .Ltmp0@l ; STATIC-NEXT: lis r[[R1:[0-9]+]], nextaddr@ha diff --git a/llvm/test/CodeGen/PowerPC/ppc-label.ll b/llvm/test/CodeGen/PowerPC/ppc-label.ll --- a/llvm/test/CodeGen/PowerPC/ppc-label.ll +++ b/llvm/test/CodeGen/PowerPC/ppc-label.ll @@ -39,6 +39,6 @@ } -; CHECK: lwz 3, .LC0-.LTOC(30) +; CHECK: lwz 3, -32768(30) ; CHECK-NOT: li 3, .Ltmp1-.L1$pb@l -; CHECK-NOT: addis 4, 30, .Ltmp1-.L1$pb@ha \ No newline at end of file +; CHECK-NOT: addis 4, 30, .Ltmp1-.L1$pb@ha diff --git a/llvm/test/CodeGen/PowerPC/ppc-label2.ll b/llvm/test/CodeGen/PowerPC/ppc-label2.ll --- a/llvm/test/CodeGen/PowerPC/ppc-label2.ll +++ b/llvm/test/CodeGen/PowerPC/ppc-label2.ll @@ -12,10 +12,10 @@ ret i64 ptrtoint (i8* blockaddress(@foo, %__here) to i64) } -; CHECK-PIC32: lwz {{r[0-9]+}}, .LC0-.LTOC(r30) +; CHECK-PIC32: lwz {{r[0-9]+}}, -32768(r30) ; CHECK-PIC32-NOT: li {{r[0-9]+}}, .Ltmp1-.L1$pb@l ; CHECK-PIC32-NOT: addis 4, 30, .Ltmp1-.L1$pb@ha ; CHECK-STATIC32: li {{r[0-9]+}}, .Ltmp0@l ; CHECK-STATIC32-NEXT: addis {{r[0-9]+}}, {{r[0-9]+}}, .Ltmp0@ha ; CHECK-PPC64: addis r3, r2, .LC0@toc@ha -; CHECK-PPC64-NEXT: ld r3, .LC0@toc@l(r3) \ No newline at end of file +; CHECK-PPC64-NEXT: ld r3, .LC0@toc@l(r3) diff --git a/llvm/test/CodeGen/PowerPC/ppc32-pic-large.ll b/llvm/test/CodeGen/PowerPC/ppc32-pic-large.ll --- a/llvm/test/CodeGen/PowerPC/ppc32-pic-large.ll +++ b/llvm/test/CodeGen/PowerPC/ppc32-pic-large.ll @@ -42,7 +42,7 @@ ; LARGE-BSS: mflr 30 ; LARGE-BSS: lwz [[REG:[0-9]+]], [[POFF]]-[[PB]](30) ; LARGE-BSS-NEXT: add 30, [[REG]], 30 -; LARGE-BSS-DAG: lwz [[VREG:[0-9]+]], [[VREF:\.LC[0-9]+]]-.LTOC(30) +; LARGE-BSS-DAG: lwz [[VREG:[0-9]+]], -32768(30) ; LARGE-BSS-DAG: lwz {{[0-9]+}}, 0([[VREG]]) ; LARGE-BSS-DAG: stw {{[0-9]+}}, 8(1) ; LARGE-BSS: lwz 30, 24(1) @@ -54,9 +54,10 @@ ; LARGE: .section .bss.bar2,"aGw",@nobits,bar2,comdat ; LARGE: .section .got2,"aw",@progbits ; LARGE-NEXT: .p2align 2 -; LARGE-NEXT: .LC0: ; LARGE-NEXT: .long bar -; LARGE-NEXT: .LC1: +; LARGE: .section .got2,"aGw",@progbits,bar1,comdat +; LARGE-NEXT: .p2align 2 ; LARGE-NEXT: .long bar1 -; LARGE-NEXT: .LC2: +; LARGE: .section .got2,"aGw",@progbits,bar2,comdat +; LARGE-NEXT: .p2align 2 ; LARGE-NEXT: .long bar2