mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-27 14:34:58 +00:00
[arm-fast-isel] Add support for ELF PIC.
This is a preliminary step towards ELF support; currently ARMFastISel hasn't been used for ELF object files yet. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@164759 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
5e92990703
commit
8f50647662
@ -37,6 +37,7 @@ FunctionPass *createARMJITCodeEmitterPass(ARMBaseTargetMachine &TM,
|
||||
|
||||
FunctionPass *createARMLoadStoreOptimizationPass(bool PreAlloc = false);
|
||||
FunctionPass *createARMExpandPseudoPass();
|
||||
FunctionPass *createARMGlobalBaseRegPass();
|
||||
FunctionPass *createARMGlobalMergePass(const TargetLowering* tli);
|
||||
FunctionPass *createARMConstantIslandPass();
|
||||
FunctionPass *createMLxExpansionPass();
|
||||
|
@ -194,6 +194,7 @@ class ARMFastISel : public FastISel {
|
||||
unsigned ARMMoveToFPReg(EVT VT, unsigned SrcReg);
|
||||
unsigned ARMMoveToIntReg(EVT VT, unsigned SrcReg);
|
||||
unsigned ARMSelectCallOp(bool UseReg);
|
||||
unsigned ARMLowerPICELF(const GlobalValue *GV, unsigned Align, EVT VT);
|
||||
|
||||
// Call handling routines.
|
||||
private:
|
||||
@ -648,6 +649,9 @@ unsigned ARMFastISel::ARMMaterializeGV(const GlobalValue *GV, EVT VT) {
|
||||
Align = TD.getTypeAllocSize(GV->getType());
|
||||
}
|
||||
|
||||
if (Subtarget->isTargetELF() && RelocM == Reloc::PIC_)
|
||||
return ARMLowerPICELF(GV, Align, VT);
|
||||
|
||||
// Grab index.
|
||||
unsigned PCAdj = (RelocM != Reloc::PIC_) ? 0 :
|
||||
(Subtarget->isThumb() ? 4 : 8);
|
||||
@ -2796,6 +2800,47 @@ bool ARMFastISel::TryToFoldLoad(MachineInstr *MI, unsigned OpNo,
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned ARMFastISel::ARMLowerPICELF(const GlobalValue *GV,
|
||||
unsigned Align, EVT VT) {
|
||||
bool UseGOTOFF = GV->hasLocalLinkage() || GV->hasHiddenVisibility();
|
||||
ARMConstantPoolConstant *CPV =
|
||||
ARMConstantPoolConstant::Create(GV, UseGOTOFF ? ARMCP::GOTOFF : ARMCP::GOT);
|
||||
unsigned Idx = MCP.getConstantPoolIndex(CPV, Align);
|
||||
|
||||
unsigned Opc;
|
||||
unsigned DestReg1 = createResultReg(TLI.getRegClassFor(VT));
|
||||
// Load value.
|
||||
if (isThumb2) {
|
||||
AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DL,
|
||||
TII.get(ARM::t2LDRpci), DestReg1)
|
||||
.addConstantPoolIndex(Idx));
|
||||
Opc = UseGOTOFF ? ARM::t2ADDrr : ARM::t2LDRs;
|
||||
} else {
|
||||
// The extra immediate is for addrmode2.
|
||||
AddOptionalDefs(BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt,
|
||||
DL, TII.get(ARM::LDRcp), DestReg1)
|
||||
.addConstantPoolIndex(Idx).addImm(0));
|
||||
Opc = UseGOTOFF ? ARM::ADDrr : ARM::LDRrs;
|
||||
}
|
||||
|
||||
unsigned GlobalBaseReg = AFI->getGlobalBaseReg();
|
||||
if (GlobalBaseReg == 0) {
|
||||
GlobalBaseReg = MRI.createVirtualRegister(TLI.getRegClassFor(VT));
|
||||
AFI->setGlobalBaseReg(GlobalBaseReg);
|
||||
}
|
||||
|
||||
unsigned DestReg2 = createResultReg(TLI.getRegClassFor(VT));
|
||||
MachineInstrBuilder MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt,
|
||||
DL, TII.get(Opc), DestReg2)
|
||||
.addReg(DestReg1)
|
||||
.addReg(GlobalBaseReg);
|
||||
if (!UseGOTOFF)
|
||||
MIB.addImm(0);
|
||||
AddOptionalDefs(MIB);
|
||||
|
||||
return DestReg2;
|
||||
}
|
||||
|
||||
namespace llvm {
|
||||
FastISel *ARM::createFastISel(FunctionLoweringInfo &funcInfo,
|
||||
const TargetLibraryInfo *libInfo) {
|
||||
|
@ -13,13 +13,17 @@
|
||||
|
||||
#include "ARMInstrInfo.h"
|
||||
#include "ARM.h"
|
||||
#include "ARMConstantPoolValue.h"
|
||||
#include "ARMMachineFunctionInfo.h"
|
||||
#include "ARMTargetMachine.h"
|
||||
#include "MCTargetDesc/ARMAddressingModes.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/CodeGen/LiveVariables.h"
|
||||
#include "llvm/CodeGen/MachineFrameInfo.h"
|
||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||
#include "llvm/CodeGen/MachineJumpTableInfo.h"
|
||||
#include "llvm/Function.h"
|
||||
#include "llvm/GlobalVariable.h"
|
||||
#include "llvm/MC/MCAsmInfo.h"
|
||||
#include "llvm/MC/MCInst.h"
|
||||
using namespace llvm;
|
||||
@ -84,3 +88,61 @@ unsigned ARMInstrInfo::getUnindexedOpcode(unsigned Opc) const {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
namespace {
|
||||
/// ARMCGBR - Create Global Base Reg pass. This initializes the PIC
|
||||
/// global base register for ARM ELF.
|
||||
struct ARMCGBR : public MachineFunctionPass {
|
||||
static char ID;
|
||||
ARMCGBR() : MachineFunctionPass(ID) {}
|
||||
|
||||
virtual bool runOnMachineFunction(MachineFunction &MF) {
|
||||
ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
|
||||
if (AFI->getGlobalBaseReg() == 0)
|
||||
return false;
|
||||
|
||||
const ARMTargetMachine *TM =
|
||||
static_cast<const ARMTargetMachine *>(&MF.getTarget());
|
||||
if (TM->getRelocationModel() != Reloc::PIC_)
|
||||
return false;
|
||||
|
||||
LLVMContext* Context = &MF.getFunction()->getContext();
|
||||
GlobalValue *GV = new GlobalVariable(Type::getInt32Ty(*Context), false,
|
||||
GlobalValue::ExternalLinkage, 0,
|
||||
"_GLOBAL_OFFSET_TABLE_");
|
||||
unsigned Id = AFI->createPICLabelUId();
|
||||
ARMConstantPoolValue *CPV = ARMConstantPoolConstant::Create(GV, Id);
|
||||
unsigned Align = TM->getTargetData()->getPrefTypeAlignment(GV->getType());
|
||||
unsigned Idx = MF.getConstantPool()->getConstantPoolIndex(CPV, Align);
|
||||
|
||||
MachineBasicBlock &FirstMBB = MF.front();
|
||||
MachineBasicBlock::iterator MBBI = FirstMBB.begin();
|
||||
DebugLoc DL = FirstMBB.findDebugLoc(MBBI);
|
||||
unsigned GlobalBaseReg = AFI->getGlobalBaseReg();
|
||||
unsigned Opc = TM->getSubtarget<ARMSubtarget>().isThumb2() ?
|
||||
ARM::t2LDRpci : ARM::LDRcp;
|
||||
const TargetInstrInfo &TII = *TM->getInstrInfo();
|
||||
MachineInstrBuilder MIB = BuildMI(FirstMBB, MBBI, DL,
|
||||
TII.get(Opc), GlobalBaseReg)
|
||||
.addConstantPoolIndex(Idx);
|
||||
if (Opc == ARM::LDRcp)
|
||||
MIB.addImm(0);
|
||||
AddDefaultPred(MIB);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual const char *getPassName() const {
|
||||
return "ARM PIC Global Base Reg Initialization";
|
||||
}
|
||||
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.setPreservesCFG();
|
||||
MachineFunctionPass::getAnalysisUsage(AU);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
char ARMCGBR::ID = 0;
|
||||
FunctionPass*
|
||||
llvm::createARMGlobalBaseRegPass() { return new ARMCGBR(); }
|
||||
|
@ -108,6 +108,11 @@ class ARMFunctionInfo : public MachineFunctionInfo {
|
||||
/// pass.
|
||||
DenseMap<unsigned, unsigned> CPEClones;
|
||||
|
||||
/// GlobalBaseReg - keeps track of the virtual register initialized for
|
||||
/// use as the global base register. This is used for PIC in some PIC
|
||||
/// relocation models.
|
||||
unsigned GlobalBaseReg;
|
||||
|
||||
public:
|
||||
ARMFunctionInfo() :
|
||||
isThumb(false),
|
||||
@ -119,7 +124,7 @@ public:
|
||||
GPRCS1Frames(0), GPRCS2Frames(0), DPRCSFrames(0),
|
||||
NumAlignedDPRCS2Regs(0),
|
||||
JumpTableUId(0), PICLabelUId(0),
|
||||
VarArgsFrameIndex(0), HasITBlocks(false) {}
|
||||
VarArgsFrameIndex(0), HasITBlocks(false), GlobalBaseReg(0) {}
|
||||
|
||||
explicit ARMFunctionInfo(MachineFunction &MF) :
|
||||
isThumb(MF.getTarget().getSubtarget<ARMSubtarget>().isThumb()),
|
||||
@ -130,7 +135,7 @@ public:
|
||||
GPRCS1Size(0), GPRCS2Size(0), DPRCSSize(0),
|
||||
GPRCS1Frames(32), GPRCS2Frames(32), DPRCSFrames(32),
|
||||
JumpTableUId(0), PICLabelUId(0),
|
||||
VarArgsFrameIndex(0), HasITBlocks(false) {}
|
||||
VarArgsFrameIndex(0), HasITBlocks(false), GlobalBaseReg(0) {}
|
||||
|
||||
bool isThumbFunction() const { return isThumb; }
|
||||
bool isThumb1OnlyFunction() const { return isThumb && !hasThumb2; }
|
||||
@ -249,6 +254,9 @@ public:
|
||||
bool hasITBlocks() const { return HasITBlocks; }
|
||||
void setHasITBlocks(bool h) { HasITBlocks = h; }
|
||||
|
||||
unsigned getGlobalBaseReg() const { return GlobalBaseReg; }
|
||||
void setGlobalBaseReg(unsigned Reg) { GlobalBaseReg = Reg; }
|
||||
|
||||
void recordCPEClone(unsigned CPIdx, unsigned CPCloneIdx) {
|
||||
if (!CPEClones.insert(std::make_pair(CPCloneIdx, CPIdx)).second)
|
||||
assert(0 && "Duplicate entries!");
|
||||
|
@ -143,6 +143,11 @@ bool ARMPassConfig::addPreISel() {
|
||||
|
||||
bool ARMPassConfig::addInstSelector() {
|
||||
addPass(createARMISelDag(getARMTargetMachine(), getOptLevel()));
|
||||
|
||||
const ARMSubtarget *Subtarget = &getARMSubtarget();
|
||||
if (Subtarget->isTargetELF() && !Subtarget->isThumb1Only() &&
|
||||
TM->Options.EnableFastISel)
|
||||
addPass(createARMGlobalBaseRegPass());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
; RUN: llc < %s -O0 -fast-isel-abort -relocation-model=pic -mtriple=thumbv7-apple-ios | FileCheck %s --check-prefix=THUMB
|
||||
; RUN: llc < %s -O0 -fast-isel-abort -relocation-model=pic -mtriple=arm-apple-ios | FileCheck %s --check-prefix=ARM
|
||||
; RUN: llc < %s -O0 -fast-isel-abort -relocation-model=pic -mtriple=armv7-apple-ios | FileCheck %s --check-prefix=ARMv7
|
||||
; RUN: llc < %s -O0 -fast-isel-abort -relocation-model=pic -mtriple=thumbv7-none-linux-gnueabi | FileCheck %s --check-prefix=THUMB-ELF
|
||||
; RUN: llc < %s -O0 -fast-isel-abort -relocation-model=pic -mtriple=armv7-none-linux-gnueabi | FileCheck %s --check-prefix=ARMv7-ELF
|
||||
|
||||
@g = global i32 0, align 4
|
||||
|
||||
@ -10,6 +12,10 @@ entry:
|
||||
; THUMB: movw [[reg0:r[0-9]+]],
|
||||
; THUMB: movt [[reg0]],
|
||||
; THUMB: add [[reg0]], pc
|
||||
; THUMB-ELF: LoadGV
|
||||
; THUMB-ELF: ldr.n r[[reg0:[0-9]+]],
|
||||
; THUMB-ELF: ldr.n r[[reg1:[0-9]+]],
|
||||
; THUMB-ELF: ldr r[[reg0]], [r[[reg1]], r[[reg0]]]
|
||||
; ARM: LoadGV
|
||||
; ARM: ldr [[reg1:r[0-9]+]],
|
||||
; ARM: add [[reg1]], pc, [[reg1]]
|
||||
@ -17,6 +23,10 @@ entry:
|
||||
; ARMv7: movw [[reg2:r[0-9]+]],
|
||||
; ARMv7: movt [[reg2]],
|
||||
; ARMv7: add [[reg2]], pc, [[reg2]]
|
||||
; ARMv7-ELF: LoadGV
|
||||
; ARMv7-ELF: ldr r[[reg2:[0-9]+]],
|
||||
; ARMv7-ELF: ldr r[[reg3:[0-9]+]],
|
||||
; ARMv7-ELF: ldr r[[reg2]], [r[[reg3]], r[[reg2]]]
|
||||
%tmp = load i32* @g
|
||||
ret i32 %tmp
|
||||
}
|
||||
@ -30,6 +40,10 @@ entry:
|
||||
; THUMB: movt r[[reg3]],
|
||||
; THUMB: add r[[reg3]], pc
|
||||
; THUMB: ldr r[[reg3]], [r[[reg3]]]
|
||||
; THUMB-ELF: LoadIndirectSymbol
|
||||
; THUMB-ELF: ldr.n r[[reg3:[0-9]+]],
|
||||
; THUMB-ELF: ldr.n r[[reg4:[0-9]+]],
|
||||
; THUMB-ELF: ldr r[[reg3]], [r[[reg4]], r[[reg3]]]
|
||||
; ARM: LoadIndirectSymbol
|
||||
; ARM: ldr [[reg4:r[0-9]+]],
|
||||
; ARM: ldr [[reg4]], [pc, [[reg4]]]
|
||||
@ -38,6 +52,10 @@ entry:
|
||||
; ARMv7: movt r[[reg5]],
|
||||
; ARMv7: add r[[reg5]], pc, r[[reg5]]
|
||||
; ARMv7: ldr r[[reg5]], [r[[reg5]]]
|
||||
; ARMv7-ELF: LoadIndirectSymbol
|
||||
; ARMv7-ELF: ldr r[[reg5:[0-9]+]],
|
||||
; ARMv7-ELF: ldr r[[reg6:[0-9]+]],
|
||||
; ARMv7-ELF: ldr r[[reg5]], [r[[reg6]], r[[reg5]]]
|
||||
%tmp = load i32* @i
|
||||
ret i32 %tmp
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user