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

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


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

>From de9f8b1ece24c53732c8e5efae4bb87c6c95eb7a 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 dso_local 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 dso_local ptr
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).

This should help fix weak dllexport functions on aarch64 windows
---
 llvm/lib/Target/AArch64/AArch64Subtarget.cpp  |  6 ++++++
 .../CodeGen/AArch64/windows-extern-weak.ll    | 21 +++++++++++++++++++
 2 files changed, 27 insertions(+)

diff --git a/llvm/lib/Target/AArch64/AArch64Subtarget.cpp b/llvm/lib/Target/AArch64/AArch64Subtarget.cpp
index 4fef12ab37ad8..a30c93507131d 100644
--- a/llvm/lib/Target/AArch64/AArch64Subtarget.cpp
+++ b/llvm/lib/Target/AArch64/AArch64Subtarget.cpp
@@ -503,6 +503,12 @@ unsigned AArch64Subtarget::classifyGlobalFunctionReference(
       }
     }
 
+    // extern_weak dso_local ptr 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() && GV->isDSOLocal())
+      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..8bad6582f80b3 100644
--- a/llvm/test/CodeGen/AArch64/windows-extern-weak.ll
+++ b/llvm/test/CodeGen/AArch64/windows-extern-weak.ll
@@ -41,3 +41,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