[llvm] [AArch64] Fix extern_weak function calls on Windows (PR #219202)

via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 27 05:45:08 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-aarch64

Author: cqwrteur (trcrsired)

<details>
<summary>Changes</summary>

On aarch64-windows-gnu/msvc, calls to extern_weak functions were incorrectly going through a GOT/COFFSTUB load (adrp/ldr/blr) instead of using a direct BL instruction. This happened because classifyGlobalFunctionReference delegated to ClassifyGlobalReference for Windows, which returned MO_GOT | MO_COFFSTUB for extern_weak symbols.

The fix adds an early return of MO_NO_FLAG for extern_weak function references on Windows, allowing a direct call. The linker handles extern_weak by resolving to either the real symbol or null, so a direct BL is correct (matching ELF behavior).

issue: #<!-- -->218899

---
Full diff: https://github.com/llvm/llvm-project/pull/219202.diff


2 Files Affected:

- (modified) llvm/lib/Target/AArch64/AArch64Subtarget.cpp (+6) 
- (modified) llvm/test/CodeGen/AArch64/windows-extern-weak.ll (+23-4) 


``````````diff
diff --git a/llvm/lib/Target/AArch64/AArch64Subtarget.cpp b/llvm/lib/Target/AArch64/AArch64Subtarget.cpp
index 4fef12ab37ad8..19486ebc36cae 100644
--- a/llvm/lib/Target/AArch64/AArch64Subtarget.cpp
+++ b/llvm/lib/Target/AArch64/AArch64Subtarget.cpp
@@ -503,6 +503,12 @@ unsigned AArch64Subtarget::classifyGlobalFunctionReference(
       }
     }
 
+    // extern_weak function references on Windows should not go through
+    // GOT/COFFSTUB. The linker resolves extern_weak to either the real
+    // symbol or null, so a direct call is correct.
+    if (GV->hasExternalWeakLinkage())
+      return AArch64II::MO_NO_FLAG;
+
     // Use ClassifyGlobalReference for setting MO_DLLIMPORT/MO_COFFSTUB.
     return ClassifyGlobalReference(GV, TM);
   }
diff --git a/llvm/test/CodeGen/AArch64/windows-extern-weak.ll b/llvm/test/CodeGen/AArch64/windows-extern-weak.ll
index ecdb802222935..edc5874c4ff39 100644
--- a/llvm/test/CodeGen/AArch64/windows-extern-weak.ll
+++ b/llvm/test/CodeGen/AArch64/windows-extern-weak.ll
@@ -11,7 +11,7 @@ define void @func() nounwind {
 ; CHECK-NEXT:    ldr x8, [x8, :lo12:.refptr.weakfunc]
 ; CHECK-NEXT:    cbz x8, .LBB0_2
 ; CHECK-NEXT:  // %bb.1:
-; CHECK-NEXT:    blr x8
+; CHECK-NEXT:    bl weakfunc
 ; CHECK-NEXT:  .LBB0_2:
 ; CHECK-NEXT:    ldr x30, [sp], #16 // 8-byte Folded Reload
 ; CHECK-NEXT:    ret
@@ -23,9 +23,7 @@ define void @func() nounwind {
 ; FISEL-NEXT:    ldr x8, [x8, :lo12:.refptr.weakfunc]
 ; FISEL-NEXT:    cbz x8, .LBB0_2
 ; FISEL-NEXT:  // %bb.1:
-; FISEL-NEXT:    adrp x8, .refptr.weakfunc
-; FISEL-NEXT:    ldr x8, [x8, :lo12:.refptr.weakfunc]
-; FISEL-NEXT:    blr x8
+; FISEL-NEXT:    bl weakfunc
 ; FISEL-NEXT:  .LBB0_2:
 ; FISEL-NEXT:    ldr x30, [sp], #16 // 8-byte Folded Reload
 ; FISEL-NEXT:    ret
@@ -41,3 +39,24 @@ define void @func() nounwind {
 }
 
 declare extern_weak void @weakfunc()
+
+define ptr @use() {
+; CHECK-LABEL: use:
+; CHECK:       // %bb.0: // %entry
+; CHECK-NEXT:    str x30, [sp, #-16]! // 8-byte Folded Spill
+; CHECK:    bl foo
+; CHECK:    ldr x30, [sp], #16 // 8-byte Folded Reload
+; CHECK:    ret
+;
+; FISEL-LABEL: use:
+; FISEL:       // %bb.0: // %entry
+; FISEL-NEXT:    str x30, [sp, #-16]! // 8-byte Folded Spill
+; FISEL:    bl foo
+; FISEL:    ldr x30, [sp], #16 // 8-byte Folded Reload
+; FISEL:    ret
+entry:
+  %r = call ptr @foo()
+  ret ptr %r
+}
+
+declare extern_weak dso_local ptr @foo()

``````````

</details>


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


More information about the llvm-commits mailing list