diff options
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp')
-rw-r--r-- | contrib/llvm-project/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp | 222 |
1 files changed, 194 insertions, 28 deletions
diff --git a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp index 30e96cff9e2c..a089d61616e1 100644 --- a/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -28,8 +28,9 @@ #include "TargetInfo/PowerPCTargetInfo.h" #include "llvm/ADT/MapVector.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" -#include "llvm/ADT/Triple.h" #include "llvm/ADT/Twine.h" #include "llvm/BinaryFormat/ELF.h" #include "llvm/CodeGen/AsmPrinter.h" @@ -68,6 +69,7 @@ #include "llvm/Support/Process.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Target/TargetMachine.h" +#include "llvm/TargetParser/Triple.h" #include "llvm/Transforms/Utils/ModuleUtils.h" #include <algorithm> #include <cassert> @@ -80,6 +82,17 @@ using namespace llvm::XCOFF; #define DEBUG_TYPE "asmprinter" +STATISTIC(NumTOCEntries, "Number of Total TOC Entries Emitted."); +STATISTIC(NumTOCConstPool, "Number of Constant Pool TOC Entries."); +STATISTIC(NumTOCGlobalInternal, + "Number of Internal Linkage Global TOC Entries."); +STATISTIC(NumTOCGlobalExternal, + "Number of External Linkage Global TOC Entries."); +STATISTIC(NumTOCJumpTable, "Number of Jump Table TOC Entries."); +STATISTIC(NumTOCThreadLocal, "Number of Thread Local TOC Entries."); +STATISTIC(NumTOCBlockAddress, "Number of Block Address TOC Entries."); +STATISTIC(NumTOCEHBlock, "Number of EH Block TOC Entries."); + static cl::opt<bool> EnableSSPCanaryBitInTB( "aix-ssp-tb-bit", cl::init(false), cl::desc("Enable Passing SSP Canary info in Trackback on AIX"), cl::Hidden); @@ -148,7 +161,17 @@ public: StringRef getPassName() const override { return "PowerPC Assembly Printer"; } - MCSymbol *lookUpOrCreateTOCEntry(const MCSymbol *Sym, + enum TOCEntryType { + TOCType_ConstantPool, + TOCType_GlobalExternal, + TOCType_GlobalInternal, + TOCType_JumpTable, + TOCType_ThreadLocal, + TOCType_BlockAddress, + TOCType_EHBlock + }; + + MCSymbol *lookUpOrCreateTOCEntry(const MCSymbol *Sym, TOCEntryType Type, MCSymbolRefExpr::VariantKind Kind = MCSymbolRefExpr::VariantKind::VK_None); @@ -174,6 +197,7 @@ public: void LowerSTACKMAP(StackMaps &SM, const MachineInstr &MI); void LowerPATCHPOINT(StackMaps &SM, const MachineInstr &MI); void EmitTlsCall(const MachineInstr *MI, MCSymbolRefExpr::VariantKind VK); + void EmitAIXTlsCallHelper(const MachineInstr *MI); bool runOnMachineFunction(MachineFunction &MF) override { Subtarget = &MF.getSubtarget<PPCSubtarget>(); bool Changed = AsmPrinter::runOnMachineFunction(MF); @@ -266,6 +290,8 @@ public: bool doFinalization(Module &M) override; void emitTTypeReference(const GlobalValue *GV, unsigned Encoding) override; + + void emitModuleCommandLines(Module &M) override; }; } // end anonymous namespace @@ -412,12 +438,43 @@ bool PPCAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, return false; } +static void collectTOCStats(PPCAsmPrinter::TOCEntryType Type) { + ++NumTOCEntries; + switch (Type) { + case PPCAsmPrinter::TOCType_ConstantPool: + ++NumTOCConstPool; + break; + case PPCAsmPrinter::TOCType_GlobalInternal: + ++NumTOCGlobalInternal; + break; + case PPCAsmPrinter::TOCType_GlobalExternal: + ++NumTOCGlobalExternal; + break; + case PPCAsmPrinter::TOCType_JumpTable: + ++NumTOCJumpTable; + break; + case PPCAsmPrinter::TOCType_ThreadLocal: + ++NumTOCThreadLocal; + break; + case PPCAsmPrinter::TOCType_BlockAddress: + ++NumTOCBlockAddress; + break; + case PPCAsmPrinter::TOCType_EHBlock: + ++NumTOCEHBlock; + break; + } +} + /// lookUpOrCreateTOCEntry -- Given a symbol, look up whether a TOC entry /// exists for it. If not, create one. Then return a symbol that references /// the TOC entry. MCSymbol * -PPCAsmPrinter::lookUpOrCreateTOCEntry(const MCSymbol *Sym, +PPCAsmPrinter::lookUpOrCreateTOCEntry(const MCSymbol *Sym, TOCEntryType Type, MCSymbolRefExpr::VariantKind Kind) { + // If this is a new TOC entry add statistics about it. + if (!TOC.contains({Sym, Kind})) + collectTOCStats(Type); + MCSymbol *&TOCEntry = TOC[{Sym, Kind}]; if (!TOCEntry) TOCEntry = createTempSymbol("C"); @@ -558,13 +615,26 @@ 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) { +static MCSymbol *createMCSymbolForTlsGetAddr(MCContext &Ctx, unsigned MIOpc) { + StringRef SymName = + MIOpc == PPC::GETtlsTpointer32AIX ? ".__get_tpointer" : ".__tls_get_addr"; return Ctx - .getXCOFFSection(".__tls_get_addr", SectionKind::getText(), + .getXCOFFSection(SymName, SectionKind::getText(), XCOFF::CsectProperties(XCOFF::XMC_PR, XCOFF::XTY_ER)) ->getQualNameSymbol(); } +void PPCAsmPrinter::EmitAIXTlsCallHelper(const MachineInstr *MI) { + assert(Subtarget->isAIXABI() && + "Only expecting to emit calls to get the thread pointer on AIX!"); + + MCSymbol *TlsCall = createMCSymbolForTlsGetAddr(OutContext, MI->getOpcode()); + const MCExpr *TlsRef = + MCSymbolRefExpr::create(TlsCall, MCSymbolRefExpr::VK_None, OutContext); + EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::BLA).addExpr(TlsRef)); + return; +} + /// EmitTlsCall -- Given a GETtls[ld]ADDR[32] instruction, print a /// call to __tls_get_addr to the current output stream. void PPCAsmPrinter::EmitTlsCall(const MachineInstr *MI, @@ -599,10 +669,7 @@ void PPCAsmPrinter::EmitTlsCall(const MachineInstr *MI, assert(MI->getOperand(2).isReg() && MI->getOperand(2).getReg() == VarOffsetReg && "GETtls[ld]ADDR[32] must read GPR4"); - MCSymbol *TlsGetAddr = createMCSymbolForTlsGetAddr(OutContext); - const MCExpr *TlsRef = MCSymbolRefExpr::create( - TlsGetAddr, MCSymbolRefExpr::VK_None, OutContext); - EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::BLA).addExpr(TlsRef)); + EmitAIXTlsCallHelper(MI); return; } @@ -648,6 +715,48 @@ static MCSymbol *getMCSymbolForTOCPseudoMO(const MachineOperand &MO, } } +static bool hasTLSFlag(const MachineOperand &MO) { + unsigned Flags = MO.getTargetFlags(); + if (Flags & PPCII::MO_TLSGD_FLAG || Flags & PPCII::MO_TPREL_FLAG || + Flags & PPCII::MO_TLSLD_FLAG || Flags & PPCII::MO_TLSGDM_FLAG) + return true; + + if (Flags == PPCII::MO_TPREL_LO || Flags == PPCII::MO_TPREL_HA || + Flags == PPCII::MO_DTPREL_LO || Flags == PPCII::MO_TLSLD_LO || + Flags == PPCII::MO_TLS) + return true; + + return false; +} + +static PPCAsmPrinter::TOCEntryType +getTOCEntryTypeForMO(const MachineOperand &MO) { + // Use the target flags to determine if this MO is Thread Local. + // If we don't do this it comes out as Global. + if (hasTLSFlag(MO)) + return PPCAsmPrinter::TOCType_ThreadLocal; + + switch (MO.getType()) { + case MachineOperand::MO_GlobalAddress: { + const GlobalValue *GlobalV = MO.getGlobal(); + GlobalValue::LinkageTypes Linkage = GlobalV->getLinkage(); + if (Linkage == GlobalValue::ExternalLinkage || + Linkage == GlobalValue::AvailableExternallyLinkage || + Linkage == GlobalValue::ExternalWeakLinkage) + return PPCAsmPrinter::TOCType_GlobalExternal; + + return PPCAsmPrinter::TOCType_GlobalInternal; + } + case MachineOperand::MO_ConstantPoolIndex: + return PPCAsmPrinter::TOCType_ConstantPool; + case MachineOperand::MO_JumpTableIndex: + return PPCAsmPrinter::TOCType_JumpTable; + case MachineOperand::MO_BlockAddress: + return PPCAsmPrinter::TOCType_BlockAddress; + default: + llvm_unreachable("Unexpected operand type to get TOC type."); + } +} /// EmitInstruction -- Print out a single PowerPC MI in Darwin syntax to /// the current output stream. /// @@ -718,6 +827,18 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) { return Expr; }; auto GetVKForMO = [&](const MachineOperand &MO) { + // For TLS local-exec accesses on AIX, we have one TOC entry for the symbol + // (with the variable offset), which is differentiated by MO_TPREL_FLAG. + if (MO.getTargetFlags() & PPCII::MO_TPREL_FLAG) { + // TODO: Update the query and the comment above to add a check for initial + // exec when this TLS model is supported on AIX in the future, as both + // local-exec and initial-exec can use MO_TPREL_FLAG. + assert(MO.isGlobal() && "Only expecting a global MachineOperand here!\n"); + TLSModel::Model Model = TM.getTLSModel(MO.getGlobal()); + if (Model == TLSModel::LocalExec) + return MCSymbolRefExpr::VariantKind::VK_PPC_AIX_TLSLE; + llvm_unreachable("Only expecting local-exec accesses!"); + } // For GD TLS access on AIX, we have two TOC entries for the symbol (one for // the variable offset and the other for the region handle). They are // differentiated by MO_TLSGD_FLAG and MO_TLSGDM_FLAG. @@ -865,7 +986,8 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) { // Otherwise, use the TOC. 'TOCEntry' is a label used to reference the // storage allocated in the TOC which contains the address of // 'MOSymbol'. Said TOC entry will be synthesized later. - MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(MOSymbol, VK); + MCSymbol *TOCEntry = + lookUpOrCreateTOCEntry(MOSymbol, getTOCEntryTypeForMO(MO), VK); const MCExpr *Exp = MCSymbolRefExpr::create(TOCEntry, MCSymbolRefExpr::VK_None, OutContext); @@ -942,7 +1064,8 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) { // Map the machine operand to its corresponding MCSymbol, then map the // global address operand to be a reference to the TOC entry we will // synthesize later. - MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(MOSymbol, VK); + MCSymbol *TOCEntry = + lookUpOrCreateTOCEntry(MOSymbol, getTOCEntryTypeForMO(MO), VK); MCSymbolRefExpr::VariantKind VKExpr = IsAIX ? MCSymbolRefExpr::VK_None : MCSymbolRefExpr::VK_PPC_TOC; @@ -980,7 +1103,8 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) { // to the TOC entry we will synthesize later. 'TOCEntry' is a label used to // reference the storage allocated in the TOC which contains the address of // 'MOSymbol'. - MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(MOSymbol, VK); + MCSymbol *TOCEntry = + lookUpOrCreateTOCEntry(MOSymbol, getTOCEntryTypeForMO(MO), VK); const MCExpr *Exp = MCSymbolRefExpr::create(TOCEntry, MCSymbolRefExpr::VK_PPC_U, OutContext); @@ -1012,7 +1136,8 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) { // to the TOC entry we will synthesize later. 'TOCEntry' is a label used to // reference the storage allocated in the TOC which contains the address of // 'MOSymbol'. - MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(MOSymbol, VK); + MCSymbol *TOCEntry = + lookUpOrCreateTOCEntry(MOSymbol, getTOCEntryTypeForMO(MO), VK); const MCExpr *Exp = MCSymbolRefExpr::create(TOCEntry, MCSymbolRefExpr::VK_PPC_L, OutContext); @@ -1042,7 +1167,7 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) { MO.isGlobal() && Subtarget->isGVIndirectSymbol(MO.getGlobal()); if (GlobalToc || MO.isJTI() || MO.isBlockAddress() || (MO.isCPI() && TM.getCodeModel() == CodeModel::Large)) - MOSymbol = lookUpOrCreateTOCEntry(MOSymbol, VK); + MOSymbol = lookUpOrCreateTOCEntry(MOSymbol, getTOCEntryTypeForMO(MO), VK); VK = IsAIX ? MCSymbolRefExpr::VK_PPC_U : MCSymbolRefExpr::VK_PPC_TOC_HA; @@ -1084,7 +1209,7 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) { MCSymbolRefExpr::VariantKind VK = GetVKForMO(MO); if (!MO.isCPI() || TM.getCodeModel() == CodeModel::Large) - MOSymbol = lookUpOrCreateTOCEntry(MOSymbol, VK); + MOSymbol = lookUpOrCreateTOCEntry(MOSymbol, getTOCEntryTypeForMO(MO), VK); VK = IsAIX ? MCSymbolRefExpr::VK_PPC_L : MCSymbolRefExpr::VK_PPC_TOC_LO; const MCExpr *Exp = @@ -1246,6 +1371,12 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) { EmitTlsCall(MI, MCSymbolRefExpr::VK_PPC_TLSGD); return; } + case PPC::GETtlsTpointer32AIX: { + // Transform: %r3 = GETtlsTpointer32AIX + // Into: BLA .__get_tpointer() + EmitAIXTlsCallHelper(MI); + return; + } case PPC::ADDIStlsldHA: { // Transform: %xd = ADDIStlsldHA %x2, @sym // Into: %xd = ADDIS8 %x2, sym@got@tlsld@ha @@ -2096,8 +2227,9 @@ void PPCAIXAsmPrinter::emitTracebackTable() { // Set the 5th byte of mandatory field. uint32_t SecondHalfOfMandatoryField = 0; - // Always store back chain. - SecondHalfOfMandatoryField |= TracebackTable::IsBackChainStoredMask; + SecondHalfOfMandatoryField |= MF->getFrameInfo().getStackSize() + ? TracebackTable::IsBackChainStoredMask + : 0; uint32_t FPRSaved = 0; for (unsigned Reg = PPC::F14; Reg <= PPC::F31; ++Reg) { @@ -2311,7 +2443,7 @@ void PPCAIXAsmPrinter::emitTracebackTable() { auto &Ctx = OutStreamer->getContext(); MCSymbol *EHInfoSym = TargetLoweringObjectFileXCOFF::getEHInfoTableSymbol(MF); - MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(EHInfoSym); + MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(EHInfoSym, TOCType_EHBlock); const MCSymbol *TOCBaseSym = cast<MCSectionXCOFF>(getObjFileLowering().getTOCBaseSection()) ->getQualNameSymbol(); @@ -2516,16 +2648,22 @@ void PPCAIXAsmPrinter::emitPGORefs() { OutStreamer->switchSection(CntsSection); if (OutContext.hasXCOFFSection( "__llvm_prf_data", - XCOFF::CsectProperties(XCOFF::XMC_RW, XCOFF::XTY_SD))) - OutStreamer->emitXCOFFRefDirective("__llvm_prf_data[RW]"); + XCOFF::CsectProperties(XCOFF::XMC_RW, XCOFF::XTY_SD))) { + MCSymbol *S = OutContext.getOrCreateSymbol("__llvm_prf_data[RW]"); + OutStreamer->emitXCOFFRefDirective(S); + } if (OutContext.hasXCOFFSection( "__llvm_prf_names", - XCOFF::CsectProperties(XCOFF::XMC_RO, XCOFF::XTY_SD))) - OutStreamer->emitXCOFFRefDirective("__llvm_prf_names[RO]"); + XCOFF::CsectProperties(XCOFF::XMC_RO, XCOFF::XTY_SD))) { + MCSymbol *S = OutContext.getOrCreateSymbol("__llvm_prf_names[RO]"); + OutStreamer->emitXCOFFRefDirective(S); + } if (OutContext.hasXCOFFSection( "__llvm_prf_vnds", - XCOFF::CsectProperties(XCOFF::XMC_RW, XCOFF::XTY_SD))) - OutStreamer->emitXCOFFRefDirective("__llvm_prf_vnds[RW]"); + XCOFF::CsectProperties(XCOFF::XMC_RW, XCOFF::XTY_SD))) { + MCSymbol *S = OutContext.getOrCreateSymbol("__llvm_prf_vnds[RW]"); + OutStreamer->emitXCOFFRefDirective(S); + } } } @@ -2658,11 +2796,13 @@ void PPCAIXAsmPrinter::emitInstruction(const MachineInstr *MI) { MMI->hasDebugInfo()); break; } + case PPC::GETtlsTpointer32AIX: case PPC::GETtlsADDR64AIX: case PPC::GETtlsADDR32AIX: { - // The reference to .__tls_get_addr is unknown to the assembler - // so we need to emit an external symbol reference. - MCSymbol *TlsGetAddr = createMCSymbolForTlsGetAddr(OutContext); + // A reference to .__tls_get_addr/.__get_tpointer is unknown to the + // assembler so we need to emit an external symbol reference. + MCSymbol *TlsGetAddr = + createMCSymbolForTlsGetAddr(OutContext, MI->getOpcode()); ExtSymSDNodeSymbols.insert(TlsGetAddr); break; } @@ -2785,8 +2925,14 @@ void PPCAIXAsmPrinter::emitXXStructorList(const DataLayout &DL, void PPCAIXAsmPrinter::emitTTypeReference(const GlobalValue *GV, unsigned Encoding) { if (GV) { + TOCEntryType GlobalType = TOCType_GlobalInternal; + GlobalValue::LinkageTypes Linkage = GV->getLinkage(); + if (Linkage == GlobalValue::ExternalLinkage || + Linkage == GlobalValue::AvailableExternallyLinkage || + Linkage == GlobalValue::ExternalWeakLinkage) + GlobalType = TOCType_GlobalExternal; MCSymbol *TypeInfoSym = TM.getSymbol(GV); - MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(TypeInfoSym); + MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(TypeInfoSym, GlobalType); const MCSymbol *TOCBaseSym = cast<MCSectionXCOFF>(getObjFileLowering().getTOCBaseSection()) ->getQualNameSymbol(); @@ -2810,6 +2956,26 @@ createPPCAsmPrinterPass(TargetMachine &tm, return new PPCLinuxAsmPrinter(tm, std::move(Streamer)); } +void PPCAIXAsmPrinter::emitModuleCommandLines(Module &M) { + const NamedMDNode *NMD = M.getNamedMetadata("llvm.commandline"); + if (!NMD || !NMD->getNumOperands()) + return; + + std::string S; + raw_string_ostream RSOS(S); + for (unsigned i = 0, e = NMD->getNumOperands(); i != e; ++i) { + const MDNode *N = NMD->getOperand(i); + assert(N->getNumOperands() == 1 && + "llvm.commandline metadata entry can have only one operand"); + const MDString *MDS = cast<MDString>(N->getOperand(0)); + // Add "@(#)" to support retrieving the command line information with the + // AIX "what" command + RSOS << "@(#)opt " << MDS->getString() << "\n"; + RSOS.write('\0'); + } + OutStreamer->emitXCOFFCInfoSym(".GCC.command.line", RSOS.str()); +} + // Force static initialization. extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializePowerPCAsmPrinter() { TargetRegistry::RegisterAsmPrinter(getThePPC32Target(), |