summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/prebuilt/wasm2c.include.h53
-rw-r--r--src/wasm2c.h.tmpl53
-rwxr-xr-xtest/run-spec-wasm2c.py32
-rw-r--r--test/spec-wasm2c-prefix.c110
-rw-r--r--wasm2c/wasm-rt-impl.c118
-rw-r--r--wasm2c/wasm-rt-impl.h52
-rw-r--r--wasm2c/wasm-rt.h168
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_ */