[llvm] [AArch64] Fix extern_weak function calls on Windows (PR #219202)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 27 05:44:24 PDT 2026
https://github.com/trcrsired created https://github.com/llvm/llvm-project/pull/219202
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
>From 587f4d6540fe810b68f9fa41a6a6570e93fb6f9b Mon Sep 17 00:00:00 2001
From: trcrsired <oyzawqgcfc at gmail.com>
Date: Thu, 27 Aug 2026 20:18:41 +0800
Subject: [PATCH] [AArch64] Fix extern_weak function calls on Windows
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).
---
llvm/lib/Target/AArch64/AArch64Subtarget.cpp | 6 +++++
.../CodeGen/AArch64/windows-extern-weak.ll | 27 ++++++++++++++++---
2 files changed, 29 insertions(+), 4 deletions(-)
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()
More information about the llvm-commits
mailing list