[clang] eb9844b - [clang][ARM] Use sponentry for setjmp on Windows ARM32 (#222366)

via cfe-commits cfe-commits at lists.llvm.org
Sat Sep 12 13:26:09 PDT 2026


Author: Hamed
Date: 2026-09-12T23:26:03+03:00
New Revision: eb9844b5ceee01c9d9fad92cbcd027c5798c5ed4

URL: https://github.com/llvm/llvm-project/commit/eb9844b5ceee01c9d9fad92cbcd027c5798c5ed4
DIFF: https://github.com/llvm/llvm-project/commit/eb9844b5ceee01c9d9fad92cbcd027c5798c5ed4.diff

LOG: [clang][ARM] Use sponentry for setjmp on Windows ARM32 (#222366)

On Windows, _setjmp and _setjmpex take a second argument, the frame,
which the CRT stores in the jmp_buf and which longjmp later hands to
RtlUnwindEx as the frame to unwind. On aarch64, this is the stack pointer
on entry to the function, while x86_64 takes the function frame address.
ARM expects the same as aarch64 here, the stack pointer on entry.

Assisted-by: Claude Opus 5 (Anthropic)

Added: 
    

Modified: 
    clang/docs/ReleaseNotes.md
    clang/lib/CodeGen/CGBuiltin.cpp
    clang/test/CodeGen/ms-setjmp.c

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 8fd0dc4bfd245..fc7ab3efa9731 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -759,6 +759,11 @@ features cannot lower the translation-unit ABI level;
 
 #### Windows Support
 
+- Fixed ``setjmp`` on 32-bit Arm passing the frame pointer, rather than the
+  stack pointer as it was on entry to the function, as the frame value the CRT
+  stores in the ``jmp_buf``. Clang now uses ``llvm.sponentry`` there, as it
+  already did on AArch64.
+
 - Fixed a bug where Clang did not match the MSVC ABI on Arm64 when an
   over-aligned base class is followed by another base class. MSVC on Arm64 (but
   not Arm64EC or x64) reuses the tail padding of the over-aligned base for the

diff  --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 1e65a6a30c35e..e005632bfbb6c 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -1801,9 +1801,11 @@ enum class MSVCSetJmpKind {
 };
 }
 
-/// MSVC handles setjmp a bit 
diff erently on 
diff erent platforms. On every
-/// architecture except 32-bit x86, the frame address is passed. On x86, extra
-/// parameters can be passed as variadic arguments, but we always pass none.
+/// MSVC handles setjmp a bit 
diff erently on 
diff erent platforms. On 32-bit x86
+/// extra parameters can be passed as variadic arguments, but we always pass
+/// none. Everywhere else a frame value is passed: the stack pointer as it was
+/// on entry to the function for AArch64 and 32-bit Arm, and the frame address
+/// for the rest.
 static RValue EmitMSVCRTSetJmp(CodeGenFunction &CGF, MSVCSetJmpKind SJKind,
                                const CallExpr *E) {
   llvm::Value *Arg1 = nullptr;
@@ -1818,7 +1820,8 @@ static RValue EmitMSVCRTSetJmp(CodeGenFunction &CGF, MSVCSetJmpKind SJKind,
   } else {
     Name = SJKind == MSVCSetJmpKind::_setjmp ? "_setjmp" : "_setjmpex";
     Arg1Ty = CGF.Int8PtrTy;
-    if (CGF.getTarget().getTriple().getArch() == llvm::Triple::aarch64) {
+    const llvm::Triple &T = CGF.getTarget().getTriple();
+    if (T.getArch() == llvm::Triple::aarch64 || T.isARM() || T.isThumb()) {
       Arg1 = CGF.Builder.CreateCall(
           CGF.CGM.getIntrinsic(Intrinsic::sponentry, CGF.AllocaInt8PtrTy));
     } else

diff  --git a/clang/test/CodeGen/ms-setjmp.c b/clang/test/CodeGen/ms-setjmp.c
index ad4df790a611c..8525dac60edde 100644
--- a/clang/test/CodeGen/ms-setjmp.c
+++ b/clang/test/CodeGen/ms-setjmp.c
@@ -1,9 +1,13 @@
 // RUN: %clang_cc1 -fms-extensions -DDECLARE_SETJMP -triple i686-windows-msvc   -emit-llvm %s -o - | FileCheck --check-prefix=I386 %s
 // RUN: %clang_cc1 -fms-extensions -DDECLARE_SETJMP -triple x86_64-windows-msvc -emit-llvm %s -o - | FileCheck --check-prefix=X64 %s
 // RUN: %clang_cc1 -fms-extensions -DDECLARE_SETJMP -triple aarch64-windows-msvc -emit-llvm %s -o - | FileCheck --check-prefix=AARCH64 %s
+// RUN: %clang_cc1 -fms-extensions -DDECLARE_SETJMP -triple thumbv7-windows-msvc -emit-llvm %s -o - | FileCheck --check-prefix=ARM32 %s
+// RUN: %clang_cc1 -fms-extensions -DDECLARE_SETJMP -triple armv7-windows-msvc   -emit-llvm %s -o - | FileCheck --check-prefix=ARM32 %s
 // RUN: %clang_cc1 -fms-extensions -triple i686-windows-msvc -Wno-implicit-function-declaration -emit-llvm %s -o - | FileCheck --check-prefix=I386 %s
 // RUN: %clang_cc1 -fms-extensions -triple x86_64-windows-msvc -Wno-implicit-function-declaration -emit-llvm %s -o - | FileCheck --check-prefix=X64 %s
 // RUN: %clang_cc1 -fms-extensions -triple aarch64-windows-msvc -Wno-implicit-function-declaration -emit-llvm %s -o - | FileCheck --check-prefix=AARCH64 %s
+// RUN: %clang_cc1 -fms-extensions -triple thumbv7-windows-msvc -Wno-implicit-function-declaration -emit-llvm %s -o - | FileCheck --check-prefix=ARM32 %s
+// RUN: %clang_cc1 -fms-extensions -triple armv7-windows-msvc -Wno-implicit-function-declaration -emit-llvm %s -o - | FileCheck --check-prefix=ARM32 %s
 typedef char jmp_buf[1];
 
 #ifdef DECLARE_SETJMP
@@ -28,6 +32,11 @@ int test_setjmp(void) {
   // AARCH64:       %[[addr:.*]] = call ptr @llvm.sponentry.p0()
   // AARCH64:       %[[call:.*]] = call i32 @_setjmpex(ptr @jb, ptr %[[addr]])
   // AARCH64-NEXT:  ret i32 %[[call]]
+
+  // ARM32-LABEL: define dso_local arm_aapcs_vfpcc i32 @test_setjmp
+  // ARM32:       %[[addr:.*]] = call ptr @llvm.sponentry.p0()
+  // ARM32:       %[[call:.*]] = call arm_aapcs_vfpcc i32 @_setjmp(ptr @jb, ptr %[[addr]])
+  // ARM32-NEXT:  ret i32 %[[call]]
 }
 
 int test_setjmpex(void) {
@@ -41,4 +50,9 @@ int test_setjmpex(void) {
   // AARCH64:       %[[addr:.*]] = call ptr @llvm.sponentry.p0()
   // AARCH64:       %[[call:.*]] = call i32 @_setjmpex(ptr @jb, ptr %[[addr]])
   // AARCH64-NEXT:  ret i32 %[[call]]
+
+  // ARM32-LABEL: define dso_local arm_aapcs_vfpcc i32 @test_setjmpex
+  // ARM32:       %[[addr:.*]] = call ptr @llvm.sponentry.p0()
+  // ARM32:       %[[call:.*]] = call arm_aapcs_vfpcc i32 @_setjmpex(ptr @jb, ptr %[[addr]])
+  // ARM32-NEXT:  ret i32 %[[call]]
 }


        


More information about the cfe-commits mailing list