[llvm] [ARM] support -mlong-calls -fPIC on arm32 #39970 (PR #147313)

via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 9 10:49:43 PDT 2026


================
@@ -2438,19 +2438,33 @@ ARMTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
   auto PtrVt = getPointerTy(DAG.getDataLayout());
 
   if (Subtarget->genLongCalls()) {
-    assert((!isPositionIndependent() || TT.isOSWindows()) &&
-           "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.
+    bool isPIC = isPositionIndependent() && !TT.isOSWindows();
+
     if (isa<GlobalAddressSDNode>(Callee)) {
       if (Subtarget->genExecuteOnly()) {
+        // Execute-only forbids constant pools in .text, so use movw/movt.
+        // Note: execute-only may not support fPIC on ARM; this path is only
+        // reached for non-PIC targets.
         if (Subtarget->useMovt())
           ++NumMovwMovt;
         Callee = DAG.getNode(ARMISD::Wrapper, dl, PtrVt,
                              DAG.getTargetGlobalAddress(GVal, dl, PtrVt));
+      } else if (isPIC) {
+        // PIC without execute-only: use GOT-based addressing.
+        // DSO-local symbols use a plain PC-relative WrapperPIC;
+        // non-DSO-local symbols additionally load the address from the GOT.
+        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 {
----------------
jxz-hw wrote:

Thank you for the reminder. I checked the definition in the LLVM code – according to (https://github.com/llvm/llvm-project/blob/main/llvm/lib/Target/TargetMachine.cpp#L144), 
`bool TargetMachine::isPositionIndependent() const {
  return getRelocationModel() == Reloc::PIC_;
}`
isPositionIndependent() corresponds to PIC_, and Reloc::Model includes:
`namespace Reloc {
  enum Model { Static, PIC_, DynamicNoPIC, ROPI, RWPI, ROPI_RWPI };
}`

Thus, isPositionIndependent() and isROPI() are coordinate concepts, so there is no case where isROPI() is true but the GOT is mistakenly used. Moreover, both before and after my change, when isROPI() is true, the code consistently uses an absolute address constant pool (PCAdj = 0).

https://github.com/llvm/llvm-project/pull/147313


More information about the llvm-commits mailing list