diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp index 2d73725291d11..b73a53cca84e3 100644 --- a/llvm/lib/Target/ARM/ARMISelLowering.cpp +++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp @@ -2815,13 +2815,20 @@ ARMTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, auto PtrVt = getPointerTy(DAG.getDataLayout()); if (Subtarget->genLongCalls()) { - assert((!isPositionIndependent() || Subtarget->isTargetWindows()) && - "long-calls codegen is not position independent!"); // Handle a global address or an external symbol. If it's not one of // those, the target's already in a register, so we don't need to do // anything extra. if (isa(Callee)) { - if (Subtarget->genExecuteOnly()) { + if (isPositionIndependent() && !Subtarget->isTargetWindows() && + !Subtarget->genExecuteOnly()) { + SDValue G = DAG.getTargetGlobalAddress( + GVal, dl, PtrVt, 0, GVal->isDSOLocal() ? 0 : ARMII::MO_GOT); + Callee = DAG.getNode(ARMISD::WrapperPIC, dl, PtrVt, G); + if (!GVal->isDSOLocal()) + Callee = + DAG.getLoad(PtrVt, dl, DAG.getEntryNode(), Callee, + MachinePointerInfo::getGOT(DAG.getMachineFunction())); + } else if (Subtarget->genExecuteOnly()) { if (Subtarget->useMovt()) ++NumMovwMovt; Callee = DAG.getNode(ARMISD::Wrapper, dl, PtrVt, @@ -2839,7 +2846,8 @@ ARMTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, PtrVt, dl, DAG.getEntryNode(), Addr, MachinePointerInfo::getConstantPool(DAG.getMachineFunction())); } - } else if (ExternalSymbolSDNode *S=dyn_cast(Callee)) { + } else if (ExternalSymbolSDNode *S = + dyn_cast(Callee)) { const char *Sym = S->getSymbol(); if (Subtarget->genExecuteOnly()) { diff --git a/llvm/test/CodeGen/ARM/long-calls.ll b/llvm/test/CodeGen/ARM/long-calls.ll new file mode 100644 index 0000000000000..41763801fddd2 --- /dev/null +++ b/llvm/test/CodeGen/ARM/long-calls.ll @@ -0,0 +1,32 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 +; RUN: llc -mtriple=armv7-unknown-linux-gnueabi -relocation-model pic -mattr=+long-calls -o - %s \ +; RUN: | FileCheck %s + +@msg = private unnamed_addr constant [12 x i8] c"hello world\00", align 1 + +declare i32 @puts(ptr) + +define void @test() { +; CHECK-LABEL: test: +; CHECK: @ %bb.0: @ %entry +; CHECK-NEXT: .save {r11, lr} +; CHECK-NEXT: push {r11, lr} +; CHECK-NEXT: ldr r0, .LCPI0_0 +; CHECK-NEXT: ldr r1, .LCPI0_1 +; CHECK-NEXT: .LPC0_0: +; CHECK-NEXT: add r0, pc, r0 +; CHECK-NEXT: .LPC0_1: +; CHECK-NEXT: ldr r1, [pc, r1] +; CHECK-NEXT: blx r1 +; CHECK-NEXT: pop {r11, pc} +; CHECK-NEXT: .p2align 2 +; CHECK-NEXT: @ %bb.1: +; CHECK-NEXT: .LCPI0_0: +; CHECK-NEXT: .long .Lmsg-(.LPC0_0+8) +; CHECK-NEXT: .LCPI0_1: +; CHECK-NEXT: .Ltmp0: +; CHECK-NEXT: .long puts(GOT_PREL)-(.LPC0_1+8-.Ltmp0) +entry: + %call = call i32 @puts(ptr @msg) + ret void +}