diff options
author | Justin Hibbits <jrh29@alumni.cwru.edu> | 2014-11-12 15:16:30 +0000 |
---|---|---|
committer | Justin Hibbits <jrh29@alumni.cwru.edu> | 2014-11-12 15:16:30 +0000 |
commit | a88b605721a602e473c6072b6d2bf20aec02b0c7 (patch) | |
tree | 4839d0b50dc4a34a2721388b0216e852f3656b84 /llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp | |
parent | 62cf35b8a3116517017247b321d9c1dfbd94a401 (diff) | |
download | bcm5719-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.cpp | 116 |
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); |