Pull in r214284 from upstream llvm trunk (by Hal Finkel): [PowerPC] Add JMP_SLOT relocation definitions This will be required by upcoming patches for LLDB support. Patch by Justin Hibbits! Pull in r221510 from upstream llvm trunk (by Justin Hibbits): Add Position-independent Code model Module API. Summary: This makes PIC levels a Module flag attribute, which can be queried by the backend. The flag is named `PIC Level`, and can have a value of: 0 - Backend-default 1 - Small-model (-fpic) 2 - Large-model (-fPIC) These match the `-pic-level' command line argument for clang, and the value of the preprocessor macro `__PIC__'. Test Plan: New flags tests specific for the 'PIC Level' module flag. Tests to be added as part of a future commit for PowerPC, which will use this new API. Reviewers: rafael, echristo Reviewed By: rafael, echristo Subscribers: rafael, llvm-commits Differential Revision: http://reviews.llvm.org/D5882 Pull in r221791 from upstream llvm trunk (by Justin Hibbits): 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 Pull in r221792 from upstream llvm trunk (by Justin Hibbits): Fix thet tests. I seem to have missed the update I made for changing 'flag_pic' to "PIC Level". Mea culpa. Pull in r221793 from upstream llvm trunk (by Justin Hibbits): Revert part of the PIC tests (TLS part) This change actually wasn't warranted for -O0, and the new changes prove it and break the build. Together, these changes implement small-model PIC support for PowerPC. Thanks to Justin Hibbits and Roman Divacky for their assistance in getting this working. Introduced here: http://svnweb.freebsd.org/changeset/base/276211 Index: include/llvm/IR/Module.h =================================================================== --- include/llvm/IR/Module.h +++ include/llvm/IR/Module.h @@ -23,6 +23,7 @@ #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/Metadata.h" #include "llvm/Support/CBindingWrapping.h" +#include "llvm/Support/CodeGen.h" #include "llvm/Support/DataTypes.h" #include @@ -620,6 +621,15 @@ class Module { unsigned getDwarfVersion() const; /// @} +/// @name Utility functions for querying and setting PIC level +/// @{ + + /// \brief Returns the PIC level (small or large model) + PICLevel::Level getPICLevel() const; + + /// \brief Set the PIC level (small or large model) + void setPICLevel(PICLevel::Level PL); +/// @} }; /// An raw_ostream inserter for modules. Index: include/llvm/MC/MCExpr.h =================================================================== --- include/llvm/MC/MCExpr.h +++ include/llvm/MC/MCExpr.h @@ -238,6 +238,7 @@ class MCSymbolRefExpr : public MCExpr { VK_PPC_GOT_TLSLD_HI, // symbol@got@tlsld@h VK_PPC_GOT_TLSLD_HA, // symbol@got@tlsld@ha VK_PPC_TLSLD, // symbol@tlsld + VK_PPC_LOCAL, // symbol@local VK_Mips_GPREL, VK_Mips_GOT_CALL, Index: include/llvm/Support/CodeGen.h =================================================================== --- include/llvm/Support/CodeGen.h +++ include/llvm/Support/CodeGen.h @@ -30,6 +30,10 @@ namespace llvm { enum Model { Default, JITDefault, Small, Kernel, Medium, Large }; } + namespace PICLevel { + enum Level { Default=0, Small=1, Large=2 }; + } + // TLS models. namespace TLSModel { enum Model { Index: include/llvm/Support/ELF.h =================================================================== --- include/llvm/Support/ELF.h +++ include/llvm/Support/ELF.h @@ -459,6 +459,8 @@ enum { R_PPC_GOT16_HI = 16, R_PPC_GOT16_HA = 17, R_PPC_PLTREL24 = 18, + R_PPC_JMP_SLOT = 21, + R_PPC_LOCAL24PC = 23, R_PPC_REL32 = 26, R_PPC_TLS = 67, R_PPC_DTPMOD32 = 68, @@ -547,6 +549,7 @@ enum { R_PPC64_GOT16_LO = 15, R_PPC64_GOT16_HI = 16, R_PPC64_GOT16_HA = 17, + R_PPC64_JMP_SLOT = 21, R_PPC64_REL32 = 26, R_PPC64_ADDR64 = 38, R_PPC64_ADDR16_HIGHER = 39, Index: lib/IR/Module.cpp =================================================================== --- lib/IR/Module.cpp +++ lib/IR/Module.cpp @@ -461,3 +461,16 @@ Comdat *Module::getOrInsertComdat(StringRef Name) Entry.second.Name = &Entry; return &Entry.second; } + +PICLevel::Level Module::getPICLevel() const { + Value *Val = getModuleFlag("PIC Level"); + + if (Val == NULL) + return PICLevel::Default; + + return static_cast(cast(Val)->getZExtValue()); +} + +void Module::setPICLevel(PICLevel::Level PL) { + addModuleFlag(ModFlagBehavior::Error, "PIC Level", PL); +} Index: lib/MC/MCExpr.cpp =================================================================== --- lib/MC/MCExpr.cpp +++ lib/MC/MCExpr.cpp @@ -247,6 +247,7 @@ StringRef MCSymbolRefExpr::getVariantKindName(Vari case VK_PPC_GOT_TLSLD_HI: return "got@tlsld@h"; case VK_PPC_GOT_TLSLD_HA: return "got@tlsld@ha"; case VK_PPC_TLSLD: return "tlsld"; + case VK_PPC_LOCAL: return "local"; case VK_Mips_GPREL: return "GPREL"; case VK_Mips_GOT_CALL: return "GOT_CALL"; case VK_Mips_GOT16: return "GOT16"; Index: lib/Object/ELF.cpp =================================================================== --- lib/Object/ELF.cpp +++ lib/Object/ELF.cpp @@ -531,6 +531,8 @@ StringRef getELFRelocationTypeName(uint32_t Machin LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT16_HI); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT16_HA); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_PLTREL24); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_JMP_SLOT); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_LOCAL24PC); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL32); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_TLS); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_DTPMOD32); @@ -590,6 +592,7 @@ StringRef getELFRelocationTypeName(uint32_t Machin LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT16_LO); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT16_HI); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_JMP_SLOT); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL32); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR64); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_HIGHER); Index: lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp =================================================================== --- lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp +++ lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp @@ -95,6 +95,9 @@ unsigned PPCELFObjectWriter::getRelocTypeInner(con case MCSymbolRefExpr::VK_PLT: Type = ELF::R_PPC_PLTREL24; break; + case MCSymbolRefExpr::VK_PPC_LOCAL: + Type = ELF::R_PPC_LOCAL24PC; + break; } break; case PPC::fixup_ppc_brcond14: Index: lib/Target/PowerPC/PPCAsmPrinter.cpp =================================================================== --- lib/Target/PowerPC/PPCAsmPrinter.cpp +++ lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -311,6 +311,9 @@ MCSymbol *PPCAsmPrinter::lookUpOrCreateTOCEntry(MC 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()) { @@ -317,6 +320,26 @@ void PPCAsmPrinter::EmitInstruction(const MachineI 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 @@ -335,10 +358,14 @@ void PPCAsmPrinter::EmitInstruction(const MachineI 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()->getPICOffsetSymbol(); + LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, isDarwin); + MCSymbol *PICOffset = + MF->getInfo()->getPICOffsetSymbol(); TmpInst.setOpcode(PPC::LWZ); const MCExpr *Exp = MCSymbolRefExpr::Create(PICOffset, MCSymbolRefExpr::VK_None, OutContext); @@ -346,26 +373,26 @@ void PPCAsmPrinter::EmitInstruction(const MachineI 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 , %X2 - LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, Subtarget.isDarwin()); + // Transform %R3 = LWZtoc , %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. @@ -382,16 +409,23 @@ void PPCAsmPrinter::EmitInstruction(const MachineI else if (MO.isJTI()) MOSymbol = GetJTISymbol(MO.getIndex()); - MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(MOSymbol); + 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(".L.TOC.")), - OutContext); - Exp = MCBinaryExpr::CreateSub(Exp, PB, OutContext); - TmpInst.getOperand(1) = MCOperand::CreateExpr(Exp); + 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; } @@ -399,7 +433,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineI case PPC::LDtocCPT: case PPC::LDtoc: { // Transform %X3 = LDtoc , %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. @@ -428,7 +462,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineI case PPC::ADDIStocHA: { // Transform %Xd = ADDIStocHA %X2, - 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 @@ -470,7 +504,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineI } case PPC::LDtocL: { // Transform %Xd = LDtocL , %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 @@ -507,7 +541,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineI } case PPC::ADDItocL: { // Transform %Xd = ADDItocL %Xs, - 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 @@ -558,7 +592,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineI case PPC::LDgotTprelL: case PPC::LDgotTprelL32: { // Transform %Xd = LDgotTprelL , %Xs - LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, Subtarget.isDarwin()); + LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, isDarwin); // Change the opcode to LD. TmpInst.setOpcode(isPPC64 ? PPC::LD : PPC::LWZ); @@ -841,7 +875,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineI } } - LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, Subtarget.isDarwin()); + LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, isDarwin); EmitToStreamer(OutStreamer, TmpInst); } @@ -857,16 +891,14 @@ void PPCLinuxAsmPrinter::EmitStartOfAsmFile(Module 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); @@ -885,7 +917,9 @@ void PPCLinuxAsmPrinter::EmitStartOfAsmFile(Module 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()) { @@ -897,7 +931,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); Index: lib/Target/PowerPC/PPCISelDAGToDAG.cpp =================================================================== --- lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -27,6 +27,7 @@ #include "llvm/IR/GlobalValue.h" #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/Intrinsics.h" +#include "llvm/IR/Module.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" @@ -273,23 +274,29 @@ SDNode *PPCDAGToDAGISel::getGlobalBaseReg() { // Insert the set of GlobalBaseReg into the first MBB of the function MachineBasicBlock &FirstMBB = MF->front(); MachineBasicBlock::iterator MBBI = FirstMBB.begin(); + const Module *M = MF->getFunction()->getParent(); DebugLoc dl; if (PPCLowering->getPointerTy() == MVT::i32) { - if (PPCSubTarget->isTargetELF()) + if (PPCSubTarget->isTargetELF()) { GlobalBaseReg = PPC::R30; - else + if (M->getPICLevel() == PICLevel::Small) { + BuildMI(FirstMBB, MBBI, dl, TII.get(PPC::MoveGOTtoLR)); + BuildMI(FirstMBB, MBBI, dl, TII.get(PPC::MFLR), GlobalBaseReg); + } else { + BuildMI(FirstMBB, MBBI, dl, TII.get(PPC::MovePCtoLR)); + BuildMI(FirstMBB, MBBI, dl, TII.get(PPC::MFLR), GlobalBaseReg); + unsigned TempReg = RegInfo->createVirtualRegister(&PPC::GPRCRegClass); + BuildMI(FirstMBB, MBBI, dl, + TII.get(PPC::UpdateGBR)).addReg(GlobalBaseReg) + .addReg(TempReg, RegState::Define).addReg(GlobalBaseReg); + MF->getInfo()->setUsesPICBase(true); + } + } else { GlobalBaseReg = RegInfo->createVirtualRegister(&PPC::GPRC_NOR0RegClass); - BuildMI(FirstMBB, MBBI, dl, TII.get(PPC::MovePCtoLR)); - BuildMI(FirstMBB, MBBI, dl, TII.get(PPC::MFLR), GlobalBaseReg); - if (PPCSubTarget->isTargetELF()) { - unsigned TempReg = RegInfo->createVirtualRegister(&PPC::GPRCRegClass); - BuildMI(FirstMBB, MBBI, dl, - TII.get(PPC::GetGBRO), TempReg).addReg(GlobalBaseReg); - BuildMI(FirstMBB, MBBI, dl, - TII.get(PPC::UpdateGBR)).addReg(GlobalBaseReg).addReg(TempReg); - MF->getInfo()->setUsesPICBase(true); + BuildMI(FirstMBB, MBBI, dl, TII.get(PPC::MovePCtoLR)); + BuildMI(FirstMBB, MBBI, dl, TII.get(PPC::MFLR), GlobalBaseReg); } } else { GlobalBaseReg = RegInfo->createVirtualRegister(&PPC::G8RC_NOX0RegClass); @@ -1429,13 +1436,13 @@ SDNode *PPCDAGToDAGISel::Select(SDNode *N) { return CurDAG->SelectNodeTo(N, Reg, MVT::Other, Chain); } case PPCISD::TOC_ENTRY: { + assert ((PPCSubTarget->isPPC64() || PPCSubTarget->isSVR4ABI()) && + "Only supported for 64-bit ABI and 32-bit SVR4"); if (PPCSubTarget->isSVR4ABI() && !PPCSubTarget->isPPC64()) { SDValue GA = N->getOperand(0); return CurDAG->getMachineNode(PPC::LWZtoc, dl, MVT::i32, GA, N->getOperand(1)); } - assert (PPCSubTarget->isPPC64() && - "Only supported for 64-bit ABI and 32-bit SVR4"); // For medium and large code model, we generate two instructions as // described below. Otherwise we allow SelectCodeCommon to handle this, Index: lib/Target/PowerPC/PPCISelLowering.cpp =================================================================== --- lib/Target/PowerPC/PPCISelLowering.cpp +++ lib/Target/PowerPC/PPCISelLowering.cpp @@ -1653,6 +1653,8 @@ SDValue PPCTargetLowering::LowerGlobalTLSAddress(S const GlobalValue *GV = GA->getGlobal(); EVT PtrVT = getPointerTy(); bool is64bit = Subtarget.isPPC64(); + const Module *M = DAG.getMachineFunction().getFunction()->getParent(); + PICLevel::Level picLevel = M->getPICLevel(); TLSModel::Model Model = getTargetMachine().getTLSModel(GV); @@ -1691,7 +1693,10 @@ SDValue PPCTargetLowering::LowerGlobalTLSAddress(S GOTPtr = DAG.getNode(PPCISD::ADDIS_TLSGD_HA, dl, PtrVT, GOTReg, TGA); } else { - GOTPtr = DAG.getNode(PPCISD::PPC32_PICGOT, dl, PtrVT); + if (picLevel == PICLevel::Small) + GOTPtr = DAG.getNode(PPCISD::GlobalBaseReg, dl, PtrVT); + else + GOTPtr = DAG.getNode(PPCISD::PPC32_PICGOT, dl, PtrVT); } SDValue GOTEntry = DAG.getNode(PPCISD::ADDI_TLSGD_L, dl, PtrVT, GOTPtr, TGA); @@ -1721,7 +1726,10 @@ SDValue PPCTargetLowering::LowerGlobalTLSAddress(S GOTPtr = DAG.getNode(PPCISD::ADDIS_TLSLD_HA, dl, PtrVT, GOTReg, TGA); } else { - GOTPtr = DAG.getNode(PPCISD::PPC32_PICGOT, dl, PtrVT); + if (picLevel == PICLevel::Small) + GOTPtr = DAG.getNode(PPCISD::GlobalBaseReg, dl, PtrVT); + else + GOTPtr = DAG.getNode(PPCISD::PPC32_PICGOT, dl, PtrVT); } SDValue GOTEntry = DAG.getNode(PPCISD::ADDI_TLSLD_L, dl, PtrVT, GOTPtr, TGA); Index: lib/Target/PowerPC/PPCInstrInfo.td =================================================================== --- lib/Target/PowerPC/PPCInstrInfo.td +++ lib/Target/PowerPC/PPCInstrInfo.td @@ -976,6 +976,9 @@ let isTerminator = 1, isBarrier = 1, PPC970_Unit = let Defs = [LR] in def MovePCtoLR : Pseudo<(outs), (ins), "#MovePCtoLR", []>, PPC970_Unit_BRU; +let Defs = [LR] in + def MoveGOTtoLR : Pseudo<(outs), (ins), "#MoveGOTtoLR", []>, + PPC970_Unit_BRU; let isBranch = 1, isTerminator = 1, hasCtrlDep = 1, PPC970_Unit = 7 in { let isBarrier = 1 in { @@ -2444,15 +2447,13 @@ def ADDISdtprelHA32 : Pseudo<(outs gprc:$rD), (ins tglobaltlsaddr:$disp))]>; // Support for Position-independent code -def LWZtoc: Pseudo<(outs gprc:$rD), (ins tocentry32:$disp, gprc:$reg), - "#LWZtoc", - [(set i32:$rD, - (PPCtoc_entry tglobaladdr:$disp, i32:$reg))]>; +def LWZtoc : Pseudo<(outs gprc:$rD), (ins tocentry32:$disp, gprc:$reg), + "#LWZtoc", + [(set i32:$rD, + (PPCtoc_entry tglobaladdr:$disp, i32:$reg))]>; // Get Global (GOT) Base Register offset, from the word immediately preceding // the function label. -def GetGBRO: Pseudo<(outs gprc:$rT), (ins gprc:$rI), "#GetGBRO", []>; -// Update the Global(GOT) Base Register with the above offset. -def UpdateGBR: Pseudo<(outs gprc:$rT), (ins gprc:$rI), "#UpdateGBR", []>; +def UpdateGBR : Pseudo<(outs gprc:$rD, gprc:$rT), (ins gprc:$rI), "#UpdateGBR", []>; // Standard shifts. These are represented separately from the real shifts above Index: test/CodeGen/PowerPC/ppc32-pic-large.ll =================================================================== --- test/CodeGen/PowerPC/ppc32-pic-large.ll +++ test/CodeGen/PowerPC/ppc32-pic-large.ll @@ -0,0 +1,23 @@ +; RUN: llc < %s -mtriple=powerpc-unknown-linux-gnu -relocation-model=pic | FileCheck -check-prefix=LARGE-BSS %s +@bar = common global i32 0, align 4 + +define i32 @foo() { +entry: + %0 = load i32* @bar, align 4 + ret i32 %0 +} + +!llvm.module.flags = !{!0} +!0 = metadata !{i32 1, metadata !"PIC Level", i32 2} +; LARGE-BSS: [[POFF:\.L[0-9]+\$poff]]: +; LARGE-BSS-NEXT: .long .LTOC-[[PB:\.L[0-9]+\$pb]] +; LARGE-BSS-NEXT: foo: +; LARGE-BSS: bl [[PB]] +; LARGE-BSS-NEXT: [[PB]]: +; LARGE-BSS: mflr 30 +; LARGE-BSS: lwz [[REG:[0-9]+]], [[POFF]]-[[PB]](30) +; LARGE-BSS-NEXT: add 30, [[REG]], 30 +; LARGE-BSS: lwz [[VREG:[0-9]+]], [[VREF:\.LC[0-9]+]]-.LTOC(30) +; LARGE-BSS: lwz {{[0-9]+}}, 0([[VREG]]) +; LARGE-BSS: [[VREF]]: +; LARGE-BSS-NEXT: .long bar Index: test/CodeGen/PowerPC/ppc32-pic.ll =================================================================== --- test/CodeGen/PowerPC/ppc32-pic.ll +++ test/CodeGen/PowerPC/ppc32-pic.ll @@ -1,21 +1,16 @@ -; RUN: llc < %s -mtriple=powerpc-unknown-linux-gnu -relocation-model=pic | FileCheck %s -@foobar = common global i32 0, align 4 +; RUN: llc < %s -mtriple=powerpc-unknown-linux-gnu -relocation-model=pic | FileCheck -check-prefix=SMALL-BSS %s +@bar = common global i32 0, align 4 define i32 @foo() { entry: - %0 = load i32* @foobar, align 4 + %0 = load i32* @bar, align 4 ret i32 %0 } -; CHECK: [[POFF:\.L[0-9]+\$poff]]: -; CHECK-NEXT: .long .L.TOC.-[[PB:\.L[0-9]+\$pb]] -; CHECK-NEXT: foo: -; CHECK: bl [[PB]] -; CHECK-NEXT: [[PB]]: -; CHECK: mflr 30 -; CHECK: lwz [[REG:[0-9]+]], [[POFF]]-[[PB]](30) -; CHECK-NEXT: add 30, [[REG]], 30 -; CHECK: lwz [[VREG:[0-9]+]], [[VREF:\.LC[0-9]+]]-.L.TOC.(30) -; CHECK: lwz {{[0-9]+}}, 0([[VREG]]) -; CHECK: [[VREF]]: -; CHECK-NEXT: .long foobar +!llvm.module.flags = !{!0} +!0 = metadata !{i32 1, metadata !"PIC Level", i32 1} +; SMALL-BSS-LABEL:foo: +; SMALL-BSS: bl _GLOBAL_OFFSET_TABLE_@local-4 +; SMALL-BSS: mflr 30 +; SMALL-BSS: lwz [[VREG:[0-9]+]], bar@GOT(30) +; SMALL-BSS: lwz {{[0-9]+}}, 0([[VREG]]) Index: test/CodeGen/PowerPC/sections.ll =================================================================== --- test/CodeGen/PowerPC/sections.ll +++ test/CodeGen/PowerPC/sections.ll @@ -1,12 +1,7 @@ ; Test to make sure that bss sections are printed with '.section' directive. ; RUN: llc < %s -mtriple=powerpc-unknown-linux-gnu | FileCheck %s -; RUN: llc < %s -mtriple=powerpc-unknown-linux-gnu -relocation-model=pic | FileCheck %s -check-prefix=PIC @A = global i32 0 ; CHECK: .section .bss,"aw",@nobits ; CHECK: .globl A - -; PIC: .section .got2,"aw",@progbits -; PIC: .section .bss,"aw",@nobits -; PIC: .globl A Index: test/Linker/Inputs/module-flags-pic-1-b.ll =================================================================== --- test/Linker/Inputs/module-flags-pic-1-b.ll +++ test/Linker/Inputs/module-flags-pic-1-b.ll @@ -0,0 +1 @@ + Property changes on: test/Linker/Inputs/module-flags-pic-1-b.ll ___________________________________________________________________ Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: test/Linker/Inputs/module-flags-pic-2-b.ll =================================================================== --- test/Linker/Inputs/module-flags-pic-2-b.ll +++ test/Linker/Inputs/module-flags-pic-2-b.ll @@ -0,0 +1,3 @@ +!0 = metadata !{ i32 1, metadata !"PIC Level", i32 2 } + +!llvm.module.flags = !{!0} Index: test/Linker/module-flags-pic-1-a.ll =================================================================== --- test/Linker/module-flags-pic-1-a.ll +++ test/Linker/module-flags-pic-1-a.ll @@ -0,0 +1,9 @@ +; RUN: llvm-link %s %p/Inputs/module-flags-pic-1-b.ll -S -o - | FileCheck %s + +; test linking modules with specified and default PIC levels + +!0 = metadata !{ i32 1, metadata !"PIC Level", i32 1 } + +!llvm.module.flags = !{!0} +; CHECK: !llvm.module.flags = !{!0} +; CHECK: !0 = metadata !{i32 1, metadata !"PIC Level", i32 1} Index: test/Linker/module-flags-pic-2-a.ll =================================================================== --- test/Linker/module-flags-pic-2-a.ll +++ test/Linker/module-flags-pic-2-a.ll @@ -0,0 +1,10 @@ +; RUN: not llvm-link %s %p/Inputs/module-flags-pic-2-b.ll -S -o - 2> %t +; RUN: FileCheck --check-prefix=CHECK-ERRORS < %t %s + +; test linking modules with two different PIC levels + +!0 = metadata !{ i32 1, metadata !"PIC Level", i32 1 } + +!llvm.module.flags = !{!0} + +; CHECK-ERRORS: linking module flags 'PIC Level': IDs have conflicting values