Ruby: wasm/tests/machine_test.c Source File

Ruby 3.2.5p208 (2024-07-26 revision 31d0f1a2e7dbfb60731d1f05b868e1d578cda493)

machine_test.c
1#include <stdio.h>
2#include <assert.h>
3#include <stdint.h>
4#include <stdbool.h>
5#include "wasm/machine.h"
6#include "wasm/asyncify.h"
7
8void *rb_wasm_get_stack_pointer(void);
9
10static void *base_stack_pointer = NULL;
11
12int __attribute__((constructor)) record_base_sp(void) {
13 base_stack_pointer = rb_wasm_get_stack_pointer();
14 return 0;
15}
16
17void dump_memory(uint8_t *base, uint8_t *end) {
18 size_t chunk_size = 16;
19
20 for (uint8_t *ptr = base; ptr <= end; ptr += chunk_size) {
21 printf("%p", ptr);
22 for (size_t offset = 0; offset < chunk_size; offset++) {
23 printf(" %02x", *(ptr + offset));
24 }
25 printf("\n");
26 }
27}
28
29bool find_in_stack(uint32_t target, void *base, void *end) {
30 for (uint32_t *ptr = base; ptr <= (uint32_t *)end; ptr++) {
31 if (*ptr == target) {
32 return true;
33 }
34 }
35 return false;
36}
37
38void *_rb_wasm_stack_mem[2];
39void rb_wasm_mark_mem_range(void *start, void *end) {
40 _rb_wasm_stack_mem[0] = start;
41 _rb_wasm_stack_mem[1] = end;
42}
43
44#define check_live(target, ctx) do { \
45 rb_wasm_scan_stack(rb_wasm_mark_mem_range); \
46 _check_live(target, ctx); \
47 } while (0);
48
49void _check_live(uint32_t target, const char *ctx) {
50 printf("checking %#x ... ", target);
51 bool found_in_locals = false, found_in_stack = false;
52 if (find_in_stack(target, _rb_wasm_stack_mem[0], _rb_wasm_stack_mem[1])) {
53 found_in_stack = true;
54 }
55 rb_wasm_scan_locals(rb_wasm_mark_mem_range);
56 if (find_in_stack(target, _rb_wasm_stack_mem[0], _rb_wasm_stack_mem[1])) {
57 found_in_locals = true;
58 }
59 if (found_in_locals && found_in_stack) {
60 printf("ok (found in C stack and Wasm locals)\n");
61 } else if (found_in_stack) {
62 printf("ok (found in C stack)\n");
63 } else if (found_in_locals) {
64 printf("ok (found in Wasm locals)\n");
65 } else {
66 printf("not found: %s\n", ctx);
67 assert(false);
68 }
69}
70
71void new_frame(uint32_t val, uint32_t depth) {
72 if (depth == 0) {
73 dump_memory(rb_wasm_get_stack_pointer(), base_stack_pointer);
74 for (uint32_t i = 0; i < 5; i++) {
75 check_live(0x00bab10c + i, "argument value");
76 }
77 } else {
78 new_frame(val, depth - 1);
79 }
80}
81
82uint32_t return_value(void) {
83 return 0xabadbabe;
84}
85
86uint32_t check_return_value(void) {
87 check_live(0xabadbabe, "returned value");
88 return 0;
89}
90
91void take_two_args(uint32_t a, uint32_t b) {
92}
93
94 __attribute__((noinline))
95int start(int argc, char **argv) {
96
97 uint32_t deadbeef;
98 register uint32_t facefeed;
99 deadbeef = 0xdeadbeef;
100 facefeed = 0xfacefeed;
101
102 check_live(0xdeadbeef, "local variable");
103 check_live(0xfacefeed, "local reg variable");
104
105 new_frame(0x00bab10c, 5);
106
107 take_two_args(return_value(), check_return_value());
108
109 return 0;
110}
111
112int main(int argc, char **argv) {
113 extern int rb_wasm_rt_start(int (main)(int argc, char **argv), int argc, char **argv);
114 return rb_wasm_rt_start(start, argc, argv);
115}
assert.h
stdbool.h
C99 shim for <stdbool.h>
__attribute__
Definition vm_insnhelper.c:2198