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]] } _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
