summaryrefslogtreecommitdiff
path: root/wasm/tests/machine_test.c
diff options
context:
space:
mode:
Diffstat (limited to 'wasm/tests/machine_test.c')
-rw-r--r--wasm/tests/machine_test.c115
1 files changed, 115 insertions, 0 deletions
diff --git a/wasm/tests/machine_test.c b/wasm/tests/machine_test.c
new file mode 100644
index 0000000000..f4b62ff580
--- /dev/null
+++ b/wasm/tests/machine_test.c
@@ -0,0 +1,115 @@
+#include <stdio.h>
+#include <assert.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include "wasm/machine.h"
+#include "wasm/asyncify.h"
+
+void *rb_wasm_get_stack_pointer(void);
+
+static void *base_stack_pointer = NULL;
+
+int __attribute__((constructor)) record_base_sp(void) {
+ base_stack_pointer = rb_wasm_get_stack_pointer();
+ return 0;
+}
+
+void dump_memory(uint8_t *base, uint8_t *end) {
+ size_t chunk_size = 16;
+
+ for (uint8_t *ptr = base; ptr <= end; ptr += chunk_size) {
+ printf("%p", ptr);
+ for (size_t offset = 0; offset < chunk_size; offset++) {
+ printf(" %02x", *(ptr + offset));
+ }
+ printf("\n");
+ }
+}
+
+bool find_in_stack(uint32_t target, void *base, void *end) {
+ for (uint32_t *ptr = base; ptr <= (uint32_t *)end; ptr++) {
+ if (*ptr == target) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void *_rb_wasm_stack_mem[2];
+void rb_wasm_mark_mem_range(void *start, void *end) {
+ _rb_wasm_stack_mem[0] = start;
+ _rb_wasm_stack_mem[1] = end;
+}
+
+#define check_live(target, ctx) do { \
+ rb_wasm_scan_stack(rb_wasm_mark_mem_range); \
+ _check_live(target, ctx); \
+ } while (0);
+
+void _check_live(uint32_t target, const char *ctx) {
+ printf("checking %#x ... ", target);
+ bool found_in_locals = false, found_in_stack = false;
+ if (find_in_stack(target, _rb_wasm_stack_mem[0], _rb_wasm_stack_mem[1])) {
+ found_in_stack = true;
+ }
+ rb_wasm_scan_locals(rb_wasm_mark_mem_range);
+ if (find_in_stack(target, _rb_wasm_stack_mem[0], _rb_wasm_stack_mem[1])) {
+ found_in_locals = true;
+ }
+ if (found_in_locals && found_in_stack) {
+ printf("ok (found in C stack and Wasm locals)\n");
+ } else if (found_in_stack) {
+ printf("ok (found in C stack)\n");
+ } else if (found_in_locals) {
+ printf("ok (found in Wasm locals)\n");
+ } else {
+ printf("not found: %s\n", ctx);
+ assert(false);
+ }
+}
+
+void new_frame(uint32_t val, uint32_t depth) {
+ if (depth == 0) {
+ dump_memory(rb_wasm_get_stack_pointer(), base_stack_pointer);
+ for (uint32_t i = 0; i < 5; i++) {
+ check_live(0x00bab10c + i, "argument value");
+ }
+ } else {
+ new_frame(val, depth - 1);
+ }
+}
+
+uint32_t return_value(void) {
+ return 0xabadbabe;
+}
+
+uint32_t check_return_value(void) {
+ check_live(0xabadbabe, "returned value");
+ return 0;
+}
+
+void take_two_args(uint32_t a, uint32_t b) {
+}
+
+__attribute__((noinline))
+int start(int argc, char **argv) {
+
+ uint32_t deadbeef;
+ register uint32_t facefeed;
+ deadbeef = 0xdeadbeef;
+ facefeed = 0xfacefeed;
+
+ check_live(0xdeadbeef, "local variable");
+ check_live(0xfacefeed, "local reg variable");
+
+ new_frame(0x00bab10c, 5);
+
+ take_two_args(return_value(), check_return_value());
+
+ return 0;
+}
+
+int main(int argc, char **argv) {
+ extern int rb_wasm_rt_start(int (main)(int argc, char **argv), int argc, char **argv);
+ return rb_wasm_rt_start(start, argc, argv);
+}