summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
diff options
context:
space:
mode:
authorJustin Hibbits <jrh29@alumni.cwru.edu>2014-11-12 15:16:30 +0000
committerJustin Hibbits <jrh29@alumni.cwru.edu>2014-11-12 15:16:30 +0000
commita88b605721a602e473c6072b6d2bf20aec02b0c7 (patch)
tree4839d0b50dc4a34a2721388b0216e852f3656b84 /llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
parent62cf35b8a3116517017247b321d9c1dfbd94a401 (diff)
downloadbcm5719-llvm-a88b605721a602e473c6072b6d2bf20aec02b0c7.tar.gz
bcm5719-llvm-a88b605721a602e473c6072b6d2bf20aec02b0c7.zip
Add support for small-model PIC for PowerPC.
Summary: Large-model was added first. With the addition of support for multiple PIC models in LLVM, now add small-model PIC for 32-bit PowerPC, SysV4 ABI. This generates more optimal code, for shared libraries with less than about 16380 data objects. Test Plan: Test cases added or updated Reviewers: joerg, hfinkel Reviewed By: hfinkel Subscribers: jholewinski, mcrosier, emaste, llvm-commits Differential Revision: http://reviews.llvm.org/D5399 llvm-svn: 221791
Diffstat (limited to 'llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp')
-rw-r--r--llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp116
1 files changed, 75 insertions, 41 deletions
diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
index 471780ac5a2..564887353dd 100644
--- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
+++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
@@ -323,12 +323,35 @@ MCSymbol *PPCAsmPrinter::lookUpOrCreateTOCEntry(MCSymbol *Sym) {
void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
MCInst TmpInst;
bool isPPC64 = Subtarget.isPPC64();
+ bool isDarwin = Triple(TM.getTargetTriple()).isOSDarwin();
+ const Module *M = MF->getFunction()->getParent();
+ PICLevel::Level PL = M->getPICLevel();
// Lower multi-instruction pseudo operations.
switch (MI->getOpcode()) {
default: break;
case TargetOpcode::DBG_VALUE:
llvm_unreachable("Should be handled target independently");
+ case PPC::MoveGOTtoLR: {
+ // Transform %LR = MoveGOTtoLR
+ // Into this: bl _GLOBAL_OFFSET_TABLE_@local-4
+ // _GLOBAL_OFFSET_TABLE_@local-4 (instruction preceding
+ // _GLOBAL_OFFSET_TABLE_) has exactly one instruction:
+ // blrl
+ // This will return the pointer to _GLOBAL_OFFSET_TABLE_@local
+ MCSymbol *GOTSymbol =
+ OutContext.GetOrCreateSymbol(StringRef("_GLOBAL_OFFSET_TABLE_"));
+ const MCExpr *OffsExpr =
+ MCBinaryExpr::CreateSub(MCSymbolRefExpr::Create(GOTSymbol,
+ MCSymbolRefExpr::VK_PPC_LOCAL,
+ OutContext),
+ MCConstantExpr::Create(4, OutContext),
+ OutContext);
+
+ // Emit the 'bl'.
+ EmitToStreamer(OutStreamer, MCInstBuilder(PPC::BL).addExpr(OffsExpr));
+ return;
+ }
case PPC::MovePCtoLR:
case PPC::MovePCtoLR8: {
// Transform %LR = MovePCtoLR
@@ -347,10 +370,14 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
OutStreamer.EmitLabel(PICBase);
return;
}
- case PPC::GetGBRO: {
+ case PPC::UpdateGBR: {
+ // Transform %Rd = UpdateGBR(%Rt, %Ri)
+ // Into: lwz %Rt, .L0$poff - .L0$pb(%Ri)
+ // add %Rd, %Rt, %Ri
// Get the offset from the GOT Base Register to the GOT
- LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, Subtarget.isDarwin());
- MCSymbol *PICOffset = MF->getInfo<PPCFunctionInfo>()->getPICOffsetSymbol();
+ LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, isDarwin);
+ MCSymbol *PICOffset =
+ MF->getInfo<PPCFunctionInfo>()->getPICOffsetSymbol();
TmpInst.setOpcode(PPC::LWZ);
const MCExpr *Exp =
MCSymbolRefExpr::Create(PICOffset, MCSymbolRefExpr::VK_None, OutContext);
@@ -358,26 +385,26 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
MCSymbolRefExpr::Create(MF->getPICBaseSymbol(),
MCSymbolRefExpr::VK_None,
OutContext);
- const MCOperand MO = TmpInst.getOperand(1);
- TmpInst.getOperand(1) = MCOperand::CreateExpr(MCBinaryExpr::CreateSub(Exp,
- PB,
- OutContext));
- TmpInst.addOperand(MO);
+ const MCOperand TR = TmpInst.getOperand(1);
+ const MCOperand PICR = TmpInst.getOperand(0);
+
+ // Step 1: lwz %Rt, .L$poff - .L$pb(%Ri)
+ TmpInst.getOperand(1) =
+ MCOperand::CreateExpr(MCBinaryExpr::CreateSub(Exp, PB, OutContext));
+ TmpInst.getOperand(0) = TR;
+ TmpInst.getOperand(2) = PICR;
EmitToStreamer(OutStreamer, TmpInst);
- return;
- }
- case PPC::UpdateGBR: {
- // Update the GOT Base Register to point to the GOT. It may be possible to
- // merge this with the PPC::GetGBRO, doing it all in one step.
- LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, Subtarget.isDarwin());
+
TmpInst.setOpcode(PPC::ADD4);
- TmpInst.addOperand(TmpInst.getOperand(0));
+ TmpInst.getOperand(0) = PICR;
+ TmpInst.getOperand(1) = TR;
+ TmpInst.getOperand(2) = PICR;
EmitToStreamer(OutStreamer, TmpInst);
return;
}
case PPC::LWZtoc: {
- // Transform %X3 = LWZtoc <ga:@min1>, %X2
- LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, Subtarget.isDarwin());
+ // Transform %R3 = LWZtoc <ga:@min1>, %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.
@@ -396,16 +423,23 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
else if (MO.isBlockAddress())
MOSymbol = GetBlockAddressSymbol(MO.getBlockAddress());
- MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(MOSymbol);
-
- const MCExpr *Exp =
- MCSymbolRefExpr::Create(TOCEntry, MCSymbolRefExpr::VK_None,
- OutContext);
- const MCExpr *PB =
- MCSymbolRefExpr::Create(OutContext.GetOrCreateSymbol(Twine(".L.TOC.")),
- OutContext);
- Exp = MCBinaryExpr::CreateSub(Exp, PB, OutContext);
- TmpInst.getOperand(1) = MCOperand::CreateExpr(Exp);
+ if (PL == PICLevel::Small) {
+ const MCExpr *Exp =
+ MCSymbolRefExpr::Create(MOSymbol, MCSymbolRefExpr::VK_GOT,
+ OutContext);
+ TmpInst.getOperand(1) = MCOperand::CreateExpr(Exp);
+ } else {
+ MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(MOSymbol);
+
+ 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);
+ TmpInst.getOperand(1) = MCOperand::CreateExpr(Exp);
+ }
EmitToStreamer(OutStreamer, TmpInst);
return;
}
@@ -414,7 +448,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
case PPC::LDtocBA:
case PPC::LDtoc: {
// Transform %X3 = LDtoc <ga:@min1>, %X2
- LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, Subtarget.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.
@@ -445,7 +479,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
case PPC::ADDIStocHA: {
// Transform %Xd = ADDIStocHA %X2, <ga:@sym>
- LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, Subtarget.isDarwin());
+ 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
@@ -491,7 +525,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
}
case PPC::LDtocL: {
// Transform %Xd = LDtocL <ga:@sym>, %Xs
- LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, Subtarget.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
@@ -533,7 +567,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
}
case PPC::ADDItocL: {
// Transform %Xd = ADDItocL %Xs, <ga:@sym>
- LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, Subtarget.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
@@ -584,7 +618,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
case PPC::LDgotTprelL:
case PPC::LDgotTprelL32: {
// Transform %Xd = LDgotTprelL <ga:@sym>, %Xs
- LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, Subtarget.isDarwin());
+ LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, isDarwin);
// Change the opcode to LD.
TmpInst.setOpcode(isPPC64 ? PPC::LD : PPC::LWZ);
@@ -808,7 +842,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
}
}
- LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, Subtarget.isDarwin());
+ LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, isDarwin);
EmitToStreamer(OutStreamer, TmpInst);
}
@@ -824,16 +858,14 @@ void PPCLinuxAsmPrinter::EmitStartOfAsmFile(Module &M) {
if (Subtarget.isPPC64() || TM.getRelocationModel() != Reloc::PIC_)
return AsmPrinter::EmitStartOfAsmFile(M);
- // FIXME: The use of .got2 assumes large GOT model (-fPIC), which is not
- // optimal for some cases. We should consider supporting small model (-fpic)
- // as well in the future.
- assert(TM.getCodeModel() != CodeModel::Small &&
- "Small code model PIC is currently unsupported.");
+ if (M.getPICLevel() == PICLevel::Small)
+ return AsmPrinter::EmitStartOfAsmFile(M);
+
OutStreamer.SwitchSection(OutContext.getELFSection(".got2",
ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC,
SectionKind::getReadOnly()));
- MCSymbol *TOCSym = OutContext.GetOrCreateSymbol(Twine(".L.TOC."));
+ MCSymbol *TOCSym = OutContext.GetOrCreateSymbol(Twine(".LTOC"));
MCSymbol *CurrentPos = OutContext.CreateTempSymbol();
OutStreamer.EmitLabel(CurrentPos);
@@ -852,7 +884,9 @@ void PPCLinuxAsmPrinter::EmitStartOfAsmFile(Module &M) {
void PPCLinuxAsmPrinter::EmitFunctionEntryLabel() {
// linux/ppc32 - Normal entry label.
- if (!Subtarget.isPPC64() && TM.getRelocationModel() != Reloc::PIC_)
+ if (!Subtarget.isPPC64() &&
+ (TM.getRelocationModel() != Reloc::PIC_ ||
+ MF->getFunction()->getParent()->getPICLevel() == PICLevel::Small))
return AsmPrinter::EmitFunctionEntryLabel();
if (!Subtarget.isPPC64()) {
@@ -864,7 +898,7 @@ void PPCLinuxAsmPrinter::EmitFunctionEntryLabel() {
const MCExpr *OffsExpr =
MCBinaryExpr::CreateSub(
- MCSymbolRefExpr::Create(OutContext.GetOrCreateSymbol(Twine(".L.TOC.")),
+ MCSymbolRefExpr::Create(OutContext.GetOrCreateSymbol(Twine(".LTOC")),
OutContext),
MCSymbolRefExpr::Create(PICBase, OutContext),
OutContext);
OpenPOWER on IntegriCloud