diff options
-rw-r--r-- | src/prebuilt/wasm2c.include.h | 53 | ||||
-rw-r--r-- | src/wasm2c.h.tmpl | 53 | ||||
-rwxr-xr-x | test/run-spec-wasm2c.py | 32 | ||||
-rw-r--r-- | test/spec-wasm2c-prefix.c | 110 | ||||
-rw-r--r-- | wasm2c/wasm-rt-impl.c | 118 | ||||
-rw-r--r-- | wasm2c/wasm-rt-impl.h | 52 | ||||
-rw-r--r-- | wasm2c/wasm-rt.h | 168 |
7 files changed, 371 insertions, 215 deletions
diff --git a/src/prebuilt/wasm2c.include.h b/src/prebuilt/wasm2c.include.h index d5ada500..d2657c5a 100644 --- a/src/prebuilt/wasm2c.include.h +++ b/src/prebuilt/wasm2c.include.h @@ -4,14 +4,9 @@ const char SECTION_NAME(top)[] = "extern \"C\" {\n" "#endif\n" "\n" -"#ifndef WASM_RT_INCLUDED_\n" -"#define WASM_RT_INCLUDED_\n" -"\n" "#include <stdint.h>\n" "\n" -"#ifndef WASM_RT_MAX_CALL_STACK_DEPTH\n" -"#define WASM_RT_MAX_CALL_STACK_DEPTH 500\n" -"#endif\n" +"#include \"wasm-rt.h\"\n" "\n" "#ifndef WASM_RT_MODULE_PREFIX\n" "#define WASM_RT_MODULE_PREFIX\n" @@ -35,52 +30,6 @@ const char SECTION_NAME(top)[] = "typedef float f32;\n" "typedef double f64;\n" "\n" -"typedef enum {\n" -" WASM_RT_TRAP_NONE,\n" -" WASM_RT_TRAP_OOB,\n" -" WASM_RT_TRAP_INT_OVERFLOW,\n" -" WASM_RT_TRAP_DIV_BY_ZERO,\n" -" WASM_RT_TRAP_INVALID_CONVERSION,\n" -" WASM_RT_TRAP_UNREACHABLE,\n" -" WASM_RT_TRAP_CALL_INDIRECT,\n" -" WASM_RT_TRAP_EXHAUSTION,\n" -"} wasm_rt_trap_t;\n" -"\n" -"typedef enum {\n" -" WASM_RT_I32,\n" -" WASM_RT_I64,\n" -" WASM_RT_F32,\n" -" WASM_RT_F64,\n" -"} wasm_rt_type_t;\n" -"\n" -"typedef void (*wasm_rt_anyfunc_t)(void);\n" -"\n" -"typedef struct {\n" -" uint32_t func_type;\n" -" wasm_rt_anyfunc_t func;\n" -"} wasm_rt_elem_t;\n" -"\n" -"typedef struct {\n" -" uint8_t* data;\n" -" uint32_t pages, max_pages;\n" -" uint32_t size;\n" -"} wasm_rt_memory_t;\n" -"\n" -"typedef struct {\n" -" wasm_rt_elem_t* data;\n" -" uint32_t max_size;\n" -" uint32_t size;\n" -"} wasm_rt_table_t;\n" -"\n" -"extern void wasm_rt_trap(wasm_rt_trap_t) __attribute__((noreturn));\n" -"extern uint32_t wasm_rt_register_func_type(uint32_t params, uint32_t results, ...);\n" -"extern void wasm_rt_allocate_memory(wasm_rt_memory_t*, uint32_t initial_pages, uint32_t max_pages);\n" -"extern uint32_t wasm_rt_grow_memory(wasm_rt_memory_t*, uint32_t pages);\n" -"extern void wasm_rt_allocate_table(wasm_rt_table_t*, uint32_t elements, uint32_t max_elements);\n" -"extern uint32_t wasm_rt_call_stack_depth;\n" -"\n" -"#endif /* WASM_RT_INCLUDED_ */\n" -"\n" "extern void WASM_RT_ADD_PREFIX(init)(void);\n" ; diff --git a/src/wasm2c.h.tmpl b/src/wasm2c.h.tmpl index 24b1af23..d4a80d64 100644 --- a/src/wasm2c.h.tmpl +++ b/src/wasm2c.h.tmpl @@ -3,14 +3,9 @@ extern "C" { #endif -#ifndef WASM_RT_INCLUDED_ -#define WASM_RT_INCLUDED_ - #include <stdint.h> -#ifndef WASM_RT_MAX_CALL_STACK_DEPTH -#define WASM_RT_MAX_CALL_STACK_DEPTH 500 -#endif +#include "wasm-rt.h" #ifndef WASM_RT_MODULE_PREFIX #define WASM_RT_MODULE_PREFIX @@ -34,52 +29,6 @@ typedef int64_t s64; typedef float f32; typedef double f64; -typedef enum { - WASM_RT_TRAP_NONE, - WASM_RT_TRAP_OOB, - WASM_RT_TRAP_INT_OVERFLOW, - WASM_RT_TRAP_DIV_BY_ZERO, - WASM_RT_TRAP_INVALID_CONVERSION, - WASM_RT_TRAP_UNREACHABLE, - WASM_RT_TRAP_CALL_INDIRECT, - WASM_RT_TRAP_EXHAUSTION, -} wasm_rt_trap_t; - -typedef enum { - WASM_RT_I32, - WASM_RT_I64, - WASM_RT_F32, - WASM_RT_F64, -} wasm_rt_type_t; - -typedef void (*wasm_rt_anyfunc_t)(void); - -typedef struct { - uint32_t func_type; - wasm_rt_anyfunc_t func; -} wasm_rt_elem_t; - -typedef struct { - uint8_t* data; - uint32_t pages, max_pages; - uint32_t size; -} wasm_rt_memory_t; - -typedef struct { - wasm_rt_elem_t* data; - uint32_t max_size; - uint32_t size; -} wasm_rt_table_t; - -extern void wasm_rt_trap(wasm_rt_trap_t) __attribute__((noreturn)); -extern uint32_t wasm_rt_register_func_type(uint32_t params, uint32_t results, ...); -extern void wasm_rt_allocate_memory(wasm_rt_memory_t*, uint32_t initial_pages, uint32_t max_pages); -extern uint32_t wasm_rt_grow_memory(wasm_rt_memory_t*, uint32_t pages); -extern void wasm_rt_allocate_table(wasm_rt_table_t*, uint32_t elements, uint32_t max_elements); -extern uint32_t wasm_rt_call_stack_depth; - -#endif /* WASM_RT_INCLUDED_ */ - extern void WASM_RT_ADD_PREFIX(init)(void); %%bottom #ifdef __cplusplus diff --git a/test/run-spec-wasm2c.py b/test/run-spec-wasm2c.py index 0a2d3e07..baf08a72 100755 --- a/test/run-spec-wasm2c.py +++ b/test/run-spec-wasm2c.py @@ -33,6 +33,7 @@ import utils from utils import Error SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) +WASM2C_DIR = os.path.join(find_exe.REPO_ROOT_DIR, 'wasm2c') def ReinterpretF32(f32_bits): @@ -294,6 +295,18 @@ class CWriter(object): raise Error('Unexpected action type: %s' % type_) +def Compile(cc, c_filename, out_dir, *args): + out_dir = os.path.abspath(out_dir) + o_filename = utils.ChangeDir(utils.ChangeExt(c_filename, '.o'), out_dir) + cc.RunWithArgs('-c', '-o', o_filename, c_filename, *args, cwd=out_dir) + return o_filename + + +def Link(cc, o_filenames, main_exe, out_dir, *args): + args = ['-o', main_exe] + o_filenames + list(args) + cc.RunWithArgs(*args, cwd=out_dir) + + def main(args): parser = argparse.ArgumentParser() parser.add_argument('-o', '--out-dir', metavar='PATH', @@ -303,6 +316,8 @@ def main(args): parser.add_argument('--bindir', metavar='PATH', default=find_exe.GetDefaultPath(), help='directory to search for all executables.') + parser.add_argument('--wasmrt-dir', metavar='PATH', + help='directory with wasm-rt files', default=WASM2C_DIR) parser.add_argument('--cc', metavar='PATH', help='the path to the C compiler', default='cc') parser.add_argument('--cflags', metavar='FLAGS', @@ -361,23 +376,24 @@ def main(args): out_main_file.write(output.getvalue()) o_filenames = [] + includes = '-I%s' % options.wasmrt_dir + + # Compile wasm-rt-impl. + wasm_rt_impl_c = os.path.join(options.wasmrt_dir, 'wasm-rt-impl.c') + o_filenames.append(Compile(cc, wasm_rt_impl_c, out_dir, includes)) for i, wasm_filename in enumerate(cwriter.GetModuleFilenames()): c_filename = utils.ChangeExt(wasm_filename, '.c') wasm2c.RunWithArgs(wasm_filename, '-o', c_filename, cwd=out_dir) if options.compile: - o_filename = utils.ChangeExt(wasm_filename, '.o') - o_filenames.append(o_filename) - cc.RunWithArgs( - '-c', '-o', o_filename, - '-DWASM_RT_MODULE_PREFIX=%s' % cwriter.GetModulePrefix(i), - c_filename, cwd=out_dir) + defines = '-DWASM_RT_MODULE_PREFIX=%s' % cwriter.GetModulePrefix(i) + o_filenames.append(Compile(cc, c_filename, out_dir, includes, defines)) if options.compile: main_c = os.path.basename(main_filename) + o_filenames.append(Compile(cc, main_c, out_dir, includes, defines)) main_exe = os.path.basename(utils.ChangeExt(json_file_path, '')) - args = ['-o', main_exe, main_c] + o_filenames + ['-lm'] - cc.RunWithArgs(*args, cwd=out_dir) + Link(cc, o_filenames, main_exe, out_dir, '-lm') if options.compile and options.run: utils.Executable(os.path.join(out_dir, main_exe), diff --git a/test/spec-wasm2c-prefix.c b/test/spec-wasm2c-prefix.c index c1cab955..897872b4 100644 --- a/test/spec-wasm2c-prefix.c +++ b/test/spec-wasm2c-prefix.c @@ -2,7 +2,6 @@ #define __STDC_FORMAT_MACROS #include <inttypes.h> #include <math.h> -#include <setjmp.h> #include <stdarg.h> #include <stdbool.h> #include <stdint.h> @@ -10,20 +9,11 @@ #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; +#include "wasm-rt.h" +#include "wasm-rt-impl.h" 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); @@ -38,7 +28,7 @@ static void error(const char* file, int line, const char* format, ...) { #define ASSERT_TRAP(f) \ do { \ g_tests_run++; \ - if (setjmp(g_jmp_buf) != 0) { \ + if (wasm_rt_impl_try() != 0) { \ g_tests_passed++; \ } else { \ (void)(f); \ @@ -49,7 +39,7 @@ static void error(const char* file, int line, const char* format, ...) { #define ASSERT_EXHAUSTION(f) \ do { \ g_tests_run++; \ - wasm_rt_trap_t code = setjmp(g_jmp_buf); \ + wasm_rt_trap_t code = wasm_rt_impl_try(); \ switch (code) { \ case WASM_RT_TRAP_NONE: \ (void)(f); \ @@ -70,7 +60,7 @@ static void error(const char* file, int line, const char* format, ...) { #define ASSERT_RETURN(f) \ do { \ g_tests_run++; \ - if (setjmp(g_jmp_buf) != 0) { \ + if (wasm_rt_impl_try() != 0) { \ error(__FILE__, __LINE__, #f " trapped.\n"); \ } else { \ f; \ @@ -81,7 +71,7 @@ static void error(const char* file, int line, const char* format, ...) { #define ASSERT_RETURN_T(type, fmt, f, expected) \ do { \ g_tests_run++; \ - if (setjmp(g_jmp_buf) != 0) { \ + if (wasm_rt_impl_try() != 0) { \ error(__FILE__, __LINE__, #f " trapped.\n"); \ } else { \ type actual = f; \ @@ -98,7 +88,7 @@ static void error(const char* file, int line, const char* format, ...) { #define ASSERT_RETURN_NAN_T(type, itype, fmt, f, kind) \ do { \ g_tests_run++; \ - if (setjmp(g_jmp_buf) != 0) { \ + if (wasm_rt_impl_try() != 0) { \ error(__FILE__, __LINE__, #f " trapped.\n"); \ } else { \ type actual = f; \ @@ -181,91 +171,6 @@ 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 @@ -322,4 +227,3 @@ int main(int argc, char** argv) { printf("%u/%u tests passed.\n", g_tests_passed, g_tests_run); return g_tests_passed != g_tests_run; } - diff --git a/wasm2c/wasm-rt-impl.c b/wasm2c/wasm-rt-impl.c new file mode 100644 index 00000000..859773bb --- /dev/null +++ b/wasm2c/wasm-rt-impl.c @@ -0,0 +1,118 @@ +/* + * Copyright 2018 WebAssembly Community Group participants + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "wasm-rt-impl.h" + +#include <assert.h> +#include <stdarg.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdlib.h> + +#define PAGE_SIZE 65536 + +typedef struct FuncType { + wasm_rt_type_t* params; + wasm_rt_type_t* results; + uint32_t param_count; + uint32_t result_count; +} FuncType; + +uint32_t wasm_rt_call_stack_depth; + +jmp_buf g_jmp_buf; +FuncType* g_func_types; +uint32_t g_func_type_count; + +void wasm_rt_trap(wasm_rt_trap_t code) { + assert(code != WASM_RT_TRAP_NONE); + longjmp(g_jmp_buf, code); +} + +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; +} + +uint32_t wasm_rt_register_func_type(uint32_t param_count, + uint32_t 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); + + uint32_t 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; + } + } + + uint32_t 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, + uint32_t initial_pages, + uint32_t max_pages) { + memory->pages = initial_pages; + memory->max_pages = max_pages; + memory->size = initial_pages * PAGE_SIZE; + memory->data = calloc(memory->size, 1); +} + +uint32_t wasm_rt_grow_memory(wasm_rt_memory_t* memory, uint32_t delta) { + uint32_t old_pages = memory->pages; + uint32_t new_pages = memory->pages + delta; + if (new_pages < old_pages || new_pages > memory->max_pages) { + return (uint32_t)-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, + uint32_t elements, + uint32_t max_elements) { + table->size = elements; + table->max_size = max_elements; + table->data = calloc(table->size, sizeof(wasm_rt_elem_t)); +} diff --git a/wasm2c/wasm-rt-impl.h b/wasm2c/wasm-rt-impl.h new file mode 100644 index 00000000..f4bfa09d --- /dev/null +++ b/wasm2c/wasm-rt-impl.h @@ -0,0 +1,52 @@ +/* + * Copyright 2018 WebAssembly Community Group participants + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef WASM_RT_IMPL_H_ +#define WASM_RT_IMPL_H_ + +#include <setjmp.h> + +#include "wasm-rt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** A setjmp buffer used for handling traps. */ +extern jmp_buf g_jmp_buf; + +/** Convenience macro to use before calling a wasm function. On first execution + * it will return `WASM_RT_TRAP_NONE` (i.e. 0). If the function traps, it will + * jump back and return the trap that occurred. + * + * ``` + * wasm_rt_trap_t code = wasm_rt_impl_try(); + * if (code != 0) { + * printf("A trap occurred with code: %d\n", code); + * ... + * } + * + * // Call the potentially-trapping function. + * my_wasm_func(); + * ``` + */ +#define wasm_rt_impl_try() setjmp(g_jmp_buf) + +#ifdef __cplusplus +} +#endif + +#endif // WASM_RT_IMPL_H_ diff --git a/wasm2c/wasm-rt.h b/wasm2c/wasm-rt.h new file mode 100644 index 00000000..494fde19 --- /dev/null +++ b/wasm2c/wasm-rt.h @@ -0,0 +1,168 @@ +/* + * Copyright 2018 WebAssembly Community Group participants + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef WASM_RT_H_ +#define WASM_RT_H_ + +#include <stdint.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** Maximum stack depth before trapping. This can be configured by defining + * this symbol before including wasm-rt when building the generated c files, + * for example: + * + * ``` + * cc -c -DWASM_RT_MAX_CALL_STACK_DEPTH=100 my_module.c -o my_module.o + * ``` + * */ +#ifndef WASM_RT_MAX_CALL_STACK_DEPTH +#define WASM_RT_MAX_CALL_STACK_DEPTH 500 +#endif + +/** Reason a trap occurred. Provide this to `wasm_rt_trap`. */ +typedef enum { + WASM_RT_TRAP_NONE, /** No error. */ + WASM_RT_TRAP_OOB, /** Out-of-bounds access in linear memory. */ + WASM_RT_TRAP_INT_OVERFLOW, /** Integer overflow on divide or truncation. */ + WASM_RT_TRAP_DIV_BY_ZERO, /** Integer divide by zero. */ + WASM_RT_TRAP_INVALID_CONVERSION, /** Conversion from NaN to integer. */ + WASM_RT_TRAP_UNREACHABLE, /** Unreachable instruction executed. */ + WASM_RT_TRAP_CALL_INDIRECT, /** Invalid call_indirect, for any reason. */ + WASM_RT_TRAP_EXHAUSTION, /** Call stack exhausted. */ +} wasm_rt_trap_t; + +/** Value types. Used to define function signatures. */ +typedef enum { + WASM_RT_I32, + WASM_RT_I64, + WASM_RT_F32, + WASM_RT_F64, +} wasm_rt_type_t; + +/** A function type for all `anyfunc` functions in a Table. All functions are + * stored in this canonical form, but must be cast to their proper signature to + * call. */ +typedef void (*wasm_rt_anyfunc_t)(void); + +/** A single element of a Table. */ +typedef struct { + /** The index as returned from `wasm_rt_register_func_type`. */ + uint32_t func_type; + /** The function. The embedder must know the actual C signature of the + * function and cast to it before calling. */ + wasm_rt_anyfunc_t func; +} wasm_rt_elem_t; + +/** A Memory object. */ +typedef struct { + /** The linear memory data, with a byte length of `size`. */ + uint8_t* data; + /** The current and maximum page count for this Memory object. If there is no + * maximum, `max_pages` is 0xffffffffu (i.e. UINT32_MAX). */ + uint32_t pages, max_pages; + /** The current size of the linear memory, in bytes. */ + uint32_t size; +} wasm_rt_memory_t; + +/** A Table object. */ +typedef struct { + /** The table element data, with an element count of `size`. */ + wasm_rt_elem_t* data; + /** The maximum element count of this Table object. If there is no maximum, + * `max_size` is 0xffffffffu (i.e. UINT32_MAX). */ + uint32_t max_size; + /** The current element count of the table. */ + uint32_t size; +} wasm_rt_table_t; + +/** Stop execution immediately and jump back to the call to `wasm_rt_try`. + * The result of `wasm_rt_try` will be the provided trap reason. + * + * This is typically called by the generated code, and not the embedder. */ +extern void wasm_rt_trap(wasm_rt_trap_t) __attribute__((noreturn)); + +/** Register a function type with the given signature. The returned function + * index is guaranteed to be the same for all calls with the same signature. + * The following varargs must all be of type `wasm_rt_type_t`, first the + * params` and then the `results`. + * + * ``` + * // Register (func (param i32 f32) (result i64)). + * wasm_rt_register_func_type(2, 1, WASM_RT_I32, WASM_RT_F32, WASM_RT_I64); + * => returns 1 + * + * // Register (func (result i64)). + * wasm_rt_register_func_type(0, 1, WASM_RT_I32); + * => returns 2 + * + * // Register (func (param i32 f32) (result i64)) again. + * wasm_rt_register_func_type(2, 1, WASM_RT_I32, WASM_RT_F32, WASM_RT_I64); + * => returns 1 + * ``` */ +extern uint32_t wasm_rt_register_func_type(uint32_t params, + uint32_t results, + ...); + +/** Initialize a Memory object with an initial page size of `initial_pages` and + * a maximum page size of `max_pages`. + * + * ``` + * wasm_rt_memory_t my_memory; + * // 1 initial page (65536 bytes), and a maximum of 2 pages. + * wasm_rt_allocate_memory(&my_memory, 1, 2); + * ``` */ +extern void wasm_rt_allocate_memory(wasm_rt_memory_t*, + uint32_t initial_pages, + uint32_t max_pages); + +/** Grow a Memory object by `pages`, and return the previous page count. If + * this new page count is greater than the maximum page count, the grow fails + * and 0xffffffffu (UINT32_MAX) is returned instead. + * + * ``` + * wasm_rt_memory_t my_memory; + * ... + * // Grow memory by 10 pages. + * uint32_t old_page_size = wasm_rt_grow_memory(&my_memory, 10); + * if (old_page_size == UINT32_MAX) { + * // Failed to grow memory. + * } + * ``` */ +extern uint32_t wasm_rt_grow_memory(wasm_rt_memory_t*, uint32_t pages); + +/** Initialize a Table object with an element count of `elements` and a maximum + * page size of `max_elements`. + * + * ``` + * wasm_rt_table_t my_table; + * // 5 elemnets and a maximum of 10 elements. + * wasm_rt_allocate_table(&my_table, 5, 10); + * ``` */ +extern void wasm_rt_allocate_table(wasm_rt_table_t*, + uint32_t elements, + uint32_t max_elements); + +/** Current call stack depth. */ +extern uint32_t wasm_rt_call_stack_depth; + +#ifdef __cplusplus +} +#endif + +#endif /* WASM_RT_H_ */ |