mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-04-16 20:40:16 +00:00
Implement PIC for arm-linux.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@36324 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
88894b6c40
commit
0ae4a3357a
@ -133,6 +133,7 @@ namespace {
|
||||
O << TAI->getPrivateGlobalPrefix() << Name << "$stub";
|
||||
} else
|
||||
O << Name;
|
||||
if (ACPV->hasModifier()) O << "(" << ACPV->getModifier() << ")";
|
||||
if (ACPV->getPCAdjustment() != 0)
|
||||
O << "-(" << TAI->getPrivateGlobalPrefix() << "PC"
|
||||
<< utostr(ACPV->getLabelId())
|
||||
@ -284,7 +285,9 @@ void ARMAsmPrinter::printOperand(const MachineInstr *MI, int opNum,
|
||||
FnStubs.insert(Name);
|
||||
} else
|
||||
O << Name;
|
||||
|
||||
if (isCallOp && Subtarget->isTargetELF() &&
|
||||
TM.getRelocationModel() == Reloc::PIC_)
|
||||
O << "(PLT)";
|
||||
if (GV->hasExternalWeakLinkage())
|
||||
ExtWeakSymbols.insert(GV);
|
||||
break;
|
||||
@ -299,6 +302,9 @@ void ARMAsmPrinter::printOperand(const MachineInstr *MI, int opNum,
|
||||
FnStubs.insert(Name);
|
||||
} else
|
||||
O << Name;
|
||||
if (isCallOp && Subtarget->isTargetELF() &&
|
||||
TM.getRelocationModel() == Reloc::PIC_)
|
||||
O << "(PLT)";
|
||||
break;
|
||||
}
|
||||
case MachineOperand::MO_ConstantPoolIndex:
|
||||
|
@ -19,15 +19,26 @@ using namespace llvm;
|
||||
|
||||
ARMConstantPoolValue::ARMConstantPoolValue(GlobalValue *gv, unsigned id,
|
||||
ARMCP::ARMCPKind k,
|
||||
unsigned char PCAdj)
|
||||
unsigned char PCAdj,
|
||||
const char *Modif)
|
||||
: MachineConstantPoolValue((const Type*)gv->getType()),
|
||||
GV(gv), S(NULL), LabelId(id), Kind(k), PCAdjust(PCAdj) {}
|
||||
GV(gv), S(NULL), LabelId(id), Kind(k), PCAdjust(PCAdj),
|
||||
Modifier(Modif) {}
|
||||
|
||||
ARMConstantPoolValue::ARMConstantPoolValue(const char *s, unsigned id,
|
||||
ARMCP::ARMCPKind k,
|
||||
unsigned char PCAdj)
|
||||
unsigned char PCAdj,
|
||||
const char *Modif)
|
||||
: MachineConstantPoolValue((const Type*)Type::Int32Ty),
|
||||
GV(NULL), S(s), LabelId(id), Kind(k), PCAdjust(PCAdj) {}
|
||||
GV(NULL), S(s), LabelId(id), Kind(k), PCAdjust(PCAdj),
|
||||
Modifier(Modif) {}
|
||||
|
||||
ARMConstantPoolValue::ARMConstantPoolValue(GlobalValue *gv,
|
||||
ARMCP::ARMCPKind k,
|
||||
const char *Modif)
|
||||
: MachineConstantPoolValue((const Type*)Type::Int32Ty),
|
||||
GV(gv), S(NULL), LabelId(0), Kind(k), PCAdjust(0),
|
||||
Modifier(Modif) {}
|
||||
|
||||
int ARMConstantPoolValue::getExistingMachineCPValue(MachineConstantPool *CP,
|
||||
unsigned Alignment) {
|
||||
@ -66,6 +77,7 @@ void ARMConstantPoolValue::print(std::ostream &O) const {
|
||||
O << S;
|
||||
if (isNonLazyPointer()) O << "$non_lazy_ptr";
|
||||
else if (isStub()) O << "$stub";
|
||||
if (Modifier) O << "(" << Modifier << ")";
|
||||
if (PCAdjust != 0) O << "-(LPIC" << LabelId << "+"
|
||||
<< (unsigned)PCAdjust << ")";
|
||||
}
|
||||
|
@ -36,17 +36,23 @@ class ARMConstantPoolValue : public MachineConstantPoolValue {
|
||||
ARMCP::ARMCPKind Kind; // non_lazy_ptr or stub?
|
||||
unsigned char PCAdjust; // Extra adjustment if constantpool is pc relative.
|
||||
// 8 for ARM, 4 for Thumb.
|
||||
const char *Modifier; // GV modifier i.e. (&GV(modifier)-(LPIC+8))
|
||||
|
||||
public:
|
||||
ARMConstantPoolValue(GlobalValue *gv, unsigned id,
|
||||
ARMCP::ARMCPKind Kind = ARMCP::CPValue,
|
||||
unsigned char PCAdj = 0);
|
||||
unsigned char PCAdj = 0, const char *Modifier = NULL);
|
||||
ARMConstantPoolValue(const char *s, unsigned id,
|
||||
ARMCP::ARMCPKind Kind = ARMCP::CPValue,
|
||||
unsigned char PCAdj = 0);
|
||||
unsigned char PCAdj = 0, const char *Modifier = NULL);
|
||||
ARMConstantPoolValue(GlobalValue *GV, ARMCP::ARMCPKind Kind,
|
||||
const char *Modifier);
|
||||
|
||||
|
||||
GlobalValue *getGV() const { return GV; }
|
||||
const char *getSymbol() const { return S; }
|
||||
const char *getModifier() const { return Modifier; }
|
||||
bool hasModifier() const { return Modifier != NULL; }
|
||||
unsigned getLabelId() const { return LabelId; }
|
||||
bool isNonLazyPointer() const { return Kind == ARMCP::CPNonLazyPtr; }
|
||||
bool isStub() const { return Kind == ARMCP::CPStub; }
|
||||
|
@ -179,6 +179,7 @@ ARMTargetLowering::ARMTargetLowering(TargetMachine &TM)
|
||||
setOperationAction(ISD::RET, MVT::Other, Custom);
|
||||
setOperationAction(ISD::GlobalAddress, MVT::i32, Custom);
|
||||
setOperationAction(ISD::ConstantPool, MVT::i32, Custom);
|
||||
setOperationAction(ISD::GLOBAL_OFFSET_TABLE, MVT::i32, Custom);
|
||||
|
||||
// Expand mem operations genericly.
|
||||
setOperationAction(ISD::MEMSET , MVT::Other, Expand);
|
||||
@ -694,6 +695,31 @@ static SDOperand LowerConstantPool(SDOperand Op, SelectionDAG &DAG) {
|
||||
return DAG.getNode(ARMISD::Wrapper, MVT::i32, Res);
|
||||
}
|
||||
|
||||
SDOperand ARMTargetLowering::LowerGlobalAddressELF(SDOperand Op,
|
||||
SelectionDAG &DAG) {
|
||||
MVT::ValueType PtrVT = getPointerTy();
|
||||
GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
|
||||
Reloc::Model RelocM = getTargetMachine().getRelocationModel();
|
||||
if (RelocM == Reloc::PIC_) {
|
||||
bool UseGOTOFF = GV->hasInternalLinkage();
|
||||
ARMConstantPoolValue *CPV =
|
||||
new ARMConstantPoolValue(GV, ARMCP::CPValue, UseGOTOFF ? "GOTOFF":"GOT");
|
||||
SDOperand CPAddr = DAG.getTargetConstantPool(CPV, PtrVT, 2);
|
||||
CPAddr = DAG.getNode(ARMISD::Wrapper, MVT::i32, CPAddr);
|
||||
SDOperand Result = DAG.getLoad(PtrVT, DAG.getEntryNode(), CPAddr, NULL, 0);
|
||||
SDOperand Chain = Result.getValue(1);
|
||||
SDOperand GOT = DAG.getNode(ISD::GLOBAL_OFFSET_TABLE, PtrVT);
|
||||
Result = DAG.getNode(ISD::ADD, PtrVT, Result, GOT);
|
||||
if (!UseGOTOFF)
|
||||
Result = DAG.getLoad(PtrVT, Chain, Result, NULL, 0);
|
||||
return Result;
|
||||
} else {
|
||||
SDOperand CPAddr = DAG.getTargetConstantPool(GV, PtrVT, 2);
|
||||
CPAddr = DAG.getNode(ARMISD::Wrapper, MVT::i32, CPAddr);
|
||||
return DAG.getLoad(PtrVT, DAG.getEntryNode(), CPAddr, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/// GVIsIndirectSymbol - true if the GV will be accessed via an indirect symbol
|
||||
/// even in dynamic-no-pic mode.
|
||||
static bool GVIsIndirectSymbol(GlobalValue *GV) {
|
||||
@ -701,12 +727,12 @@ static bool GVIsIndirectSymbol(GlobalValue *GV) {
|
||||
(GV->isDeclaration() && !GV->hasNotBeenReadFromBytecode()));
|
||||
}
|
||||
|
||||
SDOperand ARMTargetLowering::LowerGlobalAddress(SDOperand Op,
|
||||
SelectionDAG &DAG) {
|
||||
SDOperand ARMTargetLowering::LowerGlobalAddressDarwin(SDOperand Op,
|
||||
SelectionDAG &DAG) {
|
||||
MVT::ValueType PtrVT = getPointerTy();
|
||||
GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
|
||||
Reloc::Model RelocM = getTargetMachine().getRelocationModel();
|
||||
bool IsIndirect = Subtarget->isTargetDarwin() && GVIsIndirectSymbol(GV);
|
||||
bool IsIndirect = GVIsIndirectSymbol(GV);
|
||||
SDOperand CPAddr;
|
||||
if (RelocM == Reloc::Static)
|
||||
CPAddr = DAG.getTargetConstantPool(GV, PtrVT, 2);
|
||||
@ -734,6 +760,22 @@ SDOperand ARMTargetLowering::LowerGlobalAddress(SDOperand Op,
|
||||
return Result;
|
||||
}
|
||||
|
||||
SDOperand ARMTargetLowering::LowerGLOBAL_OFFSET_TABLE(SDOperand Op,
|
||||
SelectionDAG &DAG){
|
||||
assert(Subtarget->isTargetELF() &&
|
||||
"GLOBAL OFFSET TABLE not implemented for non-ELF targets");
|
||||
MVT::ValueType PtrVT = getPointerTy();
|
||||
unsigned PCAdj = Subtarget->isThumb() ? 4 : 8;
|
||||
ARMConstantPoolValue *CPV = new ARMConstantPoolValue("_GLOBAL_OFFSET_TABLE_",
|
||||
ARMPCLabelIndex,
|
||||
ARMCP::CPValue, PCAdj);
|
||||
SDOperand CPAddr = DAG.getTargetConstantPool(CPV, PtrVT, 2);
|
||||
CPAddr = DAG.getNode(ARMISD::Wrapper, MVT::i32, CPAddr);
|
||||
SDOperand Result = DAG.getLoad(PtrVT, DAG.getEntryNode(), CPAddr, NULL, 0);
|
||||
SDOperand PICLabel = DAG.getConstant(ARMPCLabelIndex++, MVT::i32);
|
||||
return DAG.getNode(ARMISD::PIC_ADD, PtrVT, Result, PICLabel);
|
||||
}
|
||||
|
||||
static SDOperand LowerVASTART(SDOperand Op, SelectionDAG &DAG,
|
||||
unsigned VarArgsFrameIndex) {
|
||||
// vastart just stores the address of the VarArgsFrameIndex slot into the
|
||||
@ -1198,7 +1240,9 @@ SDOperand ARMTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
|
||||
switch (Op.getOpcode()) {
|
||||
default: assert(0 && "Don't know how to custom lower this!"); abort();
|
||||
case ISD::ConstantPool: return LowerConstantPool(Op, DAG);
|
||||
case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG);
|
||||
case ISD::GlobalAddress:
|
||||
return Subtarget->isTargetDarwin() ? LowerGlobalAddressDarwin(Op, DAG) :
|
||||
LowerGlobalAddressELF(Op, DAG);
|
||||
case ISD::CALL: return LowerCALL(Op, DAG);
|
||||
case ISD::RET: return LowerRET(Op, DAG);
|
||||
case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG, Subtarget);
|
||||
@ -1220,6 +1264,7 @@ SDOperand ARMTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
|
||||
return LowerFORMAL_ARGUMENTS(Op, DAG);
|
||||
case ISD::RETURNADDR: break;
|
||||
case ISD::FRAMEADDR: break;
|
||||
case ISD::GLOBAL_OFFSET_TABLE: return LowerGLOBAL_OFFSET_TABLE(Op, DAG);
|
||||
}
|
||||
return SDOperand();
|
||||
}
|
||||
|
@ -123,7 +123,9 @@ namespace llvm {
|
||||
unsigned ARMPCLabelIndex;
|
||||
|
||||
SDOperand LowerCALL(SDOperand Op, SelectionDAG &DAG);
|
||||
SDOperand LowerGlobalAddress(SDOperand Op, SelectionDAG &DAG);
|
||||
SDOperand LowerGlobalAddressDarwin(SDOperand Op, SelectionDAG &DAG);
|
||||
SDOperand LowerGlobalAddressELF(SDOperand Op, SelectionDAG &DAG);
|
||||
SDOperand LowerGLOBAL_OFFSET_TABLE(SDOperand Op, SelectionDAG &DAG);
|
||||
SDOperand LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG);
|
||||
SDOperand LowerBR_JT(SDOperand Op, SelectionDAG &DAG);
|
||||
};
|
||||
|
@ -1,5 +1,7 @@
|
||||
; RUN: llvm-upgrade < %s | llvm-as | llc -march=arm | grep {mov lr, pc}
|
||||
; RUN: llvm-upgrade < %s | llvm-as | llc -march=arm -mattr=+v5t | grep blx
|
||||
; RUN: llvm-upgrade < %s | llvm-as | llc -march=arm -mtriple=arm-linux-gnueabi\
|
||||
; RUN: -relocation-model=pic | grep {PLT}
|
||||
|
||||
%t = weak global int ()* null
|
||||
declare void %g(int, int, int, int)
|
||||
|
@ -1,10 +1,12 @@
|
||||
; RUN: llvm-upgrade < %s | llvm-as | llc -march=arm
|
||||
; RUN: llvm-upgrade < %s | llvm-as | \
|
||||
; RUN: llc -mtriple=arm-apple-darwin -relocation-model=dynamic-no-pic | \
|
||||
; RUN: grep {L_G\$non_lazy_ptr} | wc -l | grep 2
|
||||
; RUN: llvm-upgrade < %s | llvm-as | \
|
||||
; RUN: llc -mtriple=arm-apple-darwin -relocation-model=pic | \
|
||||
; RUN: grep {ldr.*pc} | wc -l | grep 1
|
||||
; RUN: llvm-upgrade < %s | llvm-as | \
|
||||
; RUN: llc -mtriple=arm-linux-gnueabi -relocation-model=pic | \
|
||||
; RUN: grep {GOT} | wc -l | grep 1
|
||||
|
||||
%G = external global int
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user