mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-24 12:19:53 +00:00
[PowerPC] 32-bit ELF PIC support
This adds initial support for PPC32 ELF PIC (Position Independent Code; the -fPIC variety), thus rectifying a long-standing deficiency in the PowerPC backend. Patch by Justin Hibbits! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@213427 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
286fbd19f3
commit
d644d17dd4
@ -458,6 +458,7 @@ enum {
|
||||
R_PPC_GOT16_LO = 15,
|
||||
R_PPC_GOT16_HI = 16,
|
||||
R_PPC_GOT16_HA = 17,
|
||||
R_PPC_PLTREL24 = 18,
|
||||
R_PPC_REL32 = 26,
|
||||
R_PPC_TLS = 67,
|
||||
R_PPC_DTPMOD32 = 68,
|
||||
|
@ -519,6 +519,7 @@ StringRef getELFRelocationTypeName(uint32_t Machine, uint32_t Type) {
|
||||
LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT16_LO);
|
||||
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_REL32);
|
||||
LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_TLS);
|
||||
LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_DTPMOD32);
|
||||
|
@ -83,7 +83,15 @@ unsigned PPCELFObjectWriter::getRelocTypeInner(const MCValue &Target,
|
||||
llvm_unreachable("Unimplemented");
|
||||
case PPC::fixup_ppc_br24:
|
||||
case PPC::fixup_ppc_br24abs:
|
||||
Type = ELF::R_PPC_REL24;
|
||||
switch (Modifier) {
|
||||
default: llvm_unreachable("Unsupported Modifier");
|
||||
case MCSymbolRefExpr::VK_None:
|
||||
Type = ELF::R_PPC_REL24;
|
||||
break;
|
||||
case MCSymbolRefExpr::VK_PLT:
|
||||
Type = ELF::R_PPC_PLTREL24;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case PPC::fixup_ppc_brcond14:
|
||||
case PPC::fixup_ppc_brcond14abs:
|
||||
|
@ -60,10 +60,11 @@ namespace llvm {
|
||||
// PPC Specific MachineOperand flags.
|
||||
MO_NO_FLAG,
|
||||
|
||||
/// MO_DARWIN_STUB - On a symbol operand "FOO", this indicates that the
|
||||
/// reference is actually to the "FOO$stub" symbol. This is used for calls
|
||||
/// and jumps to external functions on Tiger and earlier.
|
||||
MO_DARWIN_STUB = 1,
|
||||
/// MO_PLT_OR_STUB - On a symbol operand "FOO", this indicates that the
|
||||
/// reference is actually to the "FOO$stub" or "FOO@plt" symbol. This is
|
||||
/// used for calls and jumps to external functions on Tiger and earlier, and
|
||||
/// for PIC calls on Linux and ELF systems.
|
||||
MO_PLT_OR_STUB = 1,
|
||||
|
||||
/// MO_PIC_FLAG - If this bit is set, the symbol reference is relative to
|
||||
/// the function's picbase, e.g. lo16(symbol-picbase).
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
#include "PPC.h"
|
||||
#include "InstPrinter/PPCInstPrinter.h"
|
||||
#include "PPCMachineFunctionInfo.h"
|
||||
#include "MCTargetDesc/PPCMCExpr.h"
|
||||
#include "MCTargetDesc/PPCPredicates.h"
|
||||
#include "PPCSubtarget.h"
|
||||
@ -27,6 +28,7 @@
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
#include "llvm/CodeGen/AsmPrinter.h"
|
||||
#include "llvm/CodeGen/MachineConstantPool.h"
|
||||
#include "llvm/CodeGen/MachineFunctionPass.h"
|
||||
#include "llvm/CodeGen/MachineInstr.h"
|
||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||
@ -100,6 +102,7 @@ namespace {
|
||||
}
|
||||
|
||||
bool doFinalization(Module &M) override;
|
||||
void EmitStartOfAsmFile(Module &M) override;
|
||||
|
||||
void EmitFunctionEntryLabel() override;
|
||||
|
||||
@ -330,6 +333,66 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
||||
OutStreamer.EmitLabel(PICBase);
|
||||
return;
|
||||
}
|
||||
case PPC::GetGBRO: {
|
||||
// Get the offset from the GOT Base Register to the GOT
|
||||
LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, Subtarget.isDarwin());
|
||||
MCSymbol *PICOffset = MF->getInfo<PPCFunctionInfo>()->getPICOffsetSymbol();
|
||||
TmpInst.setOpcode(PPC::LWZ);
|
||||
const MCExpr *Exp =
|
||||
MCSymbolRefExpr::Create(PICOffset, MCSymbolRefExpr::VK_None, OutContext);
|
||||
const MCExpr *PB =
|
||||
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);
|
||||
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));
|
||||
EmitToStreamer(OutStreamer, TmpInst);
|
||||
return;
|
||||
}
|
||||
case PPC::LWZtoc: {
|
||||
// Transform %X3 = LWZtoc <ga:@min1>, %X2
|
||||
LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, Subtarget.isDarwin());
|
||||
|
||||
// Change the opcode to LWZ, and the global address operand to be a
|
||||
// reference to the GOT entry we will synthesize later.
|
||||
TmpInst.setOpcode(PPC::LWZ);
|
||||
const MachineOperand &MO = MI->getOperand(1);
|
||||
|
||||
// Map symbol -> label of TOC entry
|
||||
assert(MO.isGlobal() || MO.isCPI() || MO.isJTI());
|
||||
MCSymbol *MOSymbol = nullptr;
|
||||
if (MO.isGlobal())
|
||||
MOSymbol = getSymbol(MO.getGlobal());
|
||||
else if (MO.isCPI())
|
||||
MOSymbol = GetCPISymbol(MO.getIndex());
|
||||
else if (MO.isJTI())
|
||||
MOSymbol = GetJTISymbol(MO.getIndex());
|
||||
|
||||
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);
|
||||
EmitToStreamer(OutStreamer, TmpInst);
|
||||
return;
|
||||
}
|
||||
case PPC::LDtocJTI:
|
||||
case PPC::LDtocCPT:
|
||||
case PPC::LDtoc: {
|
||||
@ -717,9 +780,60 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
||||
EmitToStreamer(OutStreamer, TmpInst);
|
||||
}
|
||||
|
||||
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.");
|
||||
OutStreamer.SwitchSection(OutContext.getELFSection(".got2",
|
||||
ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC,
|
||||
SectionKind::getReadOnly()));
|
||||
|
||||
MCSymbol *TOCSym = OutContext.GetOrCreateSymbol(Twine(".L.TOC."));
|
||||
MCSymbol *CurrentPos = OutContext.CreateTempSymbol();
|
||||
|
||||
OutStreamer.EmitLabel(CurrentPos);
|
||||
|
||||
// The GOT pointer points to the middle of the GOT, in order to reference the
|
||||
// entire 64kB range. 0x8000 is the midpoint.
|
||||
const MCExpr *tocExpr =
|
||||
MCBinaryExpr::CreateAdd(MCSymbolRefExpr::Create(CurrentPos, OutContext),
|
||||
MCConstantExpr::Create(0x8000, OutContext),
|
||||
OutContext);
|
||||
|
||||
OutStreamer.EmitAssignment(TOCSym, tocExpr);
|
||||
|
||||
OutStreamer.SwitchSection(getObjFileLowering().getTextSection());
|
||||
}
|
||||
|
||||
void PPCLinuxAsmPrinter::EmitFunctionEntryLabel() {
|
||||
if (!Subtarget.isPPC64()) // linux/ppc32 - Normal entry label.
|
||||
// linux/ppc32 - Normal entry label.
|
||||
if (!Subtarget.isPPC64() && TM.getRelocationModel() != Reloc::PIC_)
|
||||
return AsmPrinter::EmitFunctionEntryLabel();
|
||||
|
||||
if (!Subtarget.isPPC64()) {
|
||||
const PPCFunctionInfo *PPCFI = MF->getInfo<PPCFunctionInfo>();
|
||||
if (PPCFI->usesPICBase()) {
|
||||
MCSymbol *RelocSymbol = PPCFI->getPICOffsetSymbol();
|
||||
MCSymbol *PICBase = MF->getPICBaseSymbol();
|
||||
OutStreamer.EmitLabel(RelocSymbol);
|
||||
|
||||
const MCExpr *OffsExpr =
|
||||
MCBinaryExpr::CreateSub(
|
||||
MCSymbolRefExpr::Create(OutContext.GetOrCreateSymbol(Twine(".L.TOC.")),
|
||||
OutContext),
|
||||
MCSymbolRefExpr::Create(PICBase, OutContext),
|
||||
OutContext);
|
||||
OutStreamer.EmitValue(OffsExpr, 4);
|
||||
OutStreamer.EmitLabel(CurrentFnSym);
|
||||
return;
|
||||
} else
|
||||
return AsmPrinter::EmitFunctionEntryLabel();
|
||||
}
|
||||
|
||||
// Emit an official procedure descriptor.
|
||||
MCSectionSubPair Current = OutStreamer.getCurrentSection();
|
||||
@ -759,8 +873,15 @@ bool PPCLinuxAsmPrinter::doFinalization(Module &M) {
|
||||
PPCTargetStreamer &TS =
|
||||
static_cast<PPCTargetStreamer &>(*OutStreamer.getTargetStreamer());
|
||||
|
||||
if (isPPC64 && !TOC.empty()) {
|
||||
const MCSectionELF *Section = OutStreamer.getContext().getELFSection(".toc",
|
||||
if (!TOC.empty()) {
|
||||
const MCSectionELF *Section;
|
||||
|
||||
if (isPPC64)
|
||||
Section = OutStreamer.getContext().getELFSection(".toc",
|
||||
ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC,
|
||||
SectionKind::getReadOnly());
|
||||
else
|
||||
Section = OutStreamer.getContext().getELFSection(".got2",
|
||||
ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC,
|
||||
SectionKind::getReadOnly());
|
||||
OutStreamer.SwitchSection(Section);
|
||||
@ -769,7 +890,10 @@ bool PPCLinuxAsmPrinter::doFinalization(Module &M) {
|
||||
E = TOC.end(); I != E; ++I) {
|
||||
OutStreamer.EmitLabel(I->second);
|
||||
MCSymbol *S = OutContext.GetOrCreateSymbol(I->first->getName());
|
||||
TS.emitTCEntry(*S);
|
||||
if (isPPC64)
|
||||
TS.emitTCEntry(*S);
|
||||
else
|
||||
OutStreamer.EmitSymbolValue(S, 4);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -461,7 +461,7 @@ void PPCFrameLowering::replaceFPWithRealFP(MachineFunction &MF) const {
|
||||
const PPCRegisterInfo *RegInfo =
|
||||
static_cast<const PPCRegisterInfo*>(MF.getTarget().getRegisterInfo());
|
||||
bool HasBP = RegInfo->hasBasePointer(MF);
|
||||
unsigned BPReg = HasBP ? (unsigned) PPC::R30 : FPReg;
|
||||
unsigned BPReg = HasBP ? (unsigned) RegInfo->getBaseRegister(MF) : FPReg;
|
||||
unsigned BP8Reg = HasBP ? (unsigned) PPC::X30 : FPReg;
|
||||
|
||||
for (MachineFunction::iterator BI = MF.begin(), BE = MF.end();
|
||||
@ -506,6 +506,7 @@ void PPCFrameLowering::emitPrologue(MachineFunction &MF) const {
|
||||
DebugLoc dl;
|
||||
bool needsFrameMoves = MMI.hasDebugInfo() ||
|
||||
MF.getFunction()->needsUnwindTableEntry();
|
||||
bool isPIC = MF.getTarget().getRelocationModel() == Reloc::PIC_;
|
||||
|
||||
// Get processor type.
|
||||
bool isPPC64 = Subtarget.isPPC64();
|
||||
@ -546,7 +547,7 @@ void PPCFrameLowering::emitPrologue(MachineFunction &MF) const {
|
||||
bool HasBP = RegInfo->hasBasePointer(MF);
|
||||
|
||||
unsigned SPReg = isPPC64 ? PPC::X1 : PPC::R1;
|
||||
unsigned BPReg = isPPC64 ? PPC::X30 : PPC::R30;
|
||||
unsigned BPReg = RegInfo->getBaseRegister(MF);
|
||||
unsigned FPReg = isPPC64 ? PPC::X31 : PPC::R31;
|
||||
unsigned LRReg = isPPC64 ? PPC::LR8 : PPC::LR;
|
||||
unsigned ScratchReg = isPPC64 ? PPC::X0 : PPC::R0;
|
||||
@ -602,7 +603,9 @@ void PPCFrameLowering::emitPrologue(MachineFunction &MF) const {
|
||||
BPOffset = FFI->getObjectOffset(BPIndex);
|
||||
} else {
|
||||
BPOffset =
|
||||
PPCFrameLowering::getBasePointerSaveOffset(isPPC64, isDarwinABI);
|
||||
PPCFrameLowering::getBasePointerSaveOffset(isPPC64,
|
||||
isDarwinABI,
|
||||
isPIC);
|
||||
}
|
||||
}
|
||||
|
||||
@ -839,6 +842,7 @@ void PPCFrameLowering::emitEpilogue(MachineFunction &MF,
|
||||
// Get the ABI.
|
||||
bool isDarwinABI = Subtarget.isDarwinABI();
|
||||
bool isSVR4ABI = Subtarget.isSVR4ABI();
|
||||
bool isPIC = MF.getTarget().getRelocationModel() == Reloc::PIC_;
|
||||
|
||||
// Check if the link register (LR) has been saved.
|
||||
PPCFunctionInfo *FI = MF.getInfo<PPCFunctionInfo>();
|
||||
@ -849,7 +853,7 @@ void PPCFrameLowering::emitEpilogue(MachineFunction &MF,
|
||||
bool HasBP = RegInfo->hasBasePointer(MF);
|
||||
|
||||
unsigned SPReg = isPPC64 ? PPC::X1 : PPC::R1;
|
||||
unsigned BPReg = isPPC64 ? PPC::X30 : PPC::R30;
|
||||
unsigned BPReg = RegInfo->getBaseRegister(MF);
|
||||
unsigned FPReg = isPPC64 ? PPC::X31 : PPC::R31;
|
||||
unsigned ScratchReg = isPPC64 ? PPC::X0 : PPC::R0;
|
||||
unsigned TempReg = isPPC64 ? PPC::X12 : PPC::R12; // another scratch reg
|
||||
@ -890,7 +894,9 @@ void PPCFrameLowering::emitEpilogue(MachineFunction &MF,
|
||||
BPOffset = FFI->getObjectOffset(BPIndex);
|
||||
} else {
|
||||
BPOffset =
|
||||
PPCFrameLowering::getBasePointerSaveOffset(isPPC64, isDarwinABI);
|
||||
PPCFrameLowering::getBasePointerSaveOffset(isPPC64,
|
||||
isDarwinABI,
|
||||
isPIC);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1067,6 +1073,7 @@ PPCFrameLowering::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
||||
int FPSI = FI->getFramePointerSaveIndex();
|
||||
bool isPPC64 = Subtarget.isPPC64();
|
||||
bool isDarwinABI = Subtarget.isDarwinABI();
|
||||
bool isPIC = MF.getTarget().getRelocationModel() == Reloc::PIC_;
|
||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||
|
||||
// If the frame pointer save index hasn't been defined yet.
|
||||
@ -1081,7 +1088,7 @@ PPCFrameLowering::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
||||
|
||||
int BPSI = FI->getBasePointerSaveIndex();
|
||||
if (!BPSI && RegInfo->hasBasePointer(MF)) {
|
||||
int BPOffset = getBasePointerSaveOffset(isPPC64, isDarwinABI);
|
||||
int BPOffset = getBasePointerSaveOffset(isPPC64, isDarwinABI, isPIC);
|
||||
// Allocate the frame index for the base pointer save area.
|
||||
BPSI = MFI->CreateFixedObject(isPPC64? 8 : 4, BPOffset, true);
|
||||
// Save the result.
|
||||
|
@ -97,12 +97,14 @@ public:
|
||||
|
||||
/// getBasePointerSaveOffset - Return the previous frame offset to save the
|
||||
/// base pointer.
|
||||
static unsigned getBasePointerSaveOffset(bool isPPC64, bool isDarwinABI) {
|
||||
static unsigned getBasePointerSaveOffset(bool isPPC64,
|
||||
bool isDarwinABI,
|
||||
bool isPIC) {
|
||||
if (isDarwinABI)
|
||||
return isPPC64 ? -16U : -8U;
|
||||
|
||||
// SVR4 ABI: First slot in the general register save area.
|
||||
return isPPC64 ? -16U : -8U;
|
||||
return isPPC64 ? -16U : isPIC ? -12U : -8U;
|
||||
}
|
||||
|
||||
/// getLinkageSize - Return the size of the PowerPC ABI linkage area.
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
#include "PPC.h"
|
||||
#include "MCTargetDesc/PPCPredicates.h"
|
||||
#include "PPCMachineFunctionInfo.h"
|
||||
#include "PPCTargetMachine.h"
|
||||
#include "llvm/CodeGen/MachineFunction.h"
|
||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||
@ -275,9 +276,21 @@ SDNode *PPCDAGToDAGISel::getGlobalBaseReg() {
|
||||
DebugLoc dl;
|
||||
|
||||
if (PPCLowering->getPointerTy() == MVT::i32) {
|
||||
GlobalBaseReg = RegInfo->createVirtualRegister(&PPC::GPRC_NOR0RegClass);
|
||||
if (PPCSubTarget->isTargetELF())
|
||||
GlobalBaseReg = PPC::R30;
|
||||
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);
|
||||
}
|
||||
} else {
|
||||
GlobalBaseReg = RegInfo->createVirtualRegister(&PPC::G8RC_NOX0RegClass);
|
||||
BuildMI(FirstMBB, MBBI, dl, TII.get(PPC::MovePCtoLR8));
|
||||
@ -1445,7 +1458,13 @@ SDNode *PPCDAGToDAGISel::Select(SDNode *N) {
|
||||
return CurDAG->SelectNodeTo(N, Reg, MVT::Other, Chain);
|
||||
}
|
||||
case PPCISD::TOC_ENTRY: {
|
||||
assert (PPCSubTarget->isPPC64() && "Only supported for 64-bit ABI");
|
||||
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,
|
||||
|
@ -1491,10 +1491,9 @@ static bool GetLabelAccessInfo(const TargetMachine &TM, unsigned &HiOpFlags,
|
||||
HiOpFlags = PPCII::MO_HA;
|
||||
LoOpFlags = PPCII::MO_LO;
|
||||
|
||||
// Don't use the pic base if not in PIC relocation model. Or if we are on a
|
||||
// non-darwin platform. We don't support PIC on other platforms yet.
|
||||
bool isPIC = TM.getRelocationModel() == Reloc::PIC_ &&
|
||||
TM.getSubtarget<PPCSubtarget>().isDarwin();
|
||||
// Don't use the pic base if not in PIC relocation model.
|
||||
bool isPIC = TM.getRelocationModel() == Reloc::PIC_;
|
||||
|
||||
if (isPIC) {
|
||||
HiOpFlags |= PPCII::MO_PIC_FLAG;
|
||||
LoOpFlags |= PPCII::MO_PIC_FLAG;
|
||||
@ -1550,6 +1549,15 @@ SDValue PPCTargetLowering::LowerConstantPool(SDValue Op,
|
||||
|
||||
unsigned MOHiFlag, MOLoFlag;
|
||||
bool isPIC = GetLabelAccessInfo(DAG.getTarget(), MOHiFlag, MOLoFlag);
|
||||
|
||||
if (isPIC && Subtarget.isSVR4ABI()) {
|
||||
SDValue GA = DAG.getTargetConstantPool(C, PtrVT, CP->getAlignment(),
|
||||
PPCII::MO_PIC_FLAG);
|
||||
SDLoc DL(CP);
|
||||
return DAG.getNode(PPCISD::TOC_ENTRY, DL, MVT::i32, GA,
|
||||
DAG.getNode(PPCISD::GlobalBaseReg, DL, PtrVT));
|
||||
}
|
||||
|
||||
SDValue CPIHi =
|
||||
DAG.getTargetConstantPool(C, PtrVT, CP->getAlignment(), 0, MOHiFlag);
|
||||
SDValue CPILo =
|
||||
@ -1571,6 +1579,15 @@ SDValue PPCTargetLowering::LowerJumpTable(SDValue Op, SelectionDAG &DAG) const {
|
||||
|
||||
unsigned MOHiFlag, MOLoFlag;
|
||||
bool isPIC = GetLabelAccessInfo(DAG.getTarget(), MOHiFlag, MOLoFlag);
|
||||
|
||||
if (isPIC && Subtarget.isSVR4ABI()) {
|
||||
SDValue GA = DAG.getTargetJumpTable(JT->getIndex(), PtrVT,
|
||||
PPCII::MO_PIC_FLAG);
|
||||
SDLoc DL(GA);
|
||||
return DAG.getNode(PPCISD::TOC_ENTRY, SDLoc(JT), PtrVT, GA,
|
||||
DAG.getNode(PPCISD::GlobalBaseReg, DL, PtrVT));
|
||||
}
|
||||
|
||||
SDValue JTIHi = DAG.getTargetJumpTable(JT->getIndex(), PtrVT, MOHiFlag);
|
||||
SDValue JTILo = DAG.getTargetJumpTable(JT->getIndex(), PtrVT, MOLoFlag);
|
||||
return LowerLabelRef(JTIHi, JTILo, isPIC, DAG);
|
||||
@ -1700,6 +1717,14 @@ SDValue PPCTargetLowering::LowerGlobalAddress(SDValue Op,
|
||||
unsigned MOHiFlag, MOLoFlag;
|
||||
bool isPIC = GetLabelAccessInfo(DAG.getTarget(), MOHiFlag, MOLoFlag, GV);
|
||||
|
||||
if (isPIC && Subtarget.isSVR4ABI()) {
|
||||
SDValue GA = DAG.getTargetGlobalAddress(GV, DL, PtrVT,
|
||||
GSDN->getOffset(),
|
||||
PPCII::MO_PIC_FLAG);
|
||||
return DAG.getNode(PPCISD::TOC_ENTRY, DL, MVT::i32, GA,
|
||||
DAG.getNode(PPCISD::GlobalBaseReg, DL, MVT::i32));
|
||||
}
|
||||
|
||||
SDValue GAHi =
|
||||
DAG.getTargetGlobalAddress(GV, DL, PtrVT, GSDN->getOffset(), MOHiFlag);
|
||||
SDValue GALo =
|
||||
@ -3357,15 +3382,18 @@ unsigned PrepareCall(SelectionDAG &DAG, SDValue &Callee, SDValue &InFlag,
|
||||
// far-call stubs may be outside relocation limits for a BL instruction.
|
||||
if (!DAG.getTarget().getSubtarget<PPCSubtarget>().isJITCodeModel()) {
|
||||
unsigned OpFlags = 0;
|
||||
if (DAG.getTarget().getRelocationModel() != Reloc::Static &&
|
||||
if ((DAG.getTarget().getRelocationModel() != Reloc::Static &&
|
||||
(Subtarget.getTargetTriple().isMacOSX() &&
|
||||
Subtarget.getTargetTriple().isMacOSXVersionLT(10, 5)) &&
|
||||
(G->getGlobal()->isDeclaration() ||
|
||||
G->getGlobal()->isWeakForLinker())) {
|
||||
G->getGlobal()->isWeakForLinker())) ||
|
||||
(Subtarget.isTargetELF() && !isPPC64 &&
|
||||
!G->getGlobal()->hasLocalLinkage() &&
|
||||
DAG.getTarget().getRelocationModel() == Reloc::PIC_)) {
|
||||
// PC-relative references to external symbols should go through $stub,
|
||||
// unless we're building with the leopard linker or later, which
|
||||
// automatically synthesizes these stubs.
|
||||
OpFlags = PPCII::MO_DARWIN_STUB;
|
||||
OpFlags = PPCII::MO_PLT_OR_STUB;
|
||||
}
|
||||
|
||||
// If the callee is a GlobalAddress/ExternalSymbol node (quite common,
|
||||
@ -3381,13 +3409,15 @@ unsigned PrepareCall(SelectionDAG &DAG, SDValue &Callee, SDValue &InFlag,
|
||||
if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) {
|
||||
unsigned char OpFlags = 0;
|
||||
|
||||
if (DAG.getTarget().getRelocationModel() != Reloc::Static &&
|
||||
(Subtarget.getTargetTriple().isMacOSX() &&
|
||||
Subtarget.getTargetTriple().isMacOSXVersionLT(10, 5))) {
|
||||
if ((DAG.getTarget().getRelocationModel() != Reloc::Static &&
|
||||
(Subtarget.getTargetTriple().isMacOSX() &&
|
||||
Subtarget.getTargetTriple().isMacOSXVersionLT(10, 5))) ||
|
||||
(Subtarget.isTargetELF() && !isPPC64 &&
|
||||
DAG.getTarget().getRelocationModel() == Reloc::PIC_) ) {
|
||||
// PC-relative references to external symbols should go through $stub,
|
||||
// unless we're building with the leopard linker or later, which
|
||||
// automatically synthesizes these stubs.
|
||||
OpFlags = PPCII::MO_DARWIN_STUB;
|
||||
OpFlags = PPCII::MO_PLT_OR_STUB;
|
||||
}
|
||||
|
||||
Callee = DAG.getTargetExternalSymbol(S->getSymbol(), Callee.getValueType(),
|
||||
@ -6613,7 +6643,10 @@ PPCTargetLowering::emitEHSjLjLongJmp(MachineInstr *MI,
|
||||
// Since FP is only updated here but NOT referenced, it's treated as GPR.
|
||||
unsigned FP = (PVT == MVT::i64) ? PPC::X31 : PPC::R31;
|
||||
unsigned SP = (PVT == MVT::i64) ? PPC::X1 : PPC::R1;
|
||||
unsigned BP = (PVT == MVT::i64) ? PPC::X30 : PPC::R30;
|
||||
unsigned BP = (PVT == MVT::i64) ? PPC::X30 :
|
||||
(Subtarget.isSVR4ABI() &&
|
||||
MF->getTarget().getRelocationModel() == Reloc::PIC_ ?
|
||||
PPC::R29 : PPC::R30);
|
||||
|
||||
MachineInstrBuilder MIB;
|
||||
|
||||
|
@ -57,6 +57,9 @@ def SDT_PPCTC_ret : SDTypeProfile<0, 2, [
|
||||
SDTCisPtrTy<0>, SDTCisVT<1, i32>
|
||||
]>;
|
||||
|
||||
def tocentry32 : Operand<iPTR> {
|
||||
let MIOperandInfo = (ops i32imm:$imm);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// PowerPC specific DAG Nodes.
|
||||
@ -2400,6 +2403,18 @@ def LDgotTprelL32: Pseudo<(outs gprc:$rD), (ins s16imm:$disp, gprc_nor0:$reg),
|
||||
def : Pat<(PPCaddTls i32:$in, tglobaltlsaddr:$g),
|
||||
(ADD4TLS $in, tglobaltlsaddr:$g)>;
|
||||
|
||||
// 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))]>;
|
||||
// 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", []>;
|
||||
|
||||
|
||||
// Standard shifts. These are represented separately from the real shifts above
|
||||
// so that we can distinguish between shifts that allow 5-bit and 6-bit shift
|
||||
// amounts.
|
||||
|
@ -13,6 +13,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "PPC.h"
|
||||
#include "PPCSubtarget.h"
|
||||
#include "MCTargetDesc/PPCMCExpr.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/ADT/Twine.h"
|
||||
@ -39,12 +40,14 @@ static MCSymbol *GetSymbolFromOperand(const MachineOperand &MO, AsmPrinter &AP){
|
||||
Mangler *Mang = AP.Mang;
|
||||
const DataLayout *DL = TM.getDataLayout();
|
||||
MCContext &Ctx = AP.OutContext;
|
||||
bool isDarwin = TM.getSubtarget<PPCSubtarget>().isDarwin();
|
||||
|
||||
SmallString<128> Name;
|
||||
StringRef Suffix;
|
||||
if (MO.getTargetFlags() == PPCII::MO_DARWIN_STUB)
|
||||
Suffix = "$stub";
|
||||
else if (MO.getTargetFlags() & PPCII::MO_NLP_FLAG)
|
||||
if (MO.getTargetFlags() == PPCII::MO_PLT_OR_STUB) {
|
||||
if (isDarwin)
|
||||
Suffix = "$stub";
|
||||
} else if (MO.getTargetFlags() & PPCII::MO_NLP_FLAG)
|
||||
Suffix = "$non_lazy_ptr";
|
||||
|
||||
if (!Suffix.empty())
|
||||
@ -68,7 +71,7 @@ static MCSymbol *GetSymbolFromOperand(const MachineOperand &MO, AsmPrinter &AP){
|
||||
|
||||
// If the target flags on the operand changes the name of the symbol, do that
|
||||
// before we return the symbol.
|
||||
if (MO.getTargetFlags() == PPCII::MO_DARWIN_STUB) {
|
||||
if (MO.getTargetFlags() == PPCII::MO_PLT_OR_STUB && isDarwin) {
|
||||
MachineModuleInfoImpl::StubValueTy &StubSym =
|
||||
getMachOMMI(AP).getFnStubEntry(Sym);
|
||||
if (StubSym.getPointer())
|
||||
@ -136,6 +139,9 @@ static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol,
|
||||
break;
|
||||
}
|
||||
|
||||
if (MO.getTargetFlags() == PPCII::MO_PLT_OR_STUB && !isDarwin)
|
||||
RefKind = MCSymbolRefExpr::VK_PLT;
|
||||
|
||||
const MCExpr *Expr = MCSymbolRefExpr::Create(Symbol, RefKind, Ctx);
|
||||
|
||||
if (!MO.isJTI() && MO.getOffset())
|
||||
|
@ -8,8 +8,16 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "PPCMachineFunctionInfo.h"
|
||||
#include "llvm/IR/DataLayout.h"
|
||||
#include "llvm/MC/MCContext.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
void PPCFunctionInfo::anchor() { }
|
||||
|
||||
MCSymbol *PPCFunctionInfo::getPICOffsetSymbol() const {
|
||||
const DataLayout *DL = MF.getTarget().getDataLayout();
|
||||
return MF.getContext().GetOrCreateSymbol(Twine(DL->getPrivateGlobalPrefix())+
|
||||
Twine(MF.getFunctionNumber())+"$poff");
|
||||
}
|
||||
|
@ -92,6 +92,12 @@ class PPCFunctionInfo : public MachineFunctionInfo {
|
||||
/// 64-bit SVR4 ABI.
|
||||
SmallVector<unsigned, 3> MustSaveCRs;
|
||||
|
||||
/// Hold onto our MachineFunction context.
|
||||
MachineFunction &MF;
|
||||
|
||||
/// Whether this uses the PIC Base register or not.
|
||||
bool UsesPICBase;
|
||||
|
||||
public:
|
||||
explicit PPCFunctionInfo(MachineFunction &MF)
|
||||
: FramePointerSaveIndex(0),
|
||||
@ -109,7 +115,9 @@ public:
|
||||
VarArgsStackOffset(0),
|
||||
VarArgsNumGPR(0),
|
||||
VarArgsNumFPR(0),
|
||||
CRSpillFrameIndex(0) {}
|
||||
CRSpillFrameIndex(0),
|
||||
MF(MF),
|
||||
UsesPICBase(0) {}
|
||||
|
||||
int getFramePointerSaveIndex() const { return FramePointerSaveIndex; }
|
||||
void setFramePointerSaveIndex(int Idx) { FramePointerSaveIndex = Idx; }
|
||||
@ -170,6 +178,11 @@ public:
|
||||
const SmallVectorImpl<unsigned> &
|
||||
getMustSaveCRs() const { return MustSaveCRs; }
|
||||
void addMustSaveCR(unsigned Reg) { MustSaveCRs.push_back(Reg); }
|
||||
|
||||
void setUsesPICBase(bool uses) { UsesPICBase = uses; }
|
||||
bool usesPICBase() const { return UsesPICBase; }
|
||||
|
||||
MCSymbol *getPICOffsetSymbol() const;
|
||||
};
|
||||
|
||||
} // end of namespace llvm
|
||||
|
@ -199,7 +199,16 @@ BitVector PPCRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
|
||||
if (PPCFI->needsFP(MF))
|
||||
Reserved.set(PPC::R31);
|
||||
|
||||
if (hasBasePointer(MF))
|
||||
if (hasBasePointer(MF)) {
|
||||
if (Subtarget.isSVR4ABI() && !Subtarget.isPPC64() &&
|
||||
MF.getTarget().getRelocationModel() == Reloc::PIC_)
|
||||
Reserved.set(PPC::R29);
|
||||
else
|
||||
Reserved.set(PPC::R30);
|
||||
}
|
||||
|
||||
if (Subtarget.isSVR4ABI() && !Subtarget.isPPC64() &&
|
||||
MF.getTarget().getRelocationModel() == Reloc::PIC_)
|
||||
Reserved.set(PPC::R30);
|
||||
|
||||
// Reserve Altivec registers when Altivec is unavailable.
|
||||
@ -843,7 +852,14 @@ unsigned PPCRegisterInfo::getBaseRegister(const MachineFunction &MF) const {
|
||||
if (!hasBasePointer(MF))
|
||||
return getFrameRegister(MF);
|
||||
|
||||
return Subtarget.isPPC64() ? PPC::X30 : PPC::R30;
|
||||
if (Subtarget.isPPC64())
|
||||
return PPC::X30;
|
||||
|
||||
if (Subtarget.isSVR4ABI() &&
|
||||
MF.getTarget().getRelocationModel() == Reloc::PIC_)
|
||||
return PPC::R29;
|
||||
|
||||
return PPC::R30;
|
||||
}
|
||||
|
||||
bool PPCRegisterInfo::hasBasePointer(const MachineFunction &MF) const {
|
||||
|
@ -222,6 +222,9 @@ public:
|
||||
/// isBGQ - True if this is a BG/Q platform.
|
||||
bool isBGQ() const { return TargetTriple.getVendor() == Triple::BGQ; }
|
||||
|
||||
bool isTargetELF() const { return TargetTriple.isOSBinFormatELF(); }
|
||||
bool isTargetMachO() const { return TargetTriple.isOSBinFormatMachO(); }
|
||||
|
||||
bool isDarwinABI() const { return isDarwin(); }
|
||||
bool isSVR4ABI() const { return !isDarwin(); }
|
||||
|
||||
|
@ -1,7 +1,8 @@
|
||||
; RUN: llc < %s -relocation-model=static | FileCheck %s -check-prefix=STATIC
|
||||
; RUN: llc < %s -relocation-model=pic | FileCheck %s -check-prefix=PIC
|
||||
; RUN: llc < %s -relocation-model=pic -mtriple=powerpc-apple-darwin8 | FileCheck %s -check-prefix=PIC
|
||||
; RUN: llc < %s -relocation-model=pic -mtriple=powerpc-unknown-linux | FileCheck %s -check-prefix=PICELF
|
||||
; RUN: llc < %s -relocation-model=pic -mtriple=powerpc64-apple-darwin8 | FileCheck %s -check-prefix=PIC64
|
||||
; RUN: llc < %s -relocation-model=dynamic-no-pic | FileCheck %s -check-prefix=DYNAMIC
|
||||
; RUN: llc < %s -relocation-model=dynamic-no-pic -mtriple=powerpc-apple-darwin8 | FileCheck %s -check-prefix=DYNAMIC
|
||||
; RUN: llc < %s -relocation-model=dynamic-no-pic -mtriple=powerpc64-apple-darwin8 | FileCheck %s -check-prefix=DYNAMIC64
|
||||
; PR4482
|
||||
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
|
||||
@ -18,6 +19,10 @@ entry:
|
||||
; PIC: bl L_exact_log2$stub
|
||||
; PIC: blr
|
||||
|
||||
; PICELF: foo:
|
||||
; PICELF: bl exact_log2@PLT
|
||||
; PICELF: blr
|
||||
|
||||
; PIC64: _foo:
|
||||
; PIC64: bl L_exact_log2$stub
|
||||
; PIC64: blr
|
||||
|
21
test/CodeGen/PowerPC/ppc32-pic.ll
Normal file
21
test/CodeGen/PowerPC/ppc32-pic.ll
Normal file
@ -0,0 +1,21 @@
|
||||
; RUN: llc < %s -mtriple=powerpc-unknown-linux-gnu -relocation-model=pic | FileCheck %s
|
||||
@foobar = common global i32 0, align 4
|
||||
|
||||
define i32 @foo() {
|
||||
entry:
|
||||
%0 = load i32* @foobar, 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
|
@ -1,8 +1,12 @@
|
||||
; 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
|
||||
|
@ -1,5 +1,7 @@
|
||||
; RUN: llc -mtriple=powerpc64-unknown-linux-gnu -mcpu=pwr7 < %s | FileCheck %s
|
||||
; RUN: llc -mtriple=powerpc64-unknown-linux-gnu -mcpu=pwr7 -disable-fp-elim < %s | FileCheck -check-prefix=CHECK-FP %s
|
||||
; RUN: llc -mtriple=powerpc-unknown-linux-gnu -disable-fp-elim < %s | FileCheck -check-prefix=CHECK-32 %s
|
||||
; RUN: llc -mtriple=powerpc-unknown-linux-gnu -disable-fp-elim -relocation-model=pic < %s | FileCheck -check-prefix=CHECK-32-PIC %s
|
||||
target datalayout = "E-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-f128:128:128-v128:128:128-n32:64"
|
||||
target triple = "powerpc64-unknown-linux-gnu"
|
||||
|
||||
@ -7,6 +9,8 @@ target triple = "powerpc64-unknown-linux-gnu"
|
||||
|
||||
declare void @bar(i32*)
|
||||
|
||||
@barbaz = external global i32
|
||||
|
||||
define void @goo(%struct.s* byval nocapture readonly %a) {
|
||||
entry:
|
||||
%x = alloca [2 x i32], align 32
|
||||
@ -16,8 +20,9 @@ entry:
|
||||
store i32 %0, i32* %arrayidx, align 32
|
||||
%b = getelementptr inbounds %struct.s* %a, i64 0, i32 1
|
||||
%1 = load i32* %b, align 4
|
||||
%2 = load i32* @barbaz, align 4
|
||||
%arrayidx2 = getelementptr inbounds [2 x i32]* %x, i64 0, i64 1
|
||||
store i32 %1, i32* %arrayidx2, align 4
|
||||
store i32 %2, i32* %arrayidx2, align 4
|
||||
call void @bar(i32* %arrayidx)
|
||||
ret void
|
||||
}
|
||||
@ -69,6 +74,24 @@ entry:
|
||||
; CHECK-FP-DAG: mtlr 0
|
||||
; CHECK-FP: blr
|
||||
|
||||
; CHECK-32-LABEL: @goo
|
||||
; CHECK-32-DAG: mflr 0
|
||||
; CHECK-32-DAG: rlwinm [[REG:[0-9]+]], 1, 0, 27, 31
|
||||
; CHECK-32-DAG: stw 30, -8(1)
|
||||
; CHECK-32-DAG: mr 30, 1
|
||||
; CHECK-32-DAG: stw 0, 4(1)
|
||||
; CHECK-32-DAG: subfic 0, [[REG]], -64
|
||||
; CHECK-32: stwux 1, 1, 0
|
||||
|
||||
; CHECK-32-PIC-LABEL: @goo
|
||||
; CHECK-32-PIC-DAG: mflr 0
|
||||
; CHECK-32-PIC-DAG: rlwinm [[REG:[0-9]+]], 1, 0, 27, 31
|
||||
; CHECK-32-PIC-DAG: stw 29, -12(1)
|
||||
; CHECK-32-PIC-DAG: mr 29, 1
|
||||
; CHECK-32-PIC-DAG: stw 0, 4(1)
|
||||
; CHECK-32-PIC-DAG: subfic 0, [[REG]], -64
|
||||
; CHECK-32-PIC: stwux 1, 1, 0
|
||||
|
||||
; The large-frame-size case.
|
||||
define void @hoo(%struct.s* byval nocapture readonly %a) {
|
||||
entry:
|
||||
@ -99,6 +122,34 @@ entry:
|
||||
|
||||
; CHECK: blr
|
||||
|
||||
; CHECK-32-LABEL: @hoo
|
||||
|
||||
; CHECK-32-DAG: lis [[REG1:[0-9]+]], -13
|
||||
; CHECK-32-DAG: rlwinm [[REG3:[0-9]+]], 1, 0, 27, 31
|
||||
; CHECK-32-DAG: mflr 0
|
||||
; CHECK-32-DAG: ori [[REG2:[0-9]+]], [[REG1]], 51904
|
||||
; CHECK-32-DAG: stw 30, -8(1)
|
||||
; CHECK-32-DAG: mr 30, 1
|
||||
; CHECK-32-DAG: stw 0, 4(1)
|
||||
; CHECK-32-DAG: subfc 0, [[REG3]], [[REG2]]
|
||||
; CHECK-32: stwux 1, 1, 0
|
||||
|
||||
; CHECK-32: blr
|
||||
|
||||
; CHECK-32-PIC-LABEL: @hoo
|
||||
|
||||
; CHECK-32-PIC-DAG: lis [[REG1:[0-9]+]], -13
|
||||
; CHECK-32-PIC-DAG: rlwinm [[REG3:[0-9]+]], 1, 0, 27, 31
|
||||
; CHECK-32-PIC-DAG: mflr 0
|
||||
; CHECK-32-PIC-DAG: ori [[REG2:[0-9]+]], [[REG1]], 51904
|
||||
; CHECK-32-PIC-DAG: stw 29, -12(1)
|
||||
; CHECK-32-PIC-DAG: mr 29, 1
|
||||
; CHECK-32-PIC-DAG: stw 0, 4(1)
|
||||
; CHECK-32-PIC-DAG: subfc 0, [[REG3]], [[REG2]]
|
||||
; CHECK-32: stwux 1, 1, 0
|
||||
|
||||
; CHECK-32: blr
|
||||
|
||||
; Make sure that the FP save area is still allocated correctly relative to
|
||||
; where r30 is saved.
|
||||
define void @loo(%struct.s* byval nocapture readonly %a) {
|
||||
|
17
test/MC/PowerPC/ppc-reloc.s
Normal file
17
test/MC/PowerPC/ppc-reloc.s
Normal file
@ -0,0 +1,17 @@
|
||||
# RUN: llvm-mc -triple=powerpc-unknown-linux-gnu -filetype=obj %s | \
|
||||
# RUN: llvm-readobj -r | FileCheck %s
|
||||
.section .text
|
||||
|
||||
.globl foo
|
||||
.type foo,@function
|
||||
.align 2
|
||||
foo:
|
||||
bl printf@plt
|
||||
.LC1:
|
||||
.size foo, . - foo
|
||||
|
||||
# CHECK: Relocations [
|
||||
# CHECK-NEXT: Section (2) .rela.text {
|
||||
# CHECK-NEXT: 0x0 R_PPC_PLTREL24 printf 0x0
|
||||
# CHECK-NEXT: }
|
||||
# CHECK-NEXT: ]
|
Loading…
Reference in New Issue
Block a user