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

via llvm-commits llvm-commits at lists.llvm.org
Fri Jun 12 06:06:04 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:

Thanks for your explanation. Yes, I agree with your point, and I have added an assertion to give a user-visible error when -mlong-calls and -fropi are used together, as that combination may generate incorrect code:

~~~c
assert(!Subtarget->isROPI() &&
       "long-calls with ROPI is not currently supported");
~~~

At the same time, the combination of -mlong-calls and -fpic appears to be reasonable – at least GCC already supports the same option pair. Our patch simply helps LLVM catch up in this area.

Thank you for your review. Could you please let me know if this merge request is ready to be merged, or are there any other issues we should discuss further? Thanks. @smithp35 

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


More information about the llvm-commits mailing list