aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp')
-rw-r--r--contrib/llvm-project/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp222
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(),