mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-26 21:20:37 +00:00
Implement external weak (ELF) symbols on AArch64
Weakly defined symbols should evaluate to 0 if they're undefined at link-time. This is impossible to do with the usual address generation patterns, so we should use a literal pool entry to materlialise the address. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@174518 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
2e402d5b5f
commit
8a06229c89
@ -1863,7 +1863,7 @@ AArch64TargetLowering::LowerGlobalAddressELF(SDValue Op,
|
||||
// TableGen doesn't have easy access to the CodeModel or RelocationModel, so
|
||||
// we make that distinction here.
|
||||
|
||||
// We support the static, small memory model for now.
|
||||
// We support the small memory model for now.
|
||||
assert(getTargetMachine().getCodeModel() == CodeModel::Small);
|
||||
|
||||
EVT PtrVT = getPointerTy();
|
||||
@ -1871,6 +1871,18 @@ AArch64TargetLowering::LowerGlobalAddressELF(SDValue Op,
|
||||
const GlobalAddressSDNode *GN = cast<GlobalAddressSDNode>(Op);
|
||||
const GlobalValue *GV = GN->getGlobal();
|
||||
unsigned Alignment = GV->getAlignment();
|
||||
Reloc::Model RelocM = getTargetMachine().getRelocationModel();
|
||||
|
||||
if (GV->isWeakForLinker() && RelocM == Reloc::Static) {
|
||||
// Weak symbols can't use ADRP/ADD pair since they should evaluate to
|
||||
// zero when undefined. In PIC mode the GOT can take care of this, but in
|
||||
// absolute mode we use a constant pool load.
|
||||
return DAG.getLoad(PtrVT, dl, DAG.getEntryNode(),
|
||||
DAG.getConstantPool(GV, GN->getValueType(0)),
|
||||
MachinePointerInfo::getConstantPool(),
|
||||
/*isVolatile=*/ false, /*isNonTemporal=*/ true,
|
||||
/*isInvariant=*/ true, 8);
|
||||
}
|
||||
|
||||
if (Alignment == 0) {
|
||||
const PointerType *GVPtrTy = cast<PointerType>(GV->getType());
|
||||
@ -1886,7 +1898,6 @@ AArch64TargetLowering::LowerGlobalAddressELF(SDValue Op,
|
||||
}
|
||||
|
||||
unsigned char HiFixup, LoFixup;
|
||||
Reloc::Model RelocM = getTargetMachine().getRelocationModel();
|
||||
bool UseGOT = Subtarget->GVIsIndirectSymbol(GV, RelocM);
|
||||
|
||||
if (UseGOT) {
|
||||
|
@ -2409,8 +2409,10 @@ class A64I_LDRlitSimple<bits<2> opc, bit v, RegisterClass OutReg,
|
||||
"ldr\t$Rt, $Imm19", patterns, NoItinerary>;
|
||||
|
||||
let mayLoad = 1 in {
|
||||
def LDRw_lit : A64I_LDRlitSimple<0b00, 0b0, GPR32>;
|
||||
def LDRx_lit : A64I_LDRlitSimple<0b01, 0b0, GPR64>;
|
||||
def LDRw_lit : A64I_LDRlitSimple<0b00, 0b0, GPR32,
|
||||
[(set (i32 GPR32:$Rt), (load constpool:$Imm19))]>;
|
||||
def LDRx_lit : A64I_LDRlitSimple<0b01, 0b0, GPR64,
|
||||
[(set (i64 GPR64:$Rt), (load constpool:$Imm19))]>;
|
||||
}
|
||||
|
||||
def LDRs_lit : A64I_LDRlitSimple<0b00, 0b1, FPR32,
|
||||
|
13
test/CodeGen/AArch64/extern-weak.ll
Normal file
13
test/CodeGen/AArch64/extern-weak.ll
Normal file
@ -0,0 +1,13 @@
|
||||
; RUN: llc -mtriple=aarch64-none-linux-gnu -o - < %s | FileCheck %s
|
||||
|
||||
declare extern_weak i32 @var()
|
||||
|
||||
define i32()* @foo() {
|
||||
; The usual ADRP/ADD pair can't be used for a weak reference because it must
|
||||
; evaluate to 0 if the symbol is undefined. We use a litpool entry.
|
||||
ret i32()* @var
|
||||
; CHECK: ldr x0, .LCPI0_0
|
||||
|
||||
; CHECK: .LCPI0_0:
|
||||
; CHECK-NEXT: .xword var
|
||||
}
|
Loading…
Reference in New Issue
Block a user