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,6 +691,8 @@ 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; @@ -698,9 +700,9 @@ // 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); + 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 +1399,46 @@ } 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. + 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); } }