summaryrefslogtreecommitdiff
path: root/third_party/wabt/wasm2c
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/wabt/wasm2c')
-rw-r--r--third_party/wabt/wasm2c/README.md5
-rw-r--r--third_party/wabt/wasm2c/wasm-rt-impl.c182
-rw-r--r--third_party/wabt/wasm2c/wasm-rt-impl.h65
-rw-r--r--third_party/wabt/wasm2c/wasm-rt.h201
4 files changed, 453 insertions, 0 deletions
diff --git a/third_party/wabt/wasm2c/README.md b/third_party/wabt/wasm2c/README.md
new file mode 100644
index 000000000..16ab3fc6c
--- /dev/null
+++ b/third_party/wabt/wasm2c/README.md
@@ -0,0 +1,5 @@
+These files are part of WABT, but are currently not present in releases, so the
+directory is included as a fallback in Binaryen in a way that the files will be
+overwritten in case WABT contains them in the future.
+
+Original README: https://github.com/WebAssembly/wabt/blob/master/wasm2c/README.md
diff --git a/third_party/wabt/wasm2c/wasm-rt-impl.c b/third_party/wabt/wasm2c/wasm-rt-impl.c
new file mode 100644
index 000000000..c52063ab3
--- /dev/null
+++ b/third_party/wabt/wasm2c/wasm-rt-impl.c
@@ -0,0 +1,182 @@
+/*
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if WASM_RT_MEMCHECK_SIGNAL_HANDLER_POSIX
+#include <signal.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#endif
+
+#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;
+uint32_t g_saved_call_stack_depth;
+
+#if WASM_RT_MEMCHECK_SIGNAL_HANDLER
+bool g_signal_handler_installed = false;
+#endif
+
+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);
+ wasm_rt_call_stack_depth = g_saved_call_stack_depth;
+ WASM_RT_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;
+}
+
+#if WASM_RT_MEMCHECK_SIGNAL_HANDLER_POSIX
+static void signal_handler(int sig, siginfo_t* si, void* unused) {
+ wasm_rt_trap(WASM_RT_TRAP_OOB);
+}
+#endif
+
+void wasm_rt_allocate_memory(wasm_rt_memory_t* memory,
+ uint32_t initial_pages,
+ uint32_t max_pages) {
+ uint32_t byte_length = initial_pages * PAGE_SIZE;
+#if WASM_RT_MEMCHECK_SIGNAL_HANDLER_POSIX
+ if (!g_signal_handler_installed) {
+ g_signal_handler_installed = true;
+ struct sigaction sa;
+ sa.sa_flags = SA_SIGINFO;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_sigaction = signal_handler;
+
+ /* Install SIGSEGV and SIGBUS handlers, since macOS seems to use SIGBUS. */
+ if (sigaction(SIGSEGV, &sa, NULL) != 0 ||
+ sigaction(SIGBUS, &sa, NULL) != 0) {
+ perror("sigaction failed");
+ abort();
+ }
+ }
+
+ /* Reserve 8GiB. */
+ void* addr =
+ mmap(NULL, 0x200000000ul, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+ if (addr == (void*)-1) {
+ perror("mmap failed");
+ abort();
+ }
+ mprotect(addr, byte_length, PROT_READ | PROT_WRITE);
+ memory->data = addr;
+#else
+ memory->data = calloc(byte_length, 1);
+#endif
+ memory->size = byte_length;
+ memory->pages = initial_pages;
+ memory->max_pages = max_pages;
+}
+
+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 == 0) {
+ return 0;
+ }
+ if (new_pages < old_pages || new_pages > memory->max_pages) {
+ return (uint32_t)-1;
+ }
+ uint32_t old_size = old_pages * PAGE_SIZE;
+ uint32_t new_size = new_pages * PAGE_SIZE;
+ uint32_t delta_size = delta * PAGE_SIZE;
+#if WASM_RT_MEMCHECK_SIGNAL_HANDLER_POSIX
+ uint8_t* new_data = memory->data;
+ mprotect(new_data + old_size, delta_size, PROT_READ | PROT_WRITE);
+#else
+ uint8_t* new_data = realloc(memory->data, new_size);
+ if (new_data == NULL) {
+ return (uint32_t)-1;
+ }
+ memset(new_data + old_size, 0, delta_size);
+#endif
+ memory->pages = new_pages;
+ memory->size = new_size;
+ memory->data = new_data;
+ 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/third_party/wabt/wasm2c/wasm-rt-impl.h b/third_party/wabt/wasm2c/wasm-rt-impl.h
new file mode 100644
index 000000000..39d5ed930
--- /dev/null
+++ b/third_party/wabt/wasm2c/wasm-rt-impl.h
@@ -0,0 +1,65 @@
+/*
+ * 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;
+
+/** Saved call stack depth that will be restored in case a trap occurs. */
+extern uint32_t g_saved_call_stack_depth;
+
+#if WASM_RT_MEMCHECK_SIGNAL_HANDLER_POSIX
+#define WASM_RT_SETJMP(buf) sigsetjmp(buf, 1)
+#define WASM_RT_LONGJMP(buf, val) siglongjmp(buf, val)
+#else
+#define WASM_RT_SETJMP(buf) setjmp(buf)
+#define WASM_RT_LONGJMP(buf, val) longjmp(buf, val)
+#endif
+
+/** 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() \
+ (g_saved_call_stack_depth = wasm_rt_call_stack_depth, \
+ WASM_RT_SETJMP(g_jmp_buf))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // WASM_RT_IMPL_H_
diff --git a/third_party/wabt/wasm2c/wasm-rt.h b/third_party/wabt/wasm2c/wasm-rt.h
new file mode 100644
index 000000000..2797e8f71
--- /dev/null
+++ b/third_party/wabt/wasm2c/wasm-rt.h
@@ -0,0 +1,201 @@
+/*
+ * 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
+
+/** Enable memory checking via a signal handler via the following definition:
+ *
+ * #define WASM_RT_MEMCHECK_SIGNAL_HANDLER 1
+ *
+ * This is usually 10%-25% faster, but requires OS-specific support.
+ * */
+
+/** Check whether the signal handler is supported at all. */
+#if (defined(__linux__) || defined(__unix__) || defined(__APPLE__)) && \
+ defined(__WORDSIZE) && __WORDSIZE == 64
+
+/* If the signal handler is supported, then use it by default. */
+#ifndef WASM_RT_MEMCHECK_SIGNAL_HANDLER
+#define WASM_RT_MEMCHECK_SIGNAL_HANDLER 1
+#endif
+
+#if WASM_RT_MEMCHECK_SIGNAL_HANDLER
+#define WASM_RT_MEMCHECK_SIGNAL_HANDLER_POSIX 1
+#endif
+
+#else
+
+/* The signal handler is not supported, error out if the user was trying to
+ * enable it. */
+#if WASM_RT_MEMCHECK_SIGNAL_HANDLER
+#error "Signal handler is not supported for this OS/Architecture!"
+#endif
+
+#define WASM_RT_MEMCHECK_SIGNAL_HANDLER 0
+#define WASM_RT_MEMCHECK_SIGNAL_HANDLER_POSIX 0
+
+#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_ */