aboutsummaryrefslogtreecommitdiff
path: root/lib/Target/PowerPC/PPCAsmPrinter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/PowerPC/PPCAsmPrinter.cpp')
-rw-r--r--lib/Target/PowerPC/PPCAsmPrinter.cpp482
1 files changed, 331 insertions, 151 deletions
diff --git a/lib/Target/PowerPC/PPCAsmPrinter.cpp b/lib/Target/PowerPC/PPCAsmPrinter.cpp
index bd87ce06b4fb..66236b72a1a3 100644
--- a/lib/Target/PowerPC/PPCAsmPrinter.cpp
+++ b/lib/Target/PowerPC/PPCAsmPrinter.cpp
@@ -51,9 +51,11 @@
#include "llvm/MC/MCInstBuilder.h"
#include "llvm/MC/MCSectionELF.h"
#include "llvm/MC/MCSectionMachO.h"
+#include "llvm/MC/MCSectionXCOFF.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MCSymbolELF.h"
+#include "llvm/MC/MCSymbolXCOFF.h"
#include "llvm/MC/SectionKind.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CodeGen.h"
@@ -76,7 +78,7 @@ namespace {
class PPCAsmPrinter : public AsmPrinter {
protected:
- MapVector<MCSymbol *, MCSymbol *> TOC;
+ MapVector<const MCSymbol *, MCSymbol *> TOC;
const PPCSubtarget *Subtarget;
StackMaps SM;
@@ -87,7 +89,7 @@ public:
StringRef getPassName() const override { return "PowerPC Assembly Printer"; }
- MCSymbol *lookUpOrCreateTOCEntry(MCSymbol *Sym);
+ MCSymbol *lookUpOrCreateTOCEntry(const MCSymbol *Sym);
bool doInitialization(Module &M) override {
if (!TOC.empty())
@@ -164,6 +166,14 @@ public:
: PPCAsmPrinter(TM, std::move(Streamer)) {}
StringRef getPassName() const override { return "AIX PPC Assembly Printer"; }
+
+ void SetupMachineFunction(MachineFunction &MF) override;
+
+ void EmitGlobalVariable(const GlobalVariable *GV) override;
+
+ void EmitFunctionDescriptor() override;
+
+ void EmitEndOfAsmFile(Module &) override;
};
} // end anonymous namespace
@@ -265,7 +275,7 @@ bool PPCAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
return true;
// This operand uses VSX numbering.
// If the operand is a VMX register, convert it to a VSX register.
- unsigned Reg = MI->getOperand(OpNo).getReg();
+ Register Reg = MI->getOperand(OpNo).getReg();
if (PPCInstrInfo::isVRRegister(Reg))
Reg = PPC::VSX32 + (Reg - PPC::V0);
else if (PPCInstrInfo::isVFRegister(Reg))
@@ -328,7 +338,7 @@ bool PPCAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
/// 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(MCSymbol *Sym) {
+MCSymbol *PPCAsmPrinter::lookUpOrCreateTOCEntry(const MCSymbol *Sym) {
MCSymbol *&TOCEntry = TOC[Sym];
if (!TOCEntry)
TOCEntry = createTempSymbol("C");
@@ -378,7 +388,7 @@ void PPCAsmPrinter::LowerPATCHPOINT(StackMaps &SM, const MachineInstr &MI) {
if (CallTarget) {
assert((CallTarget & 0xFFFFFFFFFFFF) == CallTarget &&
"High 16 bits of call target should be zero.");
- unsigned ScratchReg = MI.getOperand(Opers.getNextScratchIdx()).getReg();
+ Register ScratchReg = MI.getOperand(Opers.getNextScratchIdx()).getReg();
EncodedBytes = 0;
// Materialize the jump address:
EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LI8)
@@ -502,13 +512,32 @@ void PPCAsmPrinter::EmitTlsCall(const MachineInstr *MI,
.addExpr(SymVar));
}
+/// Map a machine operand for a TOC pseudo-machine instruction to its
+/// corresponding MCSymbol.
+static MCSymbol *getMCSymbolForTOCPseudoMO(const MachineOperand &MO,
+ AsmPrinter &AP) {
+ switch (MO.getType()) {
+ case MachineOperand::MO_GlobalAddress:
+ return AP.getSymbol(MO.getGlobal());
+ case MachineOperand::MO_ConstantPoolIndex:
+ return AP.GetCPISymbol(MO.getIndex());
+ case MachineOperand::MO_JumpTableIndex:
+ return AP.GetJTISymbol(MO.getIndex());
+ case MachineOperand::MO_BlockAddress:
+ return AP.GetBlockAddressSymbol(MO.getBlockAddress());
+ default:
+ llvm_unreachable("Unexpected operand type to get symbol.");
+ }
+}
+
/// EmitInstruction -- Print out a single PowerPC MI in Darwin syntax to
/// the current output stream.
///
void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
MCInst TmpInst;
- bool isPPC64 = Subtarget->isPPC64();
- bool isDarwin = TM.getTargetTriple().isOSDarwin();
+ const bool IsDarwin = TM.getTargetTriple().isOSDarwin();
+ const bool IsPPC64 = Subtarget->isPPC64();
+ const bool IsAIX = Subtarget->isAIXABI();
const Module *M = MF->getFunction().getParent();
PICLevel::Level PL = M->getPICLevel();
@@ -517,7 +546,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
if (!MI->isInlineAsm()) {
for (const MachineOperand &MO: MI->operands()) {
if (MO.isReg()) {
- unsigned Reg = MO.getReg();
+ Register Reg = MO.getReg();
if (Subtarget->hasSPE()) {
if (PPC::F4RCRegClass.contains(Reg) ||
PPC::F8RCRegClass.contains(Reg) ||
@@ -595,7 +624,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
// addis r30, r30, {.LTOC,_GLOBAL_OFFSET_TABLE} - .L0$pb@ha
// addi r30, r30, {.LTOC,_GLOBAL_OFFSET_TABLE} - .L0$pb@l
// Get the offset from the GOT Base Register to the GOT
- LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, isDarwin);
+ LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, IsDarwin);
if (Subtarget->isSecurePlt() && isPositionIndependent() ) {
unsigned PICR = TmpInst.getOperand(0).getReg();
MCSymbol *BaseSymbol = OutContext.getOrCreateSymbol(
@@ -646,43 +675,57 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
}
}
case PPC::LWZtoc: {
- // Transform %r3 = LWZtoc @min1, %r2
- LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, isDarwin);
+ assert(!IsDarwin && "TOC is an ELF/XCOFF construct.");
+
+ // Transform %rN = LWZtoc @op1, %r2
+ LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, IsDarwin);
- // Change the opcode to LWZ, and the global address operand to be a
- // reference to the GOT entry we will synthesize later.
+ // Change the opcode to LWZ.
TmpInst.setOpcode(PPC::LWZ);
+
const MachineOperand &MO = MI->getOperand(1);
+ assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) &&
+ "Invalid operand for LWZtoc.");
- // Map symbol -> label of TOC entry
- assert(MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress());
- MCSymbol *MOSymbol = nullptr;
- if (MO.isGlobal())
- MOSymbol = getSymbol(MO.getGlobal());
- else if (MO.isCPI())
- MOSymbol = GetCPISymbol(MO.getIndex());
- else if (MO.isJTI())
- MOSymbol = GetJTISymbol(MO.getIndex());
- else if (MO.isBlockAddress())
- MOSymbol = GetBlockAddressSymbol(MO.getBlockAddress());
-
- if (PL == PICLevel::SmallPIC) {
+ // Map the operand to its corresponding MCSymbol.
+ const MCSymbol *const MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);
+
+ // Create a reference to the GOT entry for the symbol. The GOT entry will be
+ // synthesized later.
+ if (PL == PICLevel::SmallPIC && !IsAIX) {
const MCExpr *Exp =
MCSymbolRefExpr::create(MOSymbol, MCSymbolRefExpr::VK_GOT,
OutContext);
TmpInst.getOperand(1) = MCOperand::createExpr(Exp);
- } else {
- MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(MOSymbol);
+ EmitToStreamer(*OutStreamer, TmpInst);
+ return;
+ }
- const MCExpr *Exp =
- MCSymbolRefExpr::create(TOCEntry, MCSymbolRefExpr::VK_None,
- OutContext);
- const MCExpr *PB =
- MCSymbolRefExpr::create(OutContext.getOrCreateSymbol(Twine(".LTOC")),
- OutContext);
- Exp = MCBinaryExpr::createSub(Exp, PB, OutContext);
+ // 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);
+ 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
+ // relative to the toc-base.
+ if (IsAIX) {
+ assert(
+ TM.getCodeModel() == CodeModel::Small &&
+ "This pseudo should only be selected for 32-bit small code model.");
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);
+ TmpInst.getOperand(1) = MCOperand::createExpr(Exp);
EmitToStreamer(*OutStreamer, TmpInst);
return;
}
@@ -690,72 +733,121 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
case PPC::LDtocCPT:
case PPC::LDtocBA:
case PPC::LDtoc: {
+ assert(!IsDarwin && "TOC is an ELF/XCOFF construct");
+
// Transform %x3 = LDtoc @min1, %x2
- LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, isDarwin);
+ LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, IsDarwin);
- // Change the opcode to LD, and the global address operand to be a
- // reference to the TOC entry we will synthesize later.
+ // Change the opcode to LD.
TmpInst.setOpcode(PPC::LD);
+
const MachineOperand &MO = MI->getOperand(1);
+ assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) &&
+ "Invalid operand!");
+
+ // 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(getMCSymbolForTOCPseudoMO(MO, *this));
+
+ const MCSymbolRefExpr::VariantKind VK =
+ IsAIX ? MCSymbolRefExpr::VK_None : MCSymbolRefExpr::VK_PPC_TOC;
+ const MCExpr *Exp =
+ MCSymbolRefExpr::create(TOCEntry, VK, OutContext);
+ TmpInst.getOperand(1) = MCOperand::createExpr(Exp);
+ EmitToStreamer(*OutStreamer, TmpInst);
+ return;
+ }
+ case PPC::ADDIStocHA: {
+ assert((IsAIX && !IsPPC64 && TM.getCodeModel() == CodeModel::Large) &&
+ "This pseudo should only be selected for 32-bit large code model on"
+ " AIX.");
+
+ // Transform %rd = ADDIStocHA %rA, @sym(%r2)
+ LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, IsDarwin);
- // Map symbol -> label of TOC entry
- assert(MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress());
- MCSymbol *MOSymbol = nullptr;
- if (MO.isGlobal())
- MOSymbol = getSymbol(MO.getGlobal());
- else if (MO.isCPI())
- MOSymbol = GetCPISymbol(MO.getIndex());
- else if (MO.isJTI())
- MOSymbol = GetJTISymbol(MO.getIndex());
- else if (MO.isBlockAddress())
- MOSymbol = GetBlockAddressSymbol(MO.getBlockAddress());
+ // Change the opcode to ADDIS.
+ TmpInst.setOpcode(PPC::ADDIS);
+ const MachineOperand &MO = MI->getOperand(2);
+ assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) &&
+ "Invalid operand for ADDIStocHA.");
+
+ // Map the machine operand to its corresponding MCSymbol.
+ MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);
+
+ // Always use TOC on AIX. Map the global address operand to be a reference
+ // 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);
+ const MCExpr *Exp = MCSymbolRefExpr::create(TOCEntry,
+ MCSymbolRefExpr::VK_PPC_U,
+ OutContext);
+ TmpInst.getOperand(2) = MCOperand::createExpr(Exp);
+ EmitToStreamer(*OutStreamer, TmpInst);
+ return;
+ }
+ case PPC::LWZtocL: {
+ assert(IsAIX && !IsPPC64 && TM.getCodeModel() == CodeModel::Large &&
+ "This pseudo should only be selected for 32-bit large code model on"
+ " AIX.");
- const MCExpr *Exp =
- MCSymbolRefExpr::create(TOCEntry, MCSymbolRefExpr::VK_PPC_TOC,
- OutContext);
+ // Transform %rd = LWZtocL @sym, %rs.
+ LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, IsDarwin);
+
+ // Change the opcode to lwz.
+ TmpInst.setOpcode(PPC::LWZ);
+
+ const MachineOperand &MO = MI->getOperand(1);
+ assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) &&
+ "Invalid operand for LWZtocL.");
+
+ // Map the machine operand to its corresponding MCSymbol.
+ MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);
+
+ // Always use TOC on AIX. Map the global address operand to be a reference
+ // 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);
+ const MCExpr *Exp = MCSymbolRefExpr::create(TOCEntry,
+ MCSymbolRefExpr::VK_PPC_L,
+ OutContext);
TmpInst.getOperand(1) = MCOperand::createExpr(Exp);
EmitToStreamer(*OutStreamer, TmpInst);
return;
}
+ case PPC::ADDIStocHA8: {
+ assert(!IsDarwin && "TOC is an ELF/XCOFF construct");
- case PPC::ADDIStocHA: {
- // Transform %xd = ADDIStocHA %x2, @sym
- LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, isDarwin);
+ // Transform %xd = ADDIStocHA8 %x2, @sym
+ LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, IsDarwin);
- // Change the opcode to ADDIS8. If the global address is external, has
- // common linkage, is a non-local function address, or is a jump table
- // address, then generate a TOC entry and reference that. Otherwise
- // reference the symbol directly.
+ // Change the opcode to ADDIS8. If the global address is the address of
+ // an external symbol, is a jump table address, is a block address, or is a
+ // constant pool index with large code model enabled, then generate a TOC
+ // entry and reference that. Otherwise, reference the symbol directly.
TmpInst.setOpcode(PPC::ADDIS8);
+
const MachineOperand &MO = MI->getOperand(2);
- assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() ||
- MO.isBlockAddress()) &&
- "Invalid operand for ADDIStocHA!");
- MCSymbol *MOSymbol = nullptr;
- bool GlobalToc = false;
-
- if (MO.isGlobal()) {
- const GlobalValue *GV = MO.getGlobal();
- MOSymbol = getSymbol(GV);
- unsigned char GVFlags = Subtarget->classifyGlobalReference(GV);
- GlobalToc = (GVFlags & PPCII::MO_NLP_FLAG);
- } else if (MO.isCPI()) {
- MOSymbol = GetCPISymbol(MO.getIndex());
- } else if (MO.isJTI()) {
- MOSymbol = GetJTISymbol(MO.getIndex());
- } else if (MO.isBlockAddress()) {
- MOSymbol = GetBlockAddressSymbol(MO.getBlockAddress());
- }
+ assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) &&
+ "Invalid operand for ADDIStocHA8!");
+
+ const MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);
+ const bool GlobalToc =
+ MO.isGlobal() && Subtarget->isGVIndirectSymbol(MO.getGlobal());
if (GlobalToc || MO.isJTI() || MO.isBlockAddress() ||
- TM.getCodeModel() == CodeModel::Large)
+ (MO.isCPI() && TM.getCodeModel() == CodeModel::Large))
MOSymbol = lookUpOrCreateTOCEntry(MOSymbol);
+ const MCSymbolRefExpr::VariantKind VK =
+ IsAIX ? MCSymbolRefExpr::VK_PPC_U : MCSymbolRefExpr::VK_PPC_TOC_HA;
+
const MCExpr *Exp =
- MCSymbolRefExpr::create(MOSymbol, MCSymbolRefExpr::VK_PPC_TOC_HA,
- OutContext);
+ MCSymbolRefExpr::create(MOSymbol, VK, OutContext);
if (!MO.isJTI() && MO.getOffset())
Exp = MCBinaryExpr::createAdd(Exp,
@@ -768,73 +860,59 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
return;
}
case PPC::LDtocL: {
+ assert(!IsDarwin && "TOC is an ELF/XCOFF construct");
+
// Transform %xd = LDtocL @sym, %xs
- LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, isDarwin);
+ LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, IsDarwin);
- // Change the opcode to LD. If the global address is external, has
- // common linkage, or is a jump table address, then reference the
- // associated TOC entry. Otherwise reference the symbol directly.
+ // Change the opcode to LD. If the global address is the address of
+ // an external symbol, is a jump table address, is a block address, or is
+ // a constant pool index with large code model enabled, then generate a
+ // TOC entry and reference that. Otherwise, reference the symbol directly.
TmpInst.setOpcode(PPC::LD);
+
const MachineOperand &MO = MI->getOperand(1);
assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() ||
MO.isBlockAddress()) &&
"Invalid operand for LDtocL!");
- MCSymbol *MOSymbol = nullptr;
- if (MO.isJTI())
- MOSymbol = lookUpOrCreateTOCEntry(GetJTISymbol(MO.getIndex()));
- else if (MO.isBlockAddress()) {
- MOSymbol = GetBlockAddressSymbol(MO.getBlockAddress());
- MOSymbol = lookUpOrCreateTOCEntry(MOSymbol);
- }
- else if (MO.isCPI()) {
- MOSymbol = GetCPISymbol(MO.getIndex());
- if (TM.getCodeModel() == CodeModel::Large)
- MOSymbol = lookUpOrCreateTOCEntry(MOSymbol);
- }
- else if (MO.isGlobal()) {
- const GlobalValue *GV = MO.getGlobal();
- MOSymbol = getSymbol(GV);
- LLVM_DEBUG(
- unsigned char GVFlags = Subtarget->classifyGlobalReference(GV);
- assert((GVFlags & PPCII::MO_NLP_FLAG) &&
- "LDtocL used on symbol that could be accessed directly is "
- "invalid. Must match ADDIStocHA."));
+ LLVM_DEBUG(assert(
+ (!MO.isGlobal() || Subtarget->isGVIndirectSymbol(MO.getGlobal())) &&
+ "LDtocL used on symbol that could be accessed directly is "
+ "invalid. Must match ADDIStocHA8."));
+
+ const MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);
+
+ if (!MO.isCPI() || TM.getCodeModel() == CodeModel::Large)
MOSymbol = lookUpOrCreateTOCEntry(MOSymbol);
- }
+ const MCSymbolRefExpr::VariantKind VK =
+ IsAIX ? MCSymbolRefExpr::VK_PPC_L : MCSymbolRefExpr::VK_PPC_TOC_LO;
const MCExpr *Exp =
- MCSymbolRefExpr::create(MOSymbol, MCSymbolRefExpr::VK_PPC_TOC_LO,
- OutContext);
+ MCSymbolRefExpr::create(MOSymbol, VK, OutContext);
TmpInst.getOperand(1) = MCOperand::createExpr(Exp);
EmitToStreamer(*OutStreamer, TmpInst);
return;
}
case PPC::ADDItocL: {
// Transform %xd = ADDItocL %xs, @sym
- LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, isDarwin);
+ LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, IsDarwin);
- // Change the opcode to ADDI8. If the global address is external, then
- // generate a TOC entry and reference that. Otherwise reference the
+ // Change the opcode to ADDI8. If the global address is external, then
+ // generate a TOC entry and reference that. Otherwise, reference the
// symbol directly.
TmpInst.setOpcode(PPC::ADDI8);
+
const MachineOperand &MO = MI->getOperand(2);
- assert((MO.isGlobal() || MO.isCPI()) && "Invalid operand for ADDItocL");
- MCSymbol *MOSymbol = nullptr;
-
- if (MO.isGlobal()) {
- const GlobalValue *GV = MO.getGlobal();
- LLVM_DEBUG(unsigned char GVFlags = Subtarget->classifyGlobalReference(GV);
- assert(!(GVFlags & PPCII::MO_NLP_FLAG) &&
- "Interposable definitions must use indirect access."));
- MOSymbol = getSymbol(GV);
- } else if (MO.isCPI()) {
- MOSymbol = GetCPISymbol(MO.getIndex());
- }
+ assert((MO.isGlobal() || MO.isCPI()) && "Invalid operand for ADDItocL.");
+
+ LLVM_DEBUG(assert(
+ !(MO.isGlobal() && Subtarget->isGVIndirectSymbol(MO.getGlobal())) &&
+ "Interposable definitions must use indirect access."));
const MCExpr *Exp =
- MCSymbolRefExpr::create(MOSymbol, MCSymbolRefExpr::VK_PPC_TOC_LO,
- OutContext);
+ MCSymbolRefExpr::create(getMCSymbolForTOCPseudoMO(MO, *this),
+ MCSymbolRefExpr::VK_PPC_TOC_LO, OutContext);
TmpInst.getOperand(2) = MCOperand::createExpr(Exp);
EmitToStreamer(*OutStreamer, TmpInst);
return;
@@ -842,13 +920,13 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
case PPC::ADDISgotTprelHA: {
// Transform: %xd = ADDISgotTprelHA %x2, @sym
// Into: %xd = ADDIS8 %x2, sym@got@tlsgd@ha
- assert(Subtarget->isPPC64() && "Not supported for 32-bit PowerPC");
+ assert(IsPPC64 && "Not supported for 32-bit PowerPC");
const MachineOperand &MO = MI->getOperand(2);
const GlobalValue *GValue = MO.getGlobal();
MCSymbol *MOSymbol = getSymbol(GValue);
const MCExpr *SymGotTprel =
- MCSymbolRefExpr::create(MOSymbol, MCSymbolRefExpr::VK_PPC_GOT_TPREL_HA,
- OutContext);
+ MCSymbolRefExpr::create(MOSymbol, MCSymbolRefExpr::VK_PPC_GOT_TPREL_HA,
+ OutContext);
EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDIS8)
.addReg(MI->getOperand(0).getReg())
.addReg(MI->getOperand(1).getReg())
@@ -858,16 +936,17 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
case PPC::LDgotTprelL:
case PPC::LDgotTprelL32: {
// Transform %xd = LDgotTprelL @sym, %xs
- LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, isDarwin);
+ LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, IsDarwin);
// Change the opcode to LD.
- TmpInst.setOpcode(isPPC64 ? PPC::LD : PPC::LWZ);
+ TmpInst.setOpcode(IsPPC64 ? PPC::LD : PPC::LWZ);
const MachineOperand &MO = MI->getOperand(1);
const GlobalValue *GValue = MO.getGlobal();
MCSymbol *MOSymbol = getSymbol(GValue);
- const MCExpr *Exp =
- MCSymbolRefExpr::create(MOSymbol, MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO,
- OutContext);
+ const MCExpr *Exp = MCSymbolRefExpr::create(
+ MOSymbol, IsPPC64 ? MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO
+ : MCSymbolRefExpr::VK_PPC_GOT_TPREL,
+ OutContext);
TmpInst.getOperand(1) = MCOperand::createExpr(Exp);
EmitToStreamer(*OutStreamer, TmpInst);
return;
@@ -920,7 +999,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
case PPC::ADDIStlsgdHA: {
// Transform: %xd = ADDIStlsgdHA %x2, @sym
// Into: %xd = ADDIS8 %x2, sym@got@tlsgd@ha
- assert(Subtarget->isPPC64() && "Not supported for 32-bit PowerPC");
+ assert(IsPPC64 && "Not supported for 32-bit PowerPC");
const MachineOperand &MO = MI->getOperand(2);
const GlobalValue *GValue = MO.getGlobal();
MCSymbol *MOSymbol = getSymbol(GValue);
@@ -943,11 +1022,11 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
const GlobalValue *GValue = MO.getGlobal();
MCSymbol *MOSymbol = getSymbol(GValue);
const MCExpr *SymGotTlsGD = MCSymbolRefExpr::create(
- MOSymbol, Subtarget->isPPC64() ? MCSymbolRefExpr::VK_PPC_GOT_TLSGD_LO
- : MCSymbolRefExpr::VK_PPC_GOT_TLSGD,
+ MOSymbol, IsPPC64 ? MCSymbolRefExpr::VK_PPC_GOT_TLSGD_LO
+ : MCSymbolRefExpr::VK_PPC_GOT_TLSGD,
OutContext);
EmitToStreamer(*OutStreamer,
- MCInstBuilder(Subtarget->isPPC64() ? PPC::ADDI8 : PPC::ADDI)
+ MCInstBuilder(IsPPC64 ? PPC::ADDI8 : PPC::ADDI)
.addReg(MI->getOperand(0).getReg())
.addReg(MI->getOperand(1).getReg())
.addExpr(SymGotTlsGD));
@@ -965,7 +1044,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
case PPC::ADDIStlsldHA: {
// Transform: %xd = ADDIStlsldHA %x2, @sym
// Into: %xd = ADDIS8 %x2, sym@got@tlsld@ha
- assert(Subtarget->isPPC64() && "Not supported for 32-bit PowerPC");
+ assert(IsPPC64 && "Not supported for 32-bit PowerPC");
const MachineOperand &MO = MI->getOperand(2);
const GlobalValue *GValue = MO.getGlobal();
MCSymbol *MOSymbol = getSymbol(GValue);
@@ -988,11 +1067,11 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
const GlobalValue *GValue = MO.getGlobal();
MCSymbol *MOSymbol = getSymbol(GValue);
const MCExpr *SymGotTlsLD = MCSymbolRefExpr::create(
- MOSymbol, Subtarget->isPPC64() ? MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO
- : MCSymbolRefExpr::VK_PPC_GOT_TLSLD,
+ MOSymbol, IsPPC64 ? MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO
+ : MCSymbolRefExpr::VK_PPC_GOT_TLSLD,
OutContext);
EmitToStreamer(*OutStreamer,
- MCInstBuilder(Subtarget->isPPC64() ? PPC::ADDI8 : PPC::ADDI)
+ MCInstBuilder(IsPPC64 ? PPC::ADDI8 : PPC::ADDI)
.addReg(MI->getOperand(0).getReg())
.addReg(MI->getOperand(1).getReg())
.addExpr(SymGotTlsLD));
@@ -1021,7 +1100,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
OutContext);
EmitToStreamer(
*OutStreamer,
- MCInstBuilder(Subtarget->isPPC64() ? PPC::ADDIS8 : PPC::ADDIS)
+ MCInstBuilder(IsPPC64 ? PPC::ADDIS8 : PPC::ADDIS)
.addReg(MI->getOperand(0).getReg())
.addReg(MI->getOperand(1).getReg())
.addExpr(SymDtprel));
@@ -1040,7 +1119,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
MCSymbolRefExpr::create(MOSymbol, MCSymbolRefExpr::VK_PPC_DTPREL_LO,
OutContext);
EmitToStreamer(*OutStreamer,
- MCInstBuilder(Subtarget->isPPC64() ? PPC::ADDI8 : PPC::ADDI)
+ MCInstBuilder(IsPPC64 ? PPC::ADDI8 : PPC::ADDI)
.addReg(MI->getOperand(0).getReg())
.addReg(MI->getOperand(1).getReg())
.addExpr(SymDtprel));
@@ -1087,7 +1166,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
// suite shows a handful of test cases that fail this check for
// Darwin. Those need to be investigated before this sanity test
// can be enabled for those subtargets.
- if (!Subtarget->isDarwin()) {
+ if (!IsDarwin) {
unsigned OpNum = (MI->getOpcode() == PPC::STD) ? 2 : 1;
const MachineOperand &MO = MI->getOperand(OpNum);
if (MO.isGlobal() && MO.getGlobal()->getAlignment() < 4)
@@ -1098,7 +1177,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
}
}
- LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, isDarwin);
+ LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, IsDarwin);
EmitToStreamer(*OutStreamer, TmpInst);
}
@@ -1368,15 +1447,16 @@ bool PPCLinuxAsmPrinter::doFinalization(Module &M) {
".got2", ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC);
OutStreamer->SwitchSection(Section);
- for (MapVector<MCSymbol*, MCSymbol*>::iterator I = TOC.begin(),
- E = TOC.end(); I != E; ++I) {
- OutStreamer->EmitLabel(I->second);
- MCSymbol *S = I->first;
+ for (const auto &TOCMapPair : TOC) {
+ const MCSymbol *const TOCEntryTarget = TOCMapPair.first;
+ MCSymbol *const TOCEntryLabel = TOCMapPair.second;
+
+ OutStreamer->EmitLabel(TOCEntryLabel);
if (isPPC64) {
- TS.emitTCEntry(*S);
+ TS.emitTCEntry(*TOCEntryTarget);
} else {
OutStreamer->EmitValueToAlignment(4);
- OutStreamer->EmitSymbolValue(S, 4);
+ OutStreamer->EmitSymbolValue(TOCEntryTarget, 4);
}
}
}
@@ -1602,7 +1682,7 @@ bool PPCDarwinAsmPrinter::doFinalization(Module &M) {
if (!Stubs.empty()) {
// Switch with ".non_lazy_symbol_pointer" directive.
OutStreamer->SwitchSection(TLOFMacho.getNonLazySymbolPointerSection());
- EmitAlignment(isPPC64 ? 3 : 2);
+ EmitAlignment(isPPC64 ? Align(8) : Align(4));
for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
// L_foo$stub:
@@ -1643,6 +1723,106 @@ bool PPCDarwinAsmPrinter::doFinalization(Module &M) {
return AsmPrinter::doFinalization(M);
}
+void PPCAIXAsmPrinter::SetupMachineFunction(MachineFunction &MF) {
+ // Get the function descriptor symbol.
+ CurrentFnDescSym = getSymbol(&MF.getFunction());
+ // Set the containing csect.
+ MCSectionXCOFF *FnDescSec = OutStreamer->getContext().getXCOFFSection(
+ CurrentFnDescSym->getName(), XCOFF::XMC_DS, XCOFF::XTY_SD,
+ XCOFF::C_HIDEXT, SectionKind::getData());
+ cast<MCSymbolXCOFF>(CurrentFnDescSym)->setContainingCsect(FnDescSec);
+
+ return AsmPrinter::SetupMachineFunction(MF);
+}
+
+void PPCAIXAsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) {
+ // Early error checking limiting what is supported.
+ if (GV->isThreadLocal())
+ report_fatal_error("Thread local not yet supported on AIX.");
+
+ if (GV->hasSection())
+ report_fatal_error("Custom section for Data not yet supported.");
+
+ if (GV->hasComdat())
+ report_fatal_error("COMDAT not yet supported by AIX.");
+
+ SectionKind GVKind = getObjFileLowering().getKindForGlobal(GV, TM);
+ if (!GVKind.isCommon() && !GVKind.isBSSLocal() && !GVKind.isData())
+ report_fatal_error("Encountered a global variable kind that is "
+ "not supported yet.");
+
+ // Create the containing csect and switch to it.
+ MCSectionXCOFF *CSect = cast<MCSectionXCOFF>(
+ getObjFileLowering().SectionForGlobal(GV, GVKind, TM));
+ OutStreamer->SwitchSection(CSect);
+
+ // Create the symbol, set its storage class, and emit it.
+ MCSymbolXCOFF *GVSym = cast<MCSymbolXCOFF>(getSymbol(GV));
+ GVSym->setStorageClass(
+ TargetLoweringObjectFileXCOFF::getStorageClassForGlobal(GV));
+ GVSym->setContainingCsect(CSect);
+
+ const DataLayout &DL = GV->getParent()->getDataLayout();
+
+ // Handle common symbols.
+ if (GVKind.isCommon() || GVKind.isBSSLocal()) {
+ unsigned Align =
+ GV->getAlignment() ? GV->getAlignment() : DL.getPreferredAlignment(GV);
+ uint64_t Size = DL.getTypeAllocSize(GV->getType()->getElementType());
+
+ if (GVKind.isBSSLocal())
+ OutStreamer->EmitXCOFFLocalCommonSymbol(GVSym, Size, Align);
+ else
+ OutStreamer->EmitCommonSymbol(GVSym, Size, Align);
+ return;
+ }
+
+ MCSymbol *EmittedInitSym = GVSym;
+ EmitLinkage(GV, EmittedInitSym);
+ EmitAlignment(getGVAlignment(GV, DL), GV);
+ OutStreamer->EmitLabel(EmittedInitSym);
+ EmitGlobalConstant(GV->getParent()->getDataLayout(), GV->getInitializer());
+}
+
+void PPCAIXAsmPrinter::EmitFunctionDescriptor() {
+ const DataLayout &DL = getDataLayout();
+ const unsigned PointerSize = DL.getPointerSizeInBits() == 64 ? 8 : 4;
+
+ MCSectionSubPair Current = OutStreamer->getCurrentSection();
+ // Emit function descriptor.
+ OutStreamer->SwitchSection(
+ cast<MCSymbolXCOFF>(CurrentFnDescSym)->getContainingCsect());
+ OutStreamer->EmitLabel(CurrentFnDescSym);
+ // Emit function entry point address.
+ OutStreamer->EmitValue(MCSymbolRefExpr::create(CurrentFnSym, OutContext),
+ PointerSize);
+ // Emit TOC base address.
+ MCSymbol *TOCBaseSym = OutContext.getOrCreateSymbol(StringRef("TOC[TC0]"));
+ OutStreamer->EmitValue(MCSymbolRefExpr::create(TOCBaseSym, OutContext),
+ PointerSize);
+ // Emit a null environment pointer.
+ OutStreamer->EmitIntValue(0, PointerSize);
+
+ OutStreamer->SwitchSection(Current.first, Current.second);
+}
+
+void PPCAIXAsmPrinter::EmitEndOfAsmFile(Module &M) {
+ // If there are no functions in this module, we will never need to reference
+ // the TOC base.
+ if (M.empty())
+ return;
+
+ // Emit TOC base.
+ MCSymbol *TOCBaseSym = OutContext.getOrCreateSymbol(StringRef("TOC[TC0]"));
+ MCSectionXCOFF *TOCBaseSection = OutStreamer->getContext().getXCOFFSection(
+ StringRef("TOC"), XCOFF::XMC_TC0, XCOFF::XTY_SD, XCOFF::C_HIDEXT,
+ SectionKind::getData());
+ cast<MCSymbolXCOFF>(TOCBaseSym)->setContainingCsect(TOCBaseSection);
+ // Switch to section to emit TOC base.
+ OutStreamer->SwitchSection(TOCBaseSection);
+}
+
+
/// createPPCAsmPrinterPass - Returns a pass that prints the PPC assembly code
/// for a MachineFunction to the given output stream, in a format that the
/// Darwin assembler can deal with.