From a8cff25e47f37d76811d842eb7c4275b819c8027 Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Tue, 1 Mar 2022 17:08:27 -0800 Subject: [PATCH] Add windows implementation of wasm2c runtime Split out from #1833 --- CMakeLists.txt | 18 ++- test/run-spec-wasm2c.py | 20 +-- test/run-tests.py | 4 - test/spec-wasm2c-prefix.c | 4 +- wasm2c/README.md | 7 +- wasm2c/wasm-rt-impl.c | 24 +++- wasm2c/wasm-rt-os-unix.c | 190 ++++++++++++++++++++++++++++ wasm2c/wasm-rt-os-win.c | 256 ++++++++++++++++++++++++++++++++++++++ wasm2c/wasm-rt-os.h | 47 +++++++ wasm2c/wasm-rt.h | 27 ++-- 10 files changed, 560 insertions(+), 37 deletions(-) create mode 100644 wasm2c/wasm-rt-os-unix.c create mode 100644 wasm2c/wasm-rt-os-win.c create mode 100644 wasm2c/wasm-rt-os.h diff --git a/CMakeLists.txt b/CMakeLists.txt index f5d2b96e8e..f9791834ab 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -351,11 +351,19 @@ set(WABT_LIBRARY_SRC add_library(wabt STATIC ${WABT_LIBRARY_SRC}) -IF (NOT WIN32) - add_library(wasm-rt-impl STATIC wasm2c/wasm-rt-impl.c wasm2c/wasm-rt-impl.h) - install(TARGETS wasm-rt-impl DESTINATION ${CMAKE_INSTALL_LIBDIR}) - install(FILES wasm2c/wasm-rt.h wasm2c/wasm-rt-impl.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) -endif () +add_library(wasm-rt-impl SHARED STATIC + wasm2c/wasm-rt-impl.c + wasm2c/wasm-rt-os-unix.c + wasm2c/wasm-rt-os-win.c) +set_property(TARGET wasm-rt-impl PROPERTY POSITION_INDEPENDENT_CODE ON) +install(TARGETS wasm-rt-impl DESTINATION ${CMAKE_INSTALL_LIBDIR}) +install(FILES wasm2c/wasm-rt.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + +add_custom_target(wasm-rt-impl-copy-to-bin ALL + COMMAND ${CMAKE_COMMAND} -E make_directory ${WABT_SOURCE_DIR}/bin + COMMAND ${CMAKE_COMMAND} -E copy $ ${WABT_SOURCE_DIR}/bin + DEPENDS wasm-rt-impl +) if (BUILD_FUZZ_TOOLS) set(FUZZ_FLAGS "-fsanitize=fuzzer,address") diff --git a/test/run-spec-wasm2c.py b/test/run-spec-wasm2c.py index b3e66c6a9f..e17bd919dc 100755 --- a/test/run-spec-wasm2c.py +++ b/test/run-spec-wasm2c.py @@ -29,6 +29,7 @@ SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) WASM2C_DIR = os.path.join(find_exe.REPO_ROOT_DIR, 'wasm2c') +IS_WINDOWS = sys.platform == 'win32' def ReinterpretF32(f32_bits): @@ -335,7 +336,10 @@ def _Action(self, command): def Compile(cc, c_filename, out_dir, *args): o_filename = utils.ChangeDir(utils.ChangeExt(c_filename, '.o'), out_dir) - cc.RunWithArgs('-c', c_filename, '-o', o_filename, *args) + if IS_WINDOWS: + cc.RunWithArgs('/c', c_filename, '/Fo' + o_filename, *args) + else: + cc.RunWithArgs('-c', c_filename, '-o', o_filename, *args) return o_filename @@ -345,6 +349,9 @@ def Link(cc, o_filenames, main_exe, *args): def main(args): + default_compiler = 'cc' + if IS_WINDOWS: + default_compiler = 'cl.exe' parser = argparse.ArgumentParser() parser.add_argument('-o', '--out-dir', metavar='PATH', help='output directory for files.') @@ -356,7 +363,8 @@ def main(args): 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') + help='the path to the C compiler', + default=default_compiler) parser.add_argument('--cflags', metavar='FLAGS', help='additional flags for C compiler.', action='append', default=[]) @@ -423,10 +431,6 @@ def main(args): 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()): wasm_filename = os.path.join(out_dir, wasm_filename) c_filename = utils.ChangeExt(wasm_filename, '.c') @@ -438,7 +442,9 @@ def main(args): if options.compile: o_filenames.append(Compile(cc, main_filename, out_dir, includes, defines)) main_exe = utils.ChangeExt(json_file_path, '') - Link(cc, o_filenames, main_exe, '-lm') + find_exe.GetDefaultPath() + Link(cc, o_filenames, main_exe, + '-L' + find_exe.GetDefaultPath(), '-lwasm-rt-impl', '-lm') if options.compile and options.run: utils.Executable(main_exe, forward_stdout=True).RunWithArgs() diff --git a/test/run-tests.py b/test/run-tests.py index 766d05788a..34a2ee34d8 100755 --- a/test/run-tests.py +++ b/test/run-tests.py @@ -158,10 +158,6 @@ ] } -# TODO(binji): Add Windows support for compiling using run-spec-wasm2c.py -if IS_WINDOWS: - TOOLS['run-spec-wasm2c'].append(('SKIP', '')) - ROUNDTRIP_TOOLS = ('wat2wasm',) diff --git a/test/spec-wasm2c-prefix.c b/test/spec-wasm2c-prefix.c index 50998f1bfd..b57f820d66 100644 --- a/test/spec-wasm2c-prefix.c +++ b/test/spec-wasm2c-prefix.c @@ -12,8 +12,8 @@ #include "wasm-rt.h" #include "wasm-rt-impl.h" -int g_tests_run; -int g_tests_passed; +static int g_tests_run; +static int g_tests_passed; static void run_spec_tests(void); diff --git a/wasm2c/README.md b/wasm2c/README.md index 43af5e40c4..a586b42188 100644 --- a/wasm2c/README.md +++ b/wasm2c/README.md @@ -90,11 +90,12 @@ int main(int argc, char** argv) { ``` To compile the executable, we need to use `main.c` and the generated `fac.c`. -We'll also include `wasm-rt-impl.c` which has implementations of the various -`wasm_rt_*` functions used by `fac.c` and `fac.h`. +We'll also include `wasm-rt-impl.c`, `wasm-rt-os-unix.c` and `wasm-rt-os-win.c` +which include some OS specific initialization which has implementations of the +various `wasm_rt_*` functions used by `fac.c` and `fac.h`. ```sh -$ cc -o fac main.c fac.c wasm-rt-impl.c +$ cc -o fac main.c fac.c wasm-rt-impl.c wasm-rt-os-unix.c wasm-rt-os-win.c ``` Now let's test it out! diff --git a/wasm2c/wasm-rt-impl.c b/wasm2c/wasm-rt-impl.c index 4a8b3baf46..043133a93a 100644 --- a/wasm2c/wasm-rt-impl.c +++ b/wasm2c/wasm-rt-impl.c @@ -15,6 +15,7 @@ */ #include "wasm-rt-impl.h" +#include "wasm-rt-os.h" #include #include @@ -108,7 +109,10 @@ static void signal_handler(int sig, siginfo_t* si, void* unused) { } #endif -void wasm_rt_allocate_memory(wasm_rt_memory_t* memory, +// Heap aligned to 4GB +#define WASM_HEAP_ALIGNMENT 0x100000000ull + +bool 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; @@ -130,12 +134,17 @@ void wasm_rt_allocate_memory(wasm_rt_memory_t* memory, /* Reserve 8GiB. */ void* addr = - mmap(NULL, 0x200000000ul, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + os_mmap_aligned(NULL, 0x200000000ul, MMAP_PROT_NONE, MMAP_MAP_NONE, + WASM_HEAP_ALIGNMENT, /*alignment_offset=*/0); + if (addr == (void*)-1) { - perror("mmap failed"); + os_print_last_error("os_mmap failed."); abort(); } - mprotect(addr, byte_length, PROT_READ | PROT_WRITE); + int ret = os_mmap_commit(addr, byte_length, MMAP_PROT_READ | MMAP_PROT_WRITE); + if (ret != 0) { + return false; + } memory->data = addr; #else memory->data = calloc(byte_length, 1); @@ -143,6 +152,7 @@ void wasm_rt_allocate_memory(wasm_rt_memory_t* memory, memory->size = byte_length; memory->pages = initial_pages; memory->max_pages = max_pages; + return true; } uint32_t wasm_rt_grow_memory(wasm_rt_memory_t* memory, uint32_t delta) { @@ -159,7 +169,11 @@ uint32_t wasm_rt_grow_memory(wasm_rt_memory_t* memory, uint32_t delta) { 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); + int ret = os_mmap_commit(new_data + old_size, delta_size, + MMAP_PROT_READ | MMAP_PROT_WRITE); + if (ret != 0) { + return (uint32_t)-1; + } #else uint8_t* new_data = realloc(memory->data, new_size); if (new_data == NULL) { diff --git a/wasm2c/wasm-rt-os-unix.c b/wasm2c/wasm-rt-os-unix.c new file mode 100644 index 0000000000..f981c4be24 --- /dev/null +++ b/wasm2c/wasm-rt-os-unix.c @@ -0,0 +1,190 @@ +// Based on +// https://web.archive.org/web/20191012035921/http://nadeausoftware.com/articles/2012/01/c_c_tip_how_use_compiler_predefined_macros_detect_operating_system#BSD +// Check for any posix or unix OS +#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || \ + (defined(__APPLE__) && defined(__MACH__))) + +#include "wasm-rt-os.h" +#include "wasm-rt.h" + +#include +#include +#include +#include +#include + +#if defined(__APPLE__) && defined(__MACH__) +// Macs priors to OSX 10.12 don't have the clock functions. So we will use mac +// specific options +#include +#include +#endif +#include +#include + +#ifdef VERBOSE_LOGGING +#define VERBOSE_LOG(...) \ + { printf(__VA_ARGS__); } +#else +#define VERBOSE_LOG(...) +#endif + +size_t os_getpagesize() { + return getpagesize(); +} + +void* os_mmap(void* hint, size_t size, int prot, int flags) { + int map_prot = PROT_NONE; + int map_flags = MAP_ANONYMOUS | MAP_PRIVATE; + uint64_t request_size, page_size; + uint8_t* addr; + + page_size = (uint64_t)os_getpagesize(); + request_size = (size + page_size - 1) & ~(page_size - 1); + + if ((size_t)request_size < size) + /* integer overflow */ + return NULL; + + if (request_size > 16 * (uint64_t)UINT32_MAX) + /* At most 16 G is allowed */ + return NULL; + + if (prot & MMAP_PROT_READ) + map_prot |= PROT_READ; + + if (prot & MMAP_PROT_WRITE) + map_prot |= PROT_WRITE; + + if (prot & MMAP_PROT_EXEC) + map_prot |= PROT_EXEC; + +#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) +#ifndef __APPLE__ + if (flags & MMAP_MAP_32BIT) + map_flags |= MAP_32BIT; +#endif +#endif + + if (flags & MMAP_MAP_FIXED) + map_flags |= MAP_FIXED; + + addr = mmap(hint, request_size, map_prot, map_flags, -1, 0); + + if (addr == MAP_FAILED) + return NULL; + + return addr; +} + +void os_munmap(void* addr, size_t size) { + uint64_t page_size = (uint64_t)os_getpagesize(); + uint64_t request_size = (size + page_size - 1) & ~(page_size - 1); + + if (addr) { + if (munmap(addr, request_size)) { + printf("os_munmap error addr:%p, size:0x%" PRIx64 ", errno:%d\n", addr, + request_size, errno); + } + } +} + +int os_mprotect(void* addr, size_t size, int prot) { + int map_prot = PROT_NONE; + uint64_t page_size = (uint64_t)os_getpagesize(); + uint64_t request_size = (size + page_size - 1) & ~(page_size - 1); + + if (!addr) + return 0; + + if (prot & MMAP_PROT_READ) + map_prot |= PROT_READ; + + if (prot & MMAP_PROT_WRITE) + map_prot |= PROT_WRITE; + + if (prot & MMAP_PROT_EXEC) + map_prot |= PROT_EXEC; + + return mprotect(addr, request_size, map_prot); +} + +void* os_mmap_aligned(void* addr, + size_t requested_length, + int prot, + int flags, + size_t alignment, + size_t alignment_offset) { + size_t padded_length = requested_length + alignment + alignment_offset; + uintptr_t unaligned = (uintptr_t)os_mmap(addr, padded_length, prot, flags); + + VERBOSE_LOG( + "os_mmap_aligned: alignment:%llu, alignment_offset:%llu, " + "requested_length:%llu, padded_length: %llu, initial mapping: %p\n", + (unsigned long long)alignment, (unsigned long long)alignment_offset, + (unsigned long long)requested_length, (unsigned long long)padded_length, + (void*)unaligned); + + if (!unaligned) { + return (void*)unaligned; + } + + // Round up the next address that has addr % alignment = 0 + const size_t alignment_corrected = alignment == 0 ? 1 : alignment; + uintptr_t aligned_nonoffset = + (unaligned + (alignment_corrected - 1)) & ~(alignment_corrected - 1); + + // Currently offset 0 is aligned according to alignment + // Alignment needs to be enforced at the given offset + uintptr_t aligned = 0; + if ((aligned_nonoffset - alignment_offset) >= unaligned) { + aligned = aligned_nonoffset - alignment_offset; + } else { + aligned = aligned_nonoffset - alignment_offset + alignment; + } + + // Sanity check + if (aligned < unaligned || + (aligned + (requested_length - 1)) > (unaligned + (padded_length - 1)) || + (aligned + alignment_offset) % alignment_corrected != 0) { + VERBOSE_LOG("os_mmap_aligned: sanity check fail. aligned: %p\n", + (void*)aligned); + os_munmap((void*)unaligned, padded_length); + return NULL; + } + + { + size_t unused_front = aligned - unaligned; + if (unused_front != 0) { + os_munmap((void*)unaligned, unused_front); + } + } + + { + size_t unused_back = + (unaligned + (padded_length - 1)) - (aligned + (requested_length - 1)); + if (unused_back != 0) { + os_munmap((void*)(aligned + requested_length), unused_back); + } + } + + VERBOSE_LOG("os_mmap_aligned: final mapping: %p\n", (void*)aligned); + return (void*)aligned; +} + +int os_mmap_commit(void* curr_heap_end_pointer, + size_t expanded_size, + int prot) { + return os_mprotect(curr_heap_end_pointer, expanded_size, prot); +} + +void os_print_last_error(const char* msg) { + perror(msg); +} + +#undef VERBOSE_LOG + +#else +// https://stackoverflow.com/questions/26541150/warning-iso-c-forbids-an-empty-translation-unit +typedef int make_iso_compilers_happy; +#endif diff --git a/wasm2c/wasm-rt-os-win.c b/wasm2c/wasm-rt-os-win.c new file mode 100644 index 0000000000..67cf84533e --- /dev/null +++ b/wasm2c/wasm-rt-os-win.c @@ -0,0 +1,256 @@ +// Based on +// https://web.archive.org/web/20191012035921/http://nadeausoftware.com/articles/2012/01/c_c_tip_how_use_compiler_predefined_macros_detect_operating_system#BSD +// Check for windows (non cygwin) environment +#if defined(_WIN32) + +#include "wasm-rt-os.h" +#include "wasm-rt.h" + +#include +#include +#include +#include +#include + +#include + +#ifdef VERBOSE_LOGGING +#define VERBOSE_LOG(...) \ + { printf(__VA_ARGS__); } +#else +#define VERBOSE_LOG(...) +#endif + +#define DONT_USE_VIRTUAL_ALLOC2 + +size_t os_getpagesize() { + SYSTEM_INFO S; + GetNativeSystemInfo(&S); + return S.dwPageSize; +} + +static void* win_mmap(void* hint, + size_t size, + int prot, + int flags, + DWORD alloc_flag) { + DWORD flProtect = PAGE_NOACCESS; + size_t request_size, page_size; + void* addr; + + page_size = os_getpagesize(); + request_size = (size + page_size - 1) & ~(page_size - 1); + + if (request_size < size) + /* integer overflow */ + return NULL; + + if (request_size == 0) + request_size = page_size; + + if (prot & MMAP_PROT_EXEC) { + if (prot & MMAP_PROT_WRITE) + flProtect = PAGE_EXECUTE_READWRITE; + else + flProtect = PAGE_EXECUTE_READ; + } else if (prot & MMAP_PROT_WRITE) + flProtect = PAGE_READWRITE; + else if (prot & MMAP_PROT_READ) + flProtect = PAGE_READONLY; + + addr = VirtualAlloc((LPVOID)hint, request_size, alloc_flag, flProtect); + return addr; +} + +void* os_mmap(void* hint, size_t size, int prot, int flags) { + DWORD alloc_flag = MEM_RESERVE | MEM_COMMIT; + return win_mmap(hint, size, prot, flags, alloc_flag); +} + +#ifndef DONT_USE_VIRTUAL_ALLOC2 +static void* win_mmap_aligned(void* hint, + size_t size, + int prot, + int flags, + size_t pow2alignment) { + DWORD alloc_flag = MEM_RESERVE | MEM_COMMIT; + DWORD flProtect = PAGE_NOACCESS; + size_t request_size, page_size; + void* addr; + + page_size = os_getpagesize(); + request_size = (size + page_size - 1) & ~(page_size - 1); + + if (request_size < size) + /* integer overflow */ + return NULL; + + if (request_size == 0) + request_size = page_size; + + if (prot & MMAP_PROT_EXEC) { + if (prot & MMAP_PROT_WRITE) + flProtect = PAGE_EXECUTE_READWRITE; + else + flProtect = PAGE_EXECUTE_READ; + } else if (prot & MMAP_PROT_WRITE) + flProtect = PAGE_READWRITE; + else if (prot & MMAP_PROT_READ) + flProtect = PAGE_READONLY; + + MEM_ADDRESS_REQUIREMENTS addressReqs = {0}; + MEM_EXTENDED_PARAMETER param = {0}; + + addressReqs.Alignment = pow2alignment; + addressReqs.HighestEndingAddress = 0; + addressReqs.LowestStartingAddress = 0; + + param.Type = MemExtendedParameterAddressRequirements; + param.Pointer = &addressReqs; + + addr = VirtualAlloc2(0, (LPVOID)addr, request_size, alloc_flag, flProtect, + ¶m, 1); + return addr; +} +#endif + +void os_munmap(void* addr, size_t size) { + DWORD alloc_flag = MEM_RELEASE; + if (addr) { + if (VirtualFree(addr, 0, alloc_flag) == 0) { + size_t page_size = os_getpagesize(); + size_t request_size = (size + page_size - 1) & ~(page_size - 1); + int64_t curr_err = errno; + printf("os_munmap error addr:%p, size:0x%zx, errno:%" PRId64 "\n", addr, + request_size, curr_err); + } + } +} + +int os_mprotect(void* addr, size_t size, int prot) { + DWORD flProtect = PAGE_NOACCESS; + + if (!addr) + return 0; + + if (prot & MMAP_PROT_EXEC) { + if (prot & MMAP_PROT_WRITE) + flProtect = PAGE_EXECUTE_READWRITE; + else + flProtect = PAGE_EXECUTE_READ; + } else if (prot & MMAP_PROT_WRITE) + flProtect = PAGE_READWRITE; + else if (prot & MMAP_PROT_READ) + flProtect = PAGE_READONLY; + + DWORD old; + BOOL succeeded = VirtualProtect((LPVOID)addr, size, flProtect, &old); + return succeeded ? 0 : -1; +} + +#ifndef DONT_USE_VIRTUAL_ALLOC2 +static int IsPowerOfTwoOrZero(size_t x) { + return (x & (x - 1)) == 0; +} +#endif + +void* os_mmap_aligned(void* addr, + size_t requested_length, + int prot, + int flags, + size_t alignment, + size_t alignment_offset) { +#ifndef DONT_USE_VIRTUAL_ALLOC2 + if (IsPowerOfTwoOrZero(alignment) && alignment_offset == 0) { + return win_mmap_aligned(addr, requested_length, prot, flags, alignment); + } else +#endif + { + size_t padded_length = requested_length + alignment + alignment_offset; + uintptr_t unaligned = + (uintptr_t)win_mmap(addr, padded_length, prot, flags, MEM_RESERVE); + + VERBOSE_LOG( + "os_mmap_aligned: alignment:%llu, alignment_offset:%llu, " + "requested_length:%llu, padded_length: %llu, initial mapping: %p\n", + (unsigned long long)alignment, (unsigned long long)alignment_offset, + (unsigned long long)requested_length, (unsigned long long)padded_length, + (void*)unaligned); + + if (!unaligned) { + return (void*)unaligned; + } + + // Round up the next address that has addr % alignment = 0 + const size_t alignment_corrected = alignment == 0 ? 1 : alignment; + uintptr_t aligned_nonoffset = + (unaligned + (alignment_corrected - 1)) & ~(alignment_corrected - 1); + + // Currently offset 0 is aligned according to alignment + // Alignment needs to be enforced at the given offset + uintptr_t aligned = 0; + if ((aligned_nonoffset - alignment_offset) >= unaligned) { + aligned = aligned_nonoffset - alignment_offset; + } else { + aligned = aligned_nonoffset - alignment_offset + alignment; + } + + if (aligned == unaligned && padded_length == requested_length) { + return (void*)aligned; + } + + // Sanity check + if (aligned < unaligned || + (aligned + (requested_length - 1)) > + (unaligned + (padded_length - 1)) || + (aligned + alignment_offset) % alignment_corrected != 0) { + VERBOSE_LOG("os_mmap_aligned: sanity check fail. aligned: %p\n", + (void*)aligned); + os_munmap((void*)unaligned, padded_length); + return NULL; + } + + // windows does not support partial unmapping, so unmap and remap + os_munmap((void*)unaligned, padded_length); + aligned = (uintptr_t)win_mmap((void*)aligned, requested_length, prot, flags, + MEM_RESERVE); + VERBOSE_LOG("os_mmap_aligned: final mapping: %p\n", (void*)aligned); + return (void*)aligned; + } +} + +int os_mmap_commit(void* curr_heap_end_pointer, + size_t expanded_size, + int prot) { + uintptr_t addr = (uintptr_t)win_mmap(curr_heap_end_pointer, expanded_size, + prot, MMAP_MAP_NONE, MEM_COMMIT); + int ret = addr ? 0 : -1; + return ret; +} + +void os_print_last_error(const char* msg) { + DWORD errorMessageID = GetLastError(); + if (errorMessageID != 0) { + LPSTR messageBuffer = 0; + // The api creates the buffer that holds the message + size_t size = FormatMessageA( + FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPSTR)&messageBuffer, 0, NULL); + (void)size; + // Copy the error message into a std::string. + printf("%s. %s\n", msg, messageBuffer); + LocalFree(messageBuffer); + } else { + printf("%s. No error code.\n", msg); + } +} + +#undef VERBOSE_LOG +#undef DONT_USE_VIRTUAL_ALLOC2 + +#else +// https://stackoverflow.com/questions/26541150/warning-iso-c-forbids-an-empty-translation-unit +typedef int make_iso_compilers_happy; +#endif diff --git a/wasm2c/wasm-rt-os.h b/wasm2c/wasm-rt-os.h new file mode 100644 index 0000000000..3b9ee5d75d --- /dev/null +++ b/wasm2c/wasm-rt-os.h @@ -0,0 +1,47 @@ +#ifndef WASM_RT_OS_H_ +#define WASM_RT_OS_H_ + +#include +#include +#include + +enum { + MMAP_PROT_NONE = 0, + MMAP_PROT_READ = 1, + MMAP_PROT_WRITE = 2, + MMAP_PROT_EXEC = 4 +}; + +/* Memory map flags */ +enum { + MMAP_MAP_NONE = 0, + /* Put the mapping into 0 to 2 G, supported only on x86_64 */ + MMAP_MAP_32BIT = 1, + /* Don't interpret addr as a hint: place the mapping at exactly + that address. */ + MMAP_MAP_FIXED = 2 +}; + +size_t os_getpagesize(); +// Try allocating Memory space. +// Returns pointer to allocated region on success, 0 on failure. +void* os_mmap(void* hint, size_t size, int prot, int flags); +void os_munmap(void* addr, size_t size); +// Set the permissions of the memory region. +// Returns 0 on success, non zero on failure. +int os_mprotect(void* addr, size_t size, int prot); +// Like mmap but returns an aligned region +void* os_mmap_aligned(void* addr, + size_t requested_length, + int prot, + int flags, + size_t alignment, + size_t alignment_offset); +// Commits and sets the permissions on an already allocated memory region +// Returns 0 on success, non zero on failure. +int os_mmap_commit(void* curr_heap_end_pointer, size_t expanded_size, int prot); + +// print the error message +void os_print_last_error(const char* msg); + +#endif diff --git a/wasm2c/wasm-rt.h b/wasm2c/wasm-rt.h index b0577b3636..de617a87fc 100644 --- a/wasm2c/wasm-rt.h +++ b/wasm2c/wasm-rt.h @@ -17,6 +17,7 @@ #ifndef WASM_RT_H_ #define WASM_RT_H_ +#include #include #ifdef __cplusplus @@ -68,6 +69,12 @@ extern "C" { #endif +#if defined(_MSC_VER) +#define WASM_RT_NO_RETURN __declspec(noreturn) +#else +#define WASM_RT_NO_RETURN __attribute__((noreturn)) +#endif + /** Reason a trap occurred. Provide this to `wasm_rt_trap`. */ typedef enum { WASM_RT_TRAP_NONE, /** No error. */ @@ -128,7 +135,7 @@ typedef struct { * 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)); +WASM_RT_NO_RETURN void wasm_rt_trap(wasm_rt_trap_t); /** 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. @@ -148,9 +155,7 @@ extern void wasm_rt_trap(wasm_rt_trap_t) __attribute__((noreturn)); * 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, - ...); +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`. @@ -160,9 +165,9 @@ extern uint32_t wasm_rt_register_func_type(uint32_t params, * // 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); +bool 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 @@ -177,7 +182,7 @@ extern void wasm_rt_allocate_memory(wasm_rt_memory_t*, * // Failed to grow memory. * } * ``` */ -extern uint32_t wasm_rt_grow_memory(wasm_rt_memory_t*, uint32_t pages); +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`. @@ -187,9 +192,9 @@ extern uint32_t wasm_rt_grow_memory(wasm_rt_memory_t*, uint32_t pages); * // 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); +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;