summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/PowerPC
diff options
context:
space:
mode:
authorDavid Tenty <daltenty@ibm.com>2019-11-27 17:17:02 -0500
committerDavid Tenty <daltenty@ibm.com>2019-11-27 17:20:55 -0500
commit98740643f794254342e22d106eafb73cf459f465 (patch)
tree4a0338009bfa08ab54ece541a89417e892016283 /llvm/lib/Target/PowerPC
parent40963b2bf0e72626d21917a08f3c86e56541ae7a (diff)
downloadbcm5719-llvm-98740643f794254342e22d106eafb73cf459f465.tar.gz
bcm5719-llvm-98740643f794254342e22d106eafb73cf459f465.zip
[AIX] Emit TOC entries for ASM printing
Summary: Emit the correct .toc psuedo op when we change to the TOC and emit TC entries. Make sure TOC psuedos get the right symbols via overriding getMCSymbolForTOCPseudoMO on AIX. Add a test for TOC assembly writing and update tests to include TOC entries. Also make sure external globals have a csect set and handle external function descriptor (originally authored by Jason Liu) so we can emit TOC entries for them. Reviewers: DiggerLin, sfertile, Xiangling_L, jasonliu, hubert.reinterpretcast Reviewed By: jasonliu Subscribers: arphaman, wuzish, nemanjai, hiraditya, kbarton, jsji, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D70461
Diffstat (limited to 'llvm/lib/Target/PowerPC')
-rw-r--r--llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp1
-rw-r--r--llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp8
-rw-r--r--llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp130
3 files changed, 117 insertions, 22 deletions
diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp
index 1216cd72728..a61c34ca6f1 100644
--- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp
+++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCAsmInfo.cpp
@@ -87,4 +87,5 @@ PPCXCOFFMCAsmInfo::PPCXCOFFMCAsmInfo(bool Is64Bit, const Triple &T) {
assert(!IsLittleEndian && "Little-endian XCOFF not supported.");
CodePointerSize = CalleeSaveStackSlotSize = Is64Bit ? 8 : 4;
ZeroDirective = "\t.space\t";
+ SymbolsHaveSMC = true;
}
diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp
index a9717bfc308..3cc1f402316 100644
--- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp
+++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.cpp
@@ -30,6 +30,7 @@
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MCSymbolELF.h"
+#include "llvm/MC/MCSymbolXCOFF.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Support/ErrorHandling.h"
@@ -108,8 +109,11 @@ public:
: PPCTargetStreamer(S), OS(OS) {}
void emitTCEntry(const MCSymbol &S) override {
+ const MCAsmInfo *MAI = Streamer.getContext().getAsmInfo();
OS << "\t.tc ";
- OS << S.getName();
+ OS << (MAI->getSymbolsHaveSMC()
+ ? cast<MCSymbolXCOFF>(S).getUnqualifiedName()
+ : S.getName());
OS << "[TC],";
OS << S.getName();
OS << '\n';
@@ -243,7 +247,7 @@ public:
PPCTargetXCOFFStreamer(MCStreamer &S) : PPCTargetStreamer(S) {}
void emitTCEntry(const MCSymbol &S) override {
- report_fatal_error("TOC entries not supported yet.");
+ // Object writing TOC entries not supported yet.
}
void emitMachine(StringRef CPU) override {
diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
index 33198efb05f..08e305d69e7 100644
--- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
+++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
@@ -43,6 +43,7 @@
#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/GlobalValue.h"
+#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Module.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
@@ -82,6 +83,8 @@ protected:
const PPCSubtarget *Subtarget = nullptr;
StackMaps SM;
+ virtual MCSymbol *getMCSymbolForTOCPseudoMO(const MachineOperand &MO);
+
public:
explicit PPCAsmPrinter(TargetMachine &TM,
std::unique_ptr<MCStreamer> Streamer)
@@ -161,6 +164,11 @@ public:
};
class PPCAIXAsmPrinter : public PPCAsmPrinter {
+private:
+ static void ValidateGV(const GlobalVariable *GV);
+protected:
+ MCSymbol *getMCSymbolForTOCPseudoMO(const MachineOperand &MO) override;
+
public:
PPCAIXAsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
: PPCAsmPrinter(TM, std::move(Streamer)) {}
@@ -514,17 +522,16 @@ void PPCAsmPrinter::EmitTlsCall(const MachineInstr *MI,
/// Map a machine operand for a TOC pseudo-machine instruction to its
/// corresponding MCSymbol.
-static MCSymbol *getMCSymbolForTOCPseudoMO(const MachineOperand &MO,
- AsmPrinter &AP) {
+MCSymbol *PPCAsmPrinter::getMCSymbolForTOCPseudoMO(const MachineOperand &MO) {
switch (MO.getType()) {
case MachineOperand::MO_GlobalAddress:
- return AP.getSymbol(MO.getGlobal());
+ return getSymbol(MO.getGlobal());
case MachineOperand::MO_ConstantPoolIndex:
- return AP.GetCPISymbol(MO.getIndex());
+ return GetCPISymbol(MO.getIndex());
case MachineOperand::MO_JumpTableIndex:
- return AP.GetJTISymbol(MO.getIndex());
+ return GetJTISymbol(MO.getIndex());
case MachineOperand::MO_BlockAddress:
- return AP.GetBlockAddressSymbol(MO.getBlockAddress());
+ return GetBlockAddressSymbol(MO.getBlockAddress());
default:
llvm_unreachable("Unexpected operand type to get symbol.");
}
@@ -688,7 +695,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
"Invalid operand for LWZtoc.");
// Map the operand to its corresponding MCSymbol.
- const MCSymbol *const MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);
+ const MCSymbol *const MOSymbol = getMCSymbolForTOCPseudoMO(MO);
// Create a reference to the GOT entry for the symbol. The GOT entry will be
// synthesized later.
@@ -749,7 +756,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
// global address operand to be a reference to the TOC entry we will
// synthesize later.
MCSymbol *TOCEntry =
- lookUpOrCreateTOCEntry(getMCSymbolForTOCPseudoMO(MO, *this));
+ lookUpOrCreateTOCEntry(getMCSymbolForTOCPseudoMO(MO));
const MCSymbolRefExpr::VariantKind VK =
IsAIX ? MCSymbolRefExpr::VK_None : MCSymbolRefExpr::VK_PPC_TOC;
@@ -775,7 +782,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
"Invalid operand for ADDIStocHA.");
// Map the machine operand to its corresponding MCSymbol.
- MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);
+ MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO);
// 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
@@ -805,7 +812,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
"Invalid operand for LWZtocL.");
// Map the machine operand to its corresponding MCSymbol.
- MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);
+ MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO);
// 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
@@ -835,7 +842,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) &&
"Invalid operand for ADDIStocHA8!");
- const MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);
+ const MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO);
const bool GlobalToc =
MO.isGlobal() && Subtarget->isGVIndirectSymbol(MO.getGlobal());
@@ -881,7 +888,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
"LDtocL used on symbol that could be accessed directly is "
"invalid. Must match ADDIStocHA8."));
- const MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO, *this);
+ const MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO);
if (!MO.isCPI() || TM.getCodeModel() == CodeModel::Large)
MOSymbol = lookUpOrCreateTOCEntry(MOSymbol);
@@ -911,7 +918,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
"Interposable definitions must use indirect access."));
const MCExpr *Exp =
- MCSymbolRefExpr::create(getMCSymbolForTOCPseudoMO(MO, *this),
+ MCSymbolRefExpr::create(getMCSymbolForTOCPseudoMO(MO),
MCSymbolRefExpr::VK_PPC_TOC_LO, OutContext);
TmpInst.getOperand(2) = MCOperand::createExpr(Exp);
EmitToStreamer(*OutStreamer, TmpInst);
@@ -1736,7 +1743,7 @@ void PPCAIXAsmPrinter::SetupMachineFunction(MachineFunction &MF) {
return AsmPrinter::SetupMachineFunction(MF);
}
-void PPCAIXAsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) {
+void PPCAIXAsmPrinter::ValidateGV(const GlobalVariable *GV) {
// Early error checking limiting what is supported.
if (GV->isThreadLocal())
report_fatal_error("Thread local not yet supported on AIX.");
@@ -1746,6 +1753,19 @@ void PPCAIXAsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) {
if (GV->hasComdat())
report_fatal_error("COMDAT not yet supported by AIX.");
+}
+
+void PPCAIXAsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) {
+ ValidateGV(GV);
+
+ // External global variables are already handled.
+ if (!GV->hasInitializer())
+ return;
+
+ // Create the symbol, set its storage class.
+ MCSymbolXCOFF *GVSym = cast<MCSymbolXCOFF>(getSymbol(GV));
+ GVSym->setStorageClass(
+ TargetLoweringObjectFileXCOFF::getStorageClassForGlobal(GV));
SectionKind GVKind = getObjFileLowering().getKindForGlobal(GV, TM);
if ((!GVKind.isCommon() && !GVKind.isBSS() && !GVKind.isData() &&
@@ -1759,11 +1779,6 @@ void PPCAIXAsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) {
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();
@@ -1802,7 +1817,10 @@ void PPCAIXAsmPrinter::EmitFunctionDescriptor() {
OutStreamer->EmitValue(MCSymbolRefExpr::create(CurrentFnSym, OutContext),
PointerSize);
// Emit TOC base address.
- MCSymbol *TOCBaseSym = OutContext.getOrCreateSymbol(StringRef("TOC[TC0]"));
+ const MCSectionXCOFF *TOCBaseSec = OutStreamer->getContext().getXCOFFSection(
+ StringRef("TOC"), XCOFF::XMC_TC0, XCOFF::XTY_SD, XCOFF::C_HIDEXT,
+ SectionKind::getData());
+ const MCSymbol *TOCBaseSym = TOCBaseSec->getQualNameSymbol();
OutStreamer->EmitValue(MCSymbolRefExpr::create(TOCBaseSym, OutContext),
PointerSize);
// Emit a null environment pointer.
@@ -1823,8 +1841,80 @@ void PPCAIXAsmPrinter::EmitEndOfAsmFile(Module &M) {
SectionKind::getData());
// Switch to section to emit TOC base.
OutStreamer->SwitchSection(TOCBaseSection);
+
+ PPCTargetStreamer &TS =
+ static_cast<PPCTargetStreamer &>(*OutStreamer->getTargetStreamer());
+
+ for (auto &I : TOC) {
+ // Setup the csect for the current TC entry.
+ MCSectionXCOFF *TCEntry = OutStreamer->getContext().getXCOFFSection(
+ cast<MCSymbolXCOFF>(I.first)->getUnqualifiedName(), XCOFF::XMC_TC,
+ XCOFF::XTY_SD, XCOFF::C_HIDEXT, SectionKind::getData());
+ cast<MCSymbolXCOFF>(I.second)->setContainingCsect(TCEntry);
+ OutStreamer->SwitchSection(TCEntry);
+
+ OutStreamer->EmitLabel(I.second);
+ TS.emitTCEntry(*I.first);
+ }
}
+MCSymbol *
+PPCAIXAsmPrinter::getMCSymbolForTOCPseudoMO(const MachineOperand &MO) {
+ const GlobalObject *GO = nullptr;
+
+ // If the MO is a function or certain kind of globals, we want to make sure to
+ // refer to the csect symbol, otherwise we can just do the default handling.
+ if (MO.getType() != MachineOperand::MO_GlobalAddress ||
+ !(GO = dyn_cast<const GlobalObject>(MO.getGlobal())))
+ return PPCAsmPrinter::getMCSymbolForTOCPseudoMO(MO);
+
+ // Do an early error check for globals we don't support. This will go away
+ // eventually.
+ const auto *GV = dyn_cast<const GlobalVariable>(GO);
+ if (GV) {
+ ValidateGV(GV);
+ }
+
+ MCSymbolXCOFF *XSym = cast<MCSymbolXCOFF>(getSymbol(GO));
+
+ // If the global object is a global variable without initializer or is a
+ // declaration of a function, then XSym is an external referenced symbol.
+ // Hence we may need to explictly create a MCSectionXCOFF for it so that we
+ // can return its symbol later.
+ if (GO->isDeclaration() && !XSym->hasContainingCsect()) {
+ // Make sure the storage class is set.
+ const XCOFF::StorageClass SC =
+ TargetLoweringObjectFileXCOFF::getStorageClassForGlobal(GO);
+ XSym->setStorageClass(SC);
+
+ MCSectionXCOFF *Csect = OutStreamer->getContext().getXCOFFSection(
+ XSym->getName(), isa<Function>(GO) ? XCOFF::XMC_DS : XCOFF::XMC_UA,
+ XCOFF::XTY_ER, SC, SectionKind::getMetadata());
+ XSym->setContainingCsect(Csect);
+
+ return Csect->getQualNameSymbol();
+ }
+
+ // Handle initialized global variables.
+ if (GV) {
+ SectionKind GVKind = getObjFileLowering().getKindForGlobal(GV, TM);
+
+ // If the operand is a common then we should refer to the csect symbol.
+ if (GVKind.isCommon() || GVKind.isBSSLocal()) {
+ MCSectionXCOFF *Csect = cast<MCSectionXCOFF>(
+ getObjFileLowering().SectionForGlobal(GV, GVKind, TM));
+ return Csect->getQualNameSymbol();
+ }
+
+ // Other global variables are refered to by labels inside of a single csect,
+ // so refer to the label directly.
+ return getSymbol(GV);
+ }
+
+ // If the MO is a function, we want to make sure to refer to the function
+ // descriptor csect.
+ return XSym->getContainingCsect()->getQualNameSymbol();
+}
/// createPPCAsmPrinterPass - Returns a pass that prints the PPC assembly code
/// for a MachineFunction to the given output stream, in a format that the
OpenPOWER on IntegriCloud