[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