setjmp / longjmp does not work on X86

I create simple IR code that uses llvm.eh.sjlj.setjmp and llvm.eh.sjlj.longjmp

define i32 @main() {
%buf = alloca i8, i32 40, align 16
%r = call i32 @llvm.eh.sjlj.setjmp(i8* %buf)

%normal = icmp eq i32 %r, 0
br i1 %normal, label %Normal, label %Jump

Normal:
call void @llvm.eh.sjlj.longjmp(i8* %buf)
ret i32 2

Jump:
ret i32 0
}

declare i32 @llvm.eh.sjlj.setjmp(i8* %setjmp_buf) returns_twice nounwind
declare void @llvm.eh.sjlj.longjmp(i8* %setjmp_buf) noreturn nounwind

On Windows 64bit and Linux 64bit this code crashes. setjmp lowering pushes only jump address to buffer, but longjmp expects also stack pointer (rsp) and bsp register values to be in the buffer.

Hi Paweł,

On Windows 64bit and Linux 64bit this code crashes. setjmp lowering pushes
only jump address to buffer, but longjmp expects also stack pointer (rsp)
and bsp register values to be in the buffer.

Saving those two components is the front-end's responsibility
(Exception Handling in LLVM — LLVM 16.0.0git documentation). The
best idea is probably to copy what clang produces for:

void foo(void *buf) {
  __builtin_setjmp(buf);
}

Cheers.

Tim.