Ruby: wasm/tests/setjmp_test.c Source File

Ruby 4.0.5p0 (2026-05-20 revision 64336ffd0ee9e1f4c05891695a3d7b49cb709721)

setjmp_test.c
1#include "wasm/setjmp.h"
2#include "wasm/asyncify.h"
3#include "wasm/machine.h"
4#include <stdio.h>
5#include <assert.h>
6
7void check_direct(void) {
8 rb_wasm_jmp_buf buf;
9 int val;
10 printf("[%s] start\n", __func__);
11 printf("[%s] call rb_wasm_setjmp\n", __func__);
12 if ((val = rb_wasm_setjmp(buf)) == 0) {
13 printf("[%s] rb_wasm_setjmp(buf) == 0\n", __func__);
14 printf("[%s] call rb_wasm_longjmp(buf, 2)\n", __func__);
15 rb_wasm_longjmp(buf, 2);
16 assert(0 && "unreachable after longjmp");
17 } else {
18 printf("[%s] rb_wasm_setjmp(buf) == %d\n", __func__, val);
19 printf("[%s] sp = %p\n", __func__, rb_wasm_get_stack_pointer());
20 assert(val == 2 && "unexpected returned value");
21 }
22 printf("[%s] end\n", __func__);
23}
24
25void jump_to_dst(rb_wasm_jmp_buf *dst) {
26 rb_wasm_jmp_buf buf;
27 printf("[%s] start sp = %p\n", __func__, rb_wasm_get_stack_pointer());
28 printf("[%s] call rb_wasm_setjmp\n", __func__);
29 if (rb_wasm_setjmp(buf) == 0) {
30 printf("[%s] rb_wasm_setjmp(buf) == 0\n", __func__);
31 printf("[%s] call rb_wasm_longjmp(dst, 4)\n", __func__);
32 rb_wasm_longjmp(*dst, 4);
33 assert(0 && "unreachable after longjmp");
34 } else {
35 assert(0 && "unreachable");
36 }
37 printf("[%s] end\n", __func__);
38}
39
40void check_jump_two_level(void) {
41 rb_wasm_jmp_buf buf;
42 int val;
43 printf("[%s] start\n", __func__);
44 printf("[%s] call rb_wasm_setjmp\n", __func__);
45 if ((val = rb_wasm_setjmp(buf)) == 0) {
46 printf("[%s] rb_wasm_setjmp(buf) == 0\n", __func__);
47 printf("[%s] call jump_to_dst(&buf)\n", __func__);
48 jump_to_dst(&buf);
49 assert(0 && "unreachable after longjmp");
50 } else {
51 printf("[%s] rb_wasm_setjmp(buf) == %d\n", __func__, val);
52 assert(val == 4 && "unexpected returned value");
53 }
54 printf("[%s] end\n", __func__);
55}
56
57void check_reuse(void) {
58 rb_wasm_jmp_buf buf;
59 int val;
60 printf("[%s] start\n", __func__);
61 printf("[%s] call rb_wasm_setjmp\n", __func__);
62 if ((val = rb_wasm_setjmp(buf)) == 0) {
63 printf("[%s] rb_wasm_setjmp(buf) == 0\n", __func__);
64 printf("[%s] call rb_wasm_longjmp(buf, 2)\n", __func__);
65 rb_wasm_longjmp(buf, 2);
66 assert(0 && "unreachable after longjmp");
67 } else {
68 printf("[%s] rb_wasm_setjmp(buf) == %d\n", __func__, val);
69 if (val < 5) {
70 printf("[%s] re-call rb_wasm_longjmp(buf, %d)\n", __func__, val + 1);
71 rb_wasm_longjmp(buf, val + 1);
72 }
73 }
74 printf("[%s] end\n", __func__);
75}
76
77void check_stack_ptr(void) {
78 static void *normal_sp;
79 rb_wasm_jmp_buf buf;
80 normal_sp = rb_wasm_get_stack_pointer();
81
82 printf("[%s] start sp = %p\n", __func__, normal_sp);
83 printf("[%s] call rb_wasm_setjmp\n", __func__);
84 if (rb_wasm_setjmp(buf) == 0) {
85 printf("[%s] call jump_to_dst(&buf)\n", __func__);
86 jump_to_dst(&buf);
87 assert(0 && "unreachable after longjmp");
88 } else {
89 printf("[%s] sp = %p\n", __func__, rb_wasm_get_stack_pointer());
90 assert(rb_wasm_get_stack_pointer() == normal_sp);
91 }
92 printf("[%s] end\n", __func__);
93}
94
95// top level function should not be inlined to stop unwinding immediately after this function returns
96 __attribute__((noinline))
97int start(int argc, char **argv) {
98 check_direct();
99 check_jump_two_level();
100 check_reuse();
101 check_stack_ptr();
102 return 0;
103}
104
105int main(int argc, char **argv) {
106 extern int rb_wasm_rt_start(int (main)(int argc, char **argv), int argc, char **argv);
107 return rb_wasm_rt_start(start, argc, argv);
108}
assert.h
rb_wasm_jmp_buf
Definition setjmp.h:17
__attribute__
Definition vm_insnhelper.c:2399