summaryrefslogtreecommitdiff
path: root/test/spec-wasm2c-prefix.c
diff options
context:
space:
mode:
Diffstat (limited to 'test/spec-wasm2c-prefix.c')
-rw-r--r--test/spec-wasm2c-prefix.c323
1 files changed, 323 insertions, 0 deletions
diff --git a/test/spec-wasm2c-prefix.c b/test/spec-wasm2c-prefix.c
new file mode 100644
index 00000000..b55664ce
--- /dev/null
+++ b/test/spec-wasm2c-prefix.c
@@ -0,0 +1,323 @@
+#include <assert.h>
+#define __STDC_FORMAT_MACROS
+#include <inttypes.h>
+#include <math.h>
+#include <setjmp.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define PAGE_SIZE 65536
+
+typedef struct FuncType {
+ wasm_rt_type_t* params;
+ wasm_rt_type_t* results;
+ u32 param_count;
+ u32 result_count;
+} FuncType;
+
+int g_tests_run;
+int g_tests_passed;
+jmp_buf g_jmp_buf;
+FuncType* g_func_types;
+u32 g_func_type_count;
+
+static void run_spec_tests(void);
+
+static void error(const char* file, int line, const char* format, ...) {
+ va_list args;
+ va_start(args, format);
+ fprintf(stderr, "%s:%d: assertion failed: ", file, line);
+ vfprintf(stderr, format, args);
+ va_end(args);
+}
+
+#define ASSERT_TRAP(f) \
+ do { \
+ g_tests_run++; \
+ if (setjmp(g_jmp_buf) != 0) { \
+ g_tests_passed++; \
+ } else { \
+ (void)(f); \
+ error(__FILE__, __LINE__, "expected " #f " to trap.\n"); \
+ } \
+ } while (0)
+
+#define ASSERT_EXHAUSTION(f) \
+ do { \
+ g_tests_run++; \
+ wasm_rt_trap_t code = setjmp(g_jmp_buf); \
+ switch (code) { \
+ case WASM_RT_TRAP_NONE: \
+ (void)(f); \
+ error(__FILE__, __LINE__, "expected " #f " to trap.\n"); \
+ break; \
+ case WASM_RT_TRAP_EXHAUSTION: \
+ g_tests_passed++; \
+ break; \
+ default: \
+ error(__FILE__, __LINE__, \
+ "expected " #f \
+ " to trap due to exhaustion, got trap code %d.\n", \
+ code); \
+ break; \
+ } \
+ } while (0)
+
+#define ASSERT_RETURN(f) \
+ do { \
+ g_tests_run++; \
+ if (setjmp(g_jmp_buf) != 0) { \
+ error(__FILE__, __LINE__, #f " trapped.\n"); \
+ } else { \
+ f; \
+ g_tests_passed++; \
+ } \
+ } while (0)
+
+#define ASSERT_RETURN_T(type, fmt, f, expected) \
+ do { \
+ g_tests_run++; \
+ if (setjmp(g_jmp_buf) != 0) { \
+ error(__FILE__, __LINE__, #f " trapped.\n"); \
+ } else { \
+ type actual = f; \
+ if (is_equal_##type(actual, expected)) { \
+ g_tests_passed++; \
+ } else { \
+ error(__FILE__, __LINE__, \
+ "in " #f ": expected %" fmt ", got %" fmt ".\n", expected, \
+ actual); \
+ } \
+ } \
+ } while (0)
+
+#define ASSERT_RETURN_NAN_T(type, itype, fmt, f, kind) \
+ do { \
+ g_tests_run++; \
+ if (setjmp(g_jmp_buf) != 0) { \
+ error(__FILE__, __LINE__, #f " trapped.\n"); \
+ } else { \
+ type actual = f; \
+ itype iactual; \
+ memcpy(&iactual, &actual, sizeof(iactual)); \
+ if (is_##kind##_nan_##type(iactual)) { \
+ g_tests_passed++; \
+ } else { \
+ error(__FILE__, __LINE__, \
+ "in " #f ": expected result to be a " #kind " nan, got 0x%" fmt \
+ ".\n", \
+ iactual); \
+ } \
+ } \
+ } while (0)
+
+#define ASSERT_RETURN_I32(f, expected) ASSERT_RETURN_T(u32, "u", f, expected)
+#define ASSERT_RETURN_I64(f, expected) ASSERT_RETURN_T(u64, PRIu64, f, expected)
+#define ASSERT_RETURN_F32(f, expected) ASSERT_RETURN_T(f32, ".9g", f, expected)
+#define ASSERT_RETURN_F64(f, expected) ASSERT_RETURN_T(f64, ".17g", f, expected)
+
+#define ASSERT_RETURN_CANONICAL_NAN_F32(f) \
+ ASSERT_RETURN_NAN_T(f32, u32, "08x", f, canonical)
+#define ASSERT_RETURN_CANONICAL_NAN_F64(f) \
+ ASSERT_RETURN_NAN_T(f64, u64, "016x", f, canonical)
+#define ASSERT_RETURN_ARITHMETIC_NAN_F32(f) \
+ ASSERT_RETURN_NAN_T(f32, u32, "08x", f, arithmetic)
+#define ASSERT_RETURN_ARITHMETIC_NAN_F64(f) \
+ ASSERT_RETURN_NAN_T(f64, u64, "016x", f, arithmetic)
+
+static bool is_equal_u32(u32 x, u32 y) {
+ return x == y;
+}
+
+static bool is_equal_u64(u64 x, u64 y) {
+ return x == y;
+}
+
+static bool is_equal_f32(f32 x, f32 y) {
+ u32 ux, uy;
+ memcpy(&ux, &x, sizeof(ux));
+ memcpy(&uy, &y, sizeof(uy));
+ return ux == uy;
+}
+
+static bool is_equal_f64(f64 x, f64 y) {
+ u64 ux, uy;
+ memcpy(&ux, &x, sizeof(ux));
+ memcpy(&uy, &y, sizeof(uy));
+ return ux == uy;
+}
+
+static f32 make_nan_f32(u32 x) {
+ x |= 0x7f800000;
+ f32 res;
+ memcpy(&res, &x, sizeof(res));
+ return res;
+}
+
+static f64 make_nan_f64(u64 x) {
+ x |= 0x7ff0000000000000;
+ f64 res;
+ memcpy(&res, &x, sizeof(res));
+ return res;
+}
+
+static bool is_canonical_nan_f32(u32 x) {
+ return (x & 0x7fffffff) == 0x7fc00000;
+}
+
+static bool is_canonical_nan_f64(u64 x) {
+ return (x & 0x7fffffffffffffff) == 0x7ff8000000000000;
+}
+
+static bool is_arithmetic_nan_f32(u32 x) {
+ return (x & 0x7fc00000) == 0x7fc00000;
+}
+
+static bool is_arithmetic_nan_f64(u64 x) {
+ return (x & 0x7ff8000000000000) == 0x7ff8000000000000;
+}
+
+static bool func_types_are_equal(FuncType* a, FuncType* b) {
+ if (a->param_count != b->param_count || a->result_count != b->result_count)
+ return 0;
+ int i;
+ for (i = 0; i < a->param_count; ++i)
+ if (a->params[i] != b->params[i])
+ return 0;
+ for (i = 0; i < a->result_count; ++i)
+ if (a->results[i] != b->results[i])
+ return 0;
+ return 1;
+}
+
+
+/*
+ * wasm_rt_* implementations
+ */
+
+uint32_t wasm_rt_call_stack_depth;
+
+void wasm_rt_trap(wasm_rt_trap_t code) {
+ assert(code != WASM_RT_TRAP_NONE);
+ longjmp(g_jmp_buf, code);
+}
+
+u32 wasm_rt_register_func_type(u32 param_count, u32 result_count, ...) {
+ FuncType func_type;
+ func_type.param_count = param_count;
+ func_type.params = malloc(param_count * sizeof(wasm_rt_type_t));
+ func_type.result_count = result_count;
+ func_type.results = malloc(result_count * sizeof(wasm_rt_type_t));
+
+ va_list args;
+ va_start(args, result_count);
+
+ u32 i;
+ for (i = 0; i < param_count; ++i)
+ func_type.params[i] = va_arg(args, wasm_rt_type_t);
+ for (i = 0; i < result_count; ++i)
+ func_type.results[i] = va_arg(args, wasm_rt_type_t);
+ va_end(args);
+
+ for (i = 0; i < g_func_type_count; ++i) {
+ if (func_types_are_equal(&g_func_types[i], &func_type)) {
+ free(func_type.params);
+ free(func_type.results);
+ return i + 1;
+ }
+ }
+
+ u32 idx = g_func_type_count++;
+ g_func_types = realloc(g_func_types, g_func_type_count * sizeof(FuncType));
+ g_func_types[idx] = func_type;
+ return idx + 1;
+}
+
+void wasm_rt_allocate_memory(wasm_rt_memory_t* memory,
+ u32 initial_pages,
+ u32 max_pages) {
+ memory->pages = initial_pages;
+ memory->max_pages = max_pages;
+ memory->size = initial_pages * PAGE_SIZE;
+ memory->data = calloc(memory->size, 1);
+}
+
+u32 wasm_rt_grow_memory(wasm_rt_memory_t* memory, u32 delta) {
+ u32 old_pages = memory->pages;
+ u32 new_pages = memory->pages + delta;
+ if (new_pages < old_pages || new_pages > memory->max_pages) {
+ return (u32)-1;
+ }
+ memory->data = realloc(memory->data, new_pages);
+ memory->pages = new_pages;
+ memory->size = new_pages * PAGE_SIZE;
+ return old_pages;
+}
+
+void wasm_rt_allocate_table(wasm_rt_table_t* table,
+ u32 elements,
+ u32 max_elements) {
+ table->size = elements;
+ table->max_size = max_elements;
+ table->data = calloc(table->size, sizeof(wasm_rt_elem_t));
+}
+
+
+/*
+ * spectest implementations
+ */
+static void spectest_print_vv(void) {
+ printf("spectest.print()\n");
+}
+
+static void spectest_print_vi(uint32_t i) {
+ printf("spectest.print(%d)\n", i);
+}
+
+static void spectest_print_vf(float f) {
+ printf("spectest.print(%g)\n", f);
+}
+
+static void spectest_print_vif(uint32_t i, float f) {
+ printf("spectest.print(%d %g)\n", i, f);
+}
+
+static void spectest_print_vd(double d) {
+ printf("spectest.print(%g)\n", d);
+}
+
+static void spectest_print_vdd(double d1, double d2) {
+ printf("spectest.print(%g %g)\n", d1, d2);
+}
+
+static wasm_rt_table_t spectest_table;
+static wasm_rt_memory_t spectest_memory;
+static uint32_t spectest_global = 666;
+
+void (*Z_spectestZ_printZ_vv)(void) = &spectest_print_vv;
+void (*Z_spectestZ_printZ_vi)(uint32_t) = &spectest_print_vi;
+void (*Z_spectestZ_printZ_vf)(float) = &spectest_print_vf;
+void (*Z_spectestZ_printZ_vif)(uint32_t, float) = &spectest_print_vif;
+void (*Z_spectestZ_printZ_vd)(double) = &spectest_print_vd;
+void (*Z_spectestZ_printZ_vdd)(double, double) = &spectest_print_vdd;
+wasm_rt_table_t* Z_spectestZ_table = &spectest_table;
+wasm_rt_memory_t* Z_spectestZ_memory = &spectest_memory;
+uint32_t* Z_spectestZ_globalZ_i = &spectest_global;
+
+static void init_spectest_module(void) {
+ wasm_rt_allocate_memory(&spectest_memory, 1, 2);
+ wasm_rt_allocate_table(&spectest_table, 10, 20);
+}
+
+
+int main(int argc, char** argv) {
+ init_spectest_module();
+ run_spec_tests();
+ printf("%u/%u tests passed.\n", g_tests_passed, g_tests_run);
+ return g_tests_passed != g_tests_run;
+}
+