721 lines
29 KiB
Diff
721 lines
29 KiB
Diff
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 <system_error>
|
|
|
|
@@ -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<PICLevel::Level>(cast<ConstantInt>(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<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);
|
|
@@ -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 <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.
|
|
@@ -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 <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.
|
|
@@ -428,7 +462,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineI
|
|
|
|
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
|
|
@@ -470,7 +504,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineI
|
|
}
|
|
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
|
|
@@ -507,7 +541,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineI
|
|
}
|
|
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
|
|
@@ -558,7 +592,7 @@ void PPCAsmPrinter::EmitInstruction(const MachineI
|
|
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);
|
|
@@ -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<PPCFunctionInfo>()->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<PPCFunctionInfo>()->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
|