From 8ad9c1775f48727eb1f88341caab3d2727b4639e Mon Sep 17 00:00:00 2001 From: sophy228 Date: Tue, 11 Aug 2020 11:30:51 +0800 Subject: [PATCH] Add wamrc AoT compiler building support for Windows(MSVC) (#332) --- README.md | 4 +- build-scripts/runtime_lib.cmake | 2 + core/config.h | 4 + core/iwasm/aot/aot_reloc.h | 11 + core/iwasm/aot/aot_runtime.c | 2 +- core/iwasm/aot/arch/aot_reloc_x86_32.c | 2 + core/iwasm/common/arch/invokeNative_ia32.asm | 27 ++ core/iwasm/common/iwasm_common.cmake | 6 +- core/iwasm/common/wasm_c_api.c | 4 +- core/iwasm/common/wasm_c_api_internal.h | 4 +- .../libc-builtin/libc_builtin_wrapper.c | 18 +- core/shared/platform/windows/platform_init.c | 18 + .../platform/windows/platform_internal.h | 66 +++ core/shared/platform/windows/posix_malloc.c | 27 ++ .../platform/windows/shared_platform.cmake | 18 + core/shared/platform/windows/win_memmap.c | 79 ++++ core/shared/platform/windows/win_thread.c | 162 +++++++ core/shared/platform/windows/win_time.c | 16 + core/shared/utils/uncommon/bh_read_file.c | 53 ++- product-mini/platforms/windows/CMakeLists.txt | 121 ++++++ product-mini/platforms/windows/main.c | 402 ++++++++++++++++++ wamr-compiler/CMakeLists.txt | 65 ++- wamr-compiler/build_llvm.py | 98 +++++ 23 files changed, 1186 insertions(+), 23 deletions(-) create mode 100644 core/iwasm/common/arch/invokeNative_ia32.asm create mode 100644 core/shared/platform/windows/platform_init.c create mode 100644 core/shared/platform/windows/platform_internal.h create mode 100644 core/shared/platform/windows/posix_malloc.c create mode 100644 core/shared/platform/windows/shared_platform.cmake create mode 100644 core/shared/platform/windows/win_memmap.c create mode 100644 core/shared/platform/windows/win_thread.c create mode 100644 core/shared/platform/windows/win_time.c create mode 100644 product-mini/platforms/windows/CMakeLists.txt create mode 100644 product-mini/platforms/windows/main.c create mode 100644 wamr-compiler/build_llvm.py diff --git a/README.md b/README.md index 44481bc0..446209f8 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,7 @@ Both wasm binary file and AoT file are supported by iwasm. The wamrc AoT compile ```shell cd wamr-compiler -./build_llvm.sh (use build_llvm_xtensa.sh instead to support xtensa target) +./build_llvm.sh (use build_llvm_xtensa.sh instead to support xtensa target; use build_llvm.py for windows) mkdir build && cd build cmake .. make @@ -72,6 +72,8 @@ ln -s {current path}/wamrc /usr/bin/wamrc ``` For MacOS, you should replace `cmake ..` with `cmake -DWAMR_BUILD_PLATFORM=darwin ..`. +For Windows you should replace `cmake ..` with `cmake -D WAMR_BUILD_PLATFORM=windows -A Win32 ..`. + Application framework =================================== diff --git a/build-scripts/runtime_lib.cmake b/build-scripts/runtime_lib.cmake index 6687ecc1..eb5a90a1 100644 --- a/build-scripts/runtime_lib.cmake +++ b/build-scripts/runtime_lib.cmake @@ -82,8 +82,10 @@ if (WAMR_BUILD_THREAD_MGR EQUAL 1) endif () ####################### Common sources ####################### +if (NOT MSVC) set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -ffunction-sections -fdata-sections \ -Wall -Wno-unused-parameter -Wno-pedantic") +endif () # include the build config template file include (${CMAKE_CURRENT_LIST_DIR}/config_common.cmake) diff --git a/core/config.h b/core/config.h index c14eac4e..ba9a1a2f 100644 --- a/core/config.h +++ b/core/config.h @@ -125,7 +125,11 @@ enum { #endif /* WASM Interpreter labels-as-values feature */ +#ifdef __GNUC__ #define WASM_ENABLE_LABELS_AS_VALUES 1 +#else +#define WASM_ENABLE_LABELS_AS_VALUES 0 +#endif /* Enable fast interpreter or not */ #ifndef WASM_ENABLE_FAST_INTERP diff --git a/core/iwasm/aot/aot_reloc.h b/core/iwasm/aot/aot_reloc.h index bd6391c0..882780a2 100644 --- a/core/iwasm/aot/aot_reloc.h +++ b/core/iwasm/aot/aot_reloc.h @@ -29,6 +29,16 @@ typedef struct { #define REG_ATOMIC_WAIT_SYM() #endif +#if (defined(_WIN32) || defined(_WIN32_)) && defined(NDEBUG) +#define REG_COMMON_SYMBOLS \ + REG_SYM(aot_set_exception_with_id), \ + REG_SYM(aot_invoke_native), \ + REG_SYM(aot_call_indirect), \ + REG_SYM(wasm_runtime_enlarge_memory), \ + REG_SYM(wasm_runtime_set_exception), \ + REG_BULK_MEMORY_SYM() \ + REG_ATOMIC_WAIT_SYM() +#else /* else of (defined(_WIN32) || defined(_WIN32_)) && defined(NDEBUG) */ #define REG_COMMON_SYMBOLS \ REG_SYM(aot_set_exception_with_id), \ REG_SYM(aot_invoke_native), \ @@ -49,6 +59,7 @@ typedef struct { REG_SYM(rintf), \ REG_BULK_MEMORY_SYM() \ REG_ATOMIC_WAIT_SYM() +#endif /* end of (defined(_WIN32) || defined(_WIN32_)) && defined(NDEBUG) */ #define CHECK_RELOC_OFFSET(data_size) do { \ if (!check_reloc_offset(target_section_size, reloc_offset, data_size, \ diff --git a/core/iwasm/aot/aot_runtime.c b/core/iwasm/aot/aot_runtime.c index 7be1a234..107b5f93 100644 --- a/core/iwasm/aot/aot_runtime.c +++ b/core/iwasm/aot/aot_runtime.c @@ -1747,7 +1747,7 @@ aot_set_aux_stack(WASMExecEnv *exec_env, set the initial value for the global */ uint32 global_offset = module->globals[stack_top_idx].data_offset; - uint8 *global_addr = module_inst->global_data.ptr + global_offset; + uint8 *global_addr = (uint8 *)module_inst->global_data.ptr + global_offset; *(int32*)global_addr = start_offset; /* The aux stack boundary is a constant value, diff --git a/core/iwasm/aot/arch/aot_reloc_x86_32.c b/core/iwasm/aot/arch/aot_reloc_x86_32.c index a1424dae..6cc470e9 100644 --- a/core/iwasm/aot/arch/aot_reloc_x86_32.c +++ b/core/iwasm/aot/arch/aot_reloc_x86_32.c @@ -15,11 +15,13 @@ void __umoddi3(); static SymbolMap target_sym_map[] = { REG_COMMON_SYMBOLS +#if !defined(_WIN32) && !defined(_WIN32_) /* compiler-rt symbols that come from compiler(e.g. gcc) */ REG_SYM(__divdi3), REG_SYM(__udivdi3), REG_SYM(__moddi3), REG_SYM(__umoddi3) +#endif }; static void diff --git a/core/iwasm/common/arch/invokeNative_ia32.asm b/core/iwasm/common/arch/invokeNative_ia32.asm new file mode 100644 index 00000000..8bd28722 --- /dev/null +++ b/core/iwasm/common/arch/invokeNative_ia32.asm @@ -0,0 +1,27 @@ +; +; Copyright (C) 2019 Intel Corporation. All rights reserved. +; SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +; + + .386 + .model flat + .code +_invokeNative PROC + push ebp + mov ebp,esp + mov ecx, [ebp+16] ; ecx = argc */ + mov edx, [ebp+12] ; edx = argv */ + test ecx, ecx + jz skip_push_args ; if ecx == 0, skip pushing arguments */ + lea edx, [edx+ecx*4-4] ; edx = edx + ecx * 4 - 4 */ + sub edx,esp ; edx = edx - esp */ +loop_push: + push [esp+edx] + loop loop_push ; loop ecx counts */ +skip_push_args: + mov edx, [ebp+8] ; edx = func_ptr */ + call edx + leave + ret +_invokeNative ENDP +END \ No newline at end of file diff --git a/core/iwasm/common/iwasm_common.cmake b/core/iwasm/common/iwasm_common.cmake index aa3683d3..50173c4f 100644 --- a/core/iwasm/common/iwasm_common.cmake +++ b/core/iwasm/common/iwasm_common.cmake @@ -13,7 +13,11 @@ file (GLOB c_source_all ${IWASM_COMMON_DIR}/*.c) if (WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_em64.s) elseif (WAMR_BUILD_TARGET STREQUAL "X86_32") - set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_ia32.s) + if (WAMR_BUILD_PLATFORM STREQUAL "windows") + set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_ia32.asm) + else () + set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_ia32.s) + endif () elseif (WAMR_BUILD_TARGET MATCHES "ARM.*") if (WAMR_BUILD_TARGET MATCHES "ARM.*_VFP") set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_arm_vfp.s) diff --git a/core/iwasm/common/wasm_c_api.c b/core/iwasm/common/wasm_c_api.c index d8e2ddc2..7439ef21 100644 --- a/core/iwasm/common/wasm_c_api.c +++ b/core/iwasm/common/wasm_c_api.c @@ -1785,7 +1785,7 @@ aot_global_set(const AOTModuleInstance *inst_aot, .type; } - data = inst_aot->global_data.ptr + data_offset; + data = (void *)((uint8 *)inst_aot->global_data.ptr + data_offset); switch (val_type_rt) { case VALUE_TYPE_I32: bh_assert(WASM_I32 == v->kind); @@ -1834,7 +1834,7 @@ aot_global_get(const AOTModuleInstance *inst_aot, .type; } - data = inst_aot->global_data.ptr + data_offset; + data = (void *)((uint8 *)inst_aot->global_data.ptr + data_offset); switch (val_type_rt) { case VALUE_TYPE_I32: out->kind = WASM_I32; diff --git a/core/iwasm/common/wasm_c_api_internal.h b/core/iwasm/common/wasm_c_api_internal.h index b321ff87..40d049aa 100644 --- a/core/iwasm/common/wasm_c_api_internal.h +++ b/core/iwasm/common/wasm_c_api_internal.h @@ -91,7 +91,9 @@ struct wasm_export_type_t { }; /* Runtime Objects */ -struct wasm_ref_t {}; +struct wasm_ref_t { + uint32 obj; +}; struct wasm_trap_t { wasm_byte_vec_t *message; diff --git a/core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c b/core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c index 88ebc013..4bdf5500 100644 --- a/core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c +++ b/core/iwasm/libraries/libc-builtin/libc_builtin_wrapper.c @@ -8,6 +8,11 @@ #include "wasm_export.h" #include "../interpreter/wasm.h" +#if defined(_WIN32) || defined(_WIN32_) +#define strncasecmp _strnicmp +#define strcasecmp _stricmp +#endif + void wasm_runtime_set_exception(wasm_module_inst_t module, const char *exception); @@ -213,8 +218,17 @@ _vprintf_wa(out_func_t out, void *ctx, const char *fmt, _va_list ap, padding = PAD_ZERO_BEFORE; goto still_might_format; } - /* Fall through */ - case '1' ... '9': + goto handle_1_to_9; + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': +handle_1_to_9: if (min_width < 0) { min_width = *fmt - '0'; } else { diff --git a/core/shared/platform/windows/platform_init.c b/core/shared/platform/windows/platform_init.c new file mode 100644 index 00000000..76594b81 --- /dev/null +++ b/core/shared/platform/windows/platform_init.c @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "platform_api_vmcore.h" + +int +bh_platform_init() +{ + return 0; +} + +void +bh_platform_destroy() +{ +} + diff --git a/core/shared/platform/windows/platform_internal.h b/core/shared/platform/windows/platform_internal.h new file mode 100644 index 00000000..8803e802 --- /dev/null +++ b/core/shared/platform/windows/platform_internal.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _PLATFORM_INTERNAL_H +#define _PLATFORM_INTERNAL_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef BH_PLATFORM_WINDOWS +#define BH_PLATFORM_WINDOWS +#endif + +/* Stack size of applet threads's native part. */ +#define BH_APPLET_PRESERVED_STACK_SIZE (32 * 1024) + +/* Default thread priority */ +#define BH_THREAD_DEFAULT_PRIORITY 0 + +typedef void *korp_tid; +typedef void *korp_mutex; +typedef void *korp_sem; +typedef void *korp_thread; + +typedef struct { + korp_sem s; + unsigned int waiting_count; +} korp_cond; + +#define os_printf printf +#define os_vprintf vprintf + +static inline size_t getpagesize() { + SYSTEM_INFO S; + GetNativeSystemInfo(&S); + return S.dwPageSize; +} + +#ifdef __cplusplus +} +#endif + +#endif /* end of _PLATFORM_INTERNAL_H */ + diff --git a/core/shared/platform/windows/posix_malloc.c b/core/shared/platform/windows/posix_malloc.c new file mode 100644 index 00000000..e83fc7d7 --- /dev/null +++ b/core/shared/platform/windows/posix_malloc.c @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "platform_api_vmcore.h" + +void * +os_malloc(unsigned size) +{ + return malloc(size); +} + +void * +os_realloc(void *ptr, unsigned size) +{ + return realloc(ptr, size); +} + +void +os_free(void *ptr) +{ + free(ptr); +} + + + diff --git a/core/shared/platform/windows/shared_platform.cmake b/core/shared/platform/windows/shared_platform.cmake new file mode 100644 index 00000000..6ab29c89 --- /dev/null +++ b/core/shared/platform/windows/shared_platform.cmake @@ -0,0 +1,18 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +set (PLATFORM_SHARED_DIR ${CMAKE_CURRENT_LIST_DIR}) + +add_definitions(-DBH_PLATFORM_WINDOWS) +add_definitions(-DHAVE_STRUCT_TIMESPEC) + + +include_directories(${PLATFORM_SHARED_DIR}) +include_directories(${PLATFORM_SHARED_DIR}/../include) + +file (GLOB_RECURSE source_all ${PLATFORM_SHARED_DIR}/*.c) + +set (PLATFORM_SHARED_SOURCE ${source_all}) + +file (GLOB header ${PLATFORM_SHARED_DIR}/../include/*.h) +LIST (APPEND RUNTIME_LIB_HEADER_LIST ${header}) diff --git a/core/shared/platform/windows/win_memmap.c b/core/shared/platform/windows/win_memmap.c new file mode 100644 index 00000000..e5d478b1 --- /dev/null +++ b/core/shared/platform/windows/win_memmap.c @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "platform_api_vmcore.h" +void * os_mmap(void *hint, size_t size, int prot, int flags) +{ + DWORD AllocType = MEM_RESERVE | MEM_COMMIT; + DWORD flProtect = PAGE_NOACCESS; + size_t request_size, page_size; + void *addr; + + page_size = getpagesize(); + request_size = (size + page_size - 1) & ~(page_size - 1); + + if (request_size < size) + /* integer overflow */ + return NULL; + + 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, AllocType, + flProtect); + return addr; +} + +void +os_munmap(void *addr, size_t size) +{ + size_t page_size = getpagesize(); + size_t request_size = (size + page_size - 1) & ~(page_size - 1); + if (addr) { + + if (VirtualFree(addr, 0, MEM_RELEASE) == 0) { + if (VirtualFree(addr, size, MEM_DECOMMIT) == 0) { + os_printf("os_munmap error addr:%p, size:0x%lx, errno:%d\n", + addr, request_size, errno); + } + } + } +} + +int +os_mprotect(void *addr, size_t size, int prot) +{ + DWORD AllocType = MEM_RESERVE | MEM_COMMIT; + 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; + + return VirtualProtect((LPVOID)addr, size, flProtect, NULL); +} + +void +os_dcache_flush(void) +{ +} diff --git a/core/shared/platform/windows/win_thread.c b/core/shared/platform/windows/win_thread.c new file mode 100644 index 00000000..d4b9e64a --- /dev/null +++ b/core/shared/platform/windows/win_thread.c @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif +#include "platform_api_vmcore.h" +#include "platform_api_extension.h" + +typedef struct { + thread_start_routine_t start; + void* stack; + uint32 stack_size; + void* arg; +} thread_wrapper_arg; + +static void *os_thread_wrapper(void *arg) +{ + thread_wrapper_arg * targ = arg; + thread_start_routine_t start_func = targ->start; + void *thread_arg = targ->arg; + os_printf("THREAD CREATED %p\n", &targ); + targ->stack = (void *)((uintptr_t)(&arg) & (uintptr_t)~0xfff); + BH_FREE(targ); + start_func(thread_arg); + return NULL; +} + +int os_thread_create_with_prio(korp_tid *tid, thread_start_routine_t start, + void *arg, unsigned int stack_size, int prio) +{ + return BHT_ERROR; +} + +int os_thread_create(korp_tid *tid, thread_start_routine_t start, void *arg, + unsigned int stack_size) +{ + return os_thread_create_with_prio(tid, start, arg, stack_size, + BH_THREAD_DEFAULT_PRIORITY); +} + +korp_tid os_self_thread() +{ + return NULL; +} + +int os_mutex_init(korp_mutex *mutex) +{ + return BHT_OK; +} + +int os_recursive_mutex_init(korp_mutex *mutex) +{ + return BHT_OK; +} + +int os_mutex_destroy(korp_mutex *mutex) +{ + return BHT_OK; +} + +/* Returned error (EINVAL, EAGAIN and EDEADLK) from + locking the mutex indicates some logic error present in + the program somewhere. + Don't try to recover error for an existing unknown error.*/ +int os_mutex_lock(korp_mutex *mutex) +{ + return BHT_ERROR; +} + +/* Returned error (EINVAL, EAGAIN and EPERM) from + unlocking the mutex indicates some logic error present + in the program somewhere. + Don't try to recover error for an existing unknown error.*/ +int os_mutex_unlock(korp_mutex *mutex) +{ + return BHT_OK; +} + +int os_cond_init(korp_cond *cond) +{ + return BHT_OK; +} + +int os_cond_destroy(korp_cond *cond) +{ + return BHT_OK; +} + +int os_cond_wait(korp_cond *cond, korp_mutex *mutex) +{ + return BHT_OK; +} + + +int gettimeofday(struct timeval * tp, struct timezone * tzp) +{ + // Note: some broken versions only have 8 trailing zero's, the correct epoch has 9 trailing zero's + // This magic number is the number of 100 nanosecond intervals since January 1, 1601 (UTC) + // until 00:00:00 January 1, 1970 + static const uint64_t EPOCH = ((uint64_t) 116444736000000000ULL); + + SYSTEMTIME system_time; + FILETIME file_time; + uint64_t time; + + GetSystemTime( &system_time ); + SystemTimeToFileTime( &system_time, &file_time ); + time = ((uint64_t)file_time.dwLowDateTime ) ; + time += ((uint64_t)file_time.dwHighDateTime) << 32; + + tp->tv_sec = (long) ((time - EPOCH) / 10000000L); + tp->tv_usec = (long) (system_time.wMilliseconds * 1000); + return 0; +} + +static void msec_nsec_to_abstime(struct timespec *ts, int usec) +{ + struct timeval tv; + + gettimeofday(&tv, NULL); + + ts->tv_sec = (long int)(tv.tv_sec + usec / 1000000); + ts->tv_nsec = (long int)(tv.tv_usec * 1000 + (usec % 1000000) * 1000); + + if (ts->tv_nsec >= 1000000000L) { + ts->tv_sec++; + ts->tv_nsec -= 1000000000L; + } +} + +int os_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, int useconds) +{ + return BHT_OK; +} + +int os_cond_signal(korp_cond *cond) +{ + return BHT_OK; +} + +int os_thread_join(korp_tid thread, void **value_ptr) +{ + return BHT_OK; +} + +int os_thread_detach(korp_tid thread) +{ + return BHT_OK; +} + +void os_thread_exit(void *retval) +{ + return BHT_OK; +} + +uint8 *os_thread_get_stack_boundary() +{ + return NULL; +} diff --git a/core/shared/platform/windows/win_time.c b/core/shared/platform/windows/win_time.c new file mode 100644 index 00000000..3028a2ef --- /dev/null +++ b/core/shared/platform/windows/win_time.c @@ -0,0 +1,16 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "platform_api_vmcore.h" + +uint64 +os_time_get_boot_microsecond() +{ + struct timespec ts; + timespec_get(&ts, TIME_UTC); + + return ((uint64) ts.tv_sec) * 1000 * 1000 + ((uint64)ts.tv_nsec) / 1000; +} + diff --git a/core/shared/utils/uncommon/bh_read_file.c b/core/shared/utils/uncommon/bh_read_file.c index f93b28d0..08165c53 100644 --- a/core/shared/utils/uncommon/bh_read_file.c +++ b/core/shared/utils/uncommon/bh_read_file.c @@ -2,8 +2,59 @@ #include #include +#if defined(_WIN32) || defined(_WIN32_) +#include +#else #include +#endif +#if defined(_WIN32) || defined(_WIN32_) +char* +bh_read_file_to_buffer(const char *filename, uint32 *ret_size) +{ + char *buffer; + int file; + uint32 file_size, read_size; + struct stat stat_buf; + + if (!filename || !ret_size) { + printf("Read file to buffer failed: invalid filename or ret size.\n"); + return NULL; + } + + if (_sopen_s(&file, filename, _O_RDONLY| _O_BINARY, _SH_DENYNO, 0)) { + printf("Read file to buffer failed: open file %s failed.\n", + filename); + return NULL; + } + + if (fstat(file, &stat_buf) != 0) { + printf("Read file to buffer failed: fstat file %s failed.\n", + filename); + _close(file); + return NULL; + } + file_size = (uint32)stat_buf.st_size; + + if (!(buffer = (char *)BH_MALLOC(file_size))) { + printf("Read file to buffer failed: alloc memory failed.\n"); + _close(file); + return NULL; + } + + read_size = _read(file, buffer, file_size); + _close(file); + + if (read_size < file_size) { + printf("Read file to buffer failed: read file content failed.\n"); + BH_FREE(buffer); + return NULL; + } + + *ret_size = file_size; + return buffer; +} +#else /* else of defined(_WIN32) || defined(_WIN32_) */ char* bh_read_file_to_buffer(const char *filename, uint32 *ret_size) { @@ -50,4 +101,4 @@ bh_read_file_to_buffer(const char *filename, uint32 *ret_size) *ret_size = file_size; return buffer; } - +#endif /* end of defined(_WIN32) || defined(_WIN32_) */ diff --git a/product-mini/platforms/windows/CMakeLists.txt b/product-mini/platforms/windows/CMakeLists.txt new file mode 100644 index 00000000..3bc67d4c --- /dev/null +++ b/product-mini/platforms/windows/CMakeLists.txt @@ -0,0 +1,121 @@ +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +cmake_minimum_required (VERSION 2.8) + +project (iwasm C ASM) +enable_language(ASM_MASM) +# set (CMAKE_VERBOSE_MAKEFILE 1) + +set (WAMR_BUILD_PLATFORM "windows") + +# Reset default linker flags +set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") +set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") + +set (CMAKE_C_STANDARD 99) + +# Set WAMR_BUILD_TARGET, currently values supported: +# "X86_64", "AMD_64", "X86_32", "AARCH64[sub]", "ARM[sub]", "THUMB[sub]", "MIPS", "XTENSA" +if (NOT DEFINED WAMR_BUILD_TARGET) + if (CMAKE_SIZEOF_VOID_P EQUAL 8) + # Build as X86_64 by default in 64-bit platform + set (WAMR_BUILD_TARGET "X86_64") + else () + # Build as X86_32 by default in 32-bit platform + set (WAMR_BUILD_TARGET "X86_32") + endif () +endif () + +if (NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Release) +endif () + +if (NOT DEFINED WAMR_BUILD_INTERP) + # Enable Interpreter by default + set (WAMR_BUILD_INTERP 1) +endif () + +if (NOT DEFINED WAMR_BUILD_AOT) + # Enable AOT by default. + set (WAMR_BUILD_AOT 1) +endif () + +if (NOT DEFINED WAMR_BUILD_JIT) + # Disable JIT by default. + set (WAMR_BUILD_JIT 0) +endif () + +if (NOT DEFINED WAMR_BUILD_LIBC_BUILTIN) + # Enable libc builtin support by default + set (WAMR_BUILD_LIBC_BUILTIN 1) +endif () + +if (NOT DEFINED WAMR_BUILD_LIBC_WASI) + # Enable libc wasi support by default + set (WAMR_BUILD_LIBC_WASI 0) +endif () + +if (NOT DEFINED WAMR_BUILD_FAST_INTERP) + # Enable fast interpreter + set (WAMR_BUILD_FAST_INTERP 0) +endif () + +if (NOT DEFINED WAMR_BUILD_MULTI_MODULE) + # Enable multiple modules + set (WAMR_BUILD_MULTI_MODULE 0) +endif () + +if (NOT DEFINED WAMR_BUILD_LIB_PTHREAD) + # Disable pthread library by default + set (WAMR_BUILD_LIB_PTHREAD 0) +endif () + +if (NOT DEFINED WAMR_BUILD_MINI_LOADER) + # Disable wasm mini loader by default + set (WAMR_BUILD_MINI_LOADER 0) +endif () + +if (COLLECT_CODE_COVERAGE EQUAL 1) + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage") +endif () + +set (WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../..) + +include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake) +add_library(vmlib ${WAMR_RUNTIME_LIB_SOURCE}) + +set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SAFESEH:NO") + +# set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wformat -Wformat-security") +# set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wconversion -Wsign-conversion") + +if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") + if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang" OR MSVC)) + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mindirect-branch-register") + endif () +endif () + +# The following flags are to enhance security, but it may impact performance, +# we disable them by default. +#if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") +# set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ftrapv -D_FORTIFY_SOURCE=2") +#endif () +#set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector-strong --param ssp-buffer-size=4") +#set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,-z,noexecstack,-z,relro,-z,now") + +include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake) + +add_executable (iwasm main.c ${UNCOMMON_SHARED_SOURCE}) + +install (TARGETS iwasm DESTINATION bin) + +target_link_libraries (iwasm vmlib ${LLVM_AVAILABLE_LIBS}) + +add_library (libiwasm SHARED ${WAMR_RUNTIME_LIB_SOURCE}) + +install (TARGETS libiwasm DESTINATION lib) + +set_target_properties (libiwasm PROPERTIES OUTPUT_NAME iwasm) + +target_link_libraries (libiwasm ${LLVM_AVAILABLE_LIBS}) diff --git a/product-mini/platforms/windows/main.c b/product-mini/platforms/windows/main.c new file mode 100644 index 00000000..bed5ee4d --- /dev/null +++ b/product-mini/platforms/windows/main.c @@ -0,0 +1,402 @@ +/* + * Copyright (C) 2019 Intel Corporation. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include +#include + +#include "bh_platform.h" +#include "bh_read_file.h" +#include "wasm_export.h" + +static int app_argc; +static char **app_argv; + +#define MODULE_PATH ("--module-path=") + +static int +print_help() +{ + printf("Usage: iwasm [-options] wasm_file [args...]\n"); + printf("options:\n"); + printf(" -f|--function name Specify a function name of the module to run rather\n" + " than main\n"); +#if WASM_ENABLE_LOG != 0 + printf(" -v=n Set log verbose level (0 to 5, default is 2) larger\n" + " level with more log\n"); +#endif + printf(" --stack-size=n Set maximum stack size in bytes, default is 16 KB\n"); + printf(" --heap-size=n Set maximum heap size in bytes, default is 16 KB\n"); + printf(" --repl Start a very simple REPL (read-eval-print-loop) mode\n" + " that runs commands in the form of `FUNC ARG...`\n"); +#if WASM_ENABLE_LIBC_WASI != 0 + printf(" --env= Pass wasi environment variables with \"key=value\"\n"); + printf(" to the program, for example:\n"); + printf(" --env=\"key1=value1\" --env=\"key2=value2\"\n"); + printf(" --dir= Grant wasi access to the given host directories\n"); + printf(" to the program, for example:\n"); + printf(" --dir= --dir=\n"); +#endif +#if WASM_ENABLE_MULTI_MODULE != 0 + printf(" --module-path= Indicate a module search path. default is current\n" + " directory('./')\n"); +#endif +#if WASM_ENABLE_LIB_PTHREAD != 0 + printf(" --max-threads=n Set maximum thread number per cluster, default is 4\n"); +#endif + return 1; +} + +static void * +app_instance_main(wasm_module_inst_t module_inst) +{ + const char *exception; + + wasm_application_execute_main(module_inst, app_argc, app_argv); + if ((exception = wasm_runtime_get_exception(module_inst))) + printf("%s\n", exception); + return NULL; +} + +static void * +app_instance_func(wasm_module_inst_t module_inst, const char *func_name) +{ + wasm_application_execute_func(module_inst, func_name, app_argc - 1, + app_argv + 1); + /* The result of wasm function or exception info was output inside + wasm_application_execute_func(), here we don't output them again. */ + return NULL; +} + +/** + * Split a space separated strings into an array of strings + * Returns NULL on failure + * Memory must be freed by caller + * Based on: http://stackoverflow.com/a/11198630/471795 + */ +static char ** +split_string(char *str, int *count) +{ + char **res = NULL; + char *p; + int idx = 0; + + /* split string and append tokens to 'res' */ + do { + p = strtok(str, " "); + str = NULL; + res = (char **)realloc(res, sizeof(char *) * (uint32)(idx + 1)); + if (res == NULL) { + return NULL; + } + res[idx++] = p; + } while (p); + + /** + * since the function name, + * res[0] might be contains a '\' to indicate a space + * func\name -> func name + */ + p = strchr(res[0], '\\'); + while (p) { + *p = ' '; + p = strchr(p, '\\'); + } + + if (count) { + *count = idx - 1; + } + return res; +} + +static void * +app_instance_repl(wasm_module_inst_t module_inst) +{ + char buffer[4096]; + char *cmd; + size_t n; + + while ((printf("webassembly> "), + cmd = fgets(buffer, sizeof(buffer), stdin)) != -1) { + bh_assert(cmd); + n = strlen(cmd); + if (cmd[n - 1] == '\n') { + if (n == 1) + continue; + else + cmd[n - 1] = '\0'; + } + if (!strcmp(cmd, "__exit__")) { + printf("exit repl mode\n"); + break; + } + app_argv = split_string(cmd, &app_argc); + if (app_argv == NULL) { + LOG_ERROR("Wasm prepare param failed: split string failed.\n"); + break; + } + if (app_argc != 0) { + wasm_application_execute_func(module_inst, app_argv[0], + app_argc - 1, app_argv + 1); + } + free(app_argv); + } + + return NULL; +} + +#if WASM_ENABLE_LIBC_WASI != 0 +static bool +validate_env_str(char *env) +{ + char *p = env; + int key_len = 0; + + while (*p != '\0' && *p != '=') { + key_len++; + p++; + } + + if (*p != '=' || key_len == 0) + return false; + + return true; +} +#endif + +#define USE_GLOBAL_HEAP_BUF 0 + +#if USE_GLOBAL_HEAP_BUF != 0 +static char global_heap_buf[10 * 1024 * 1024] = { 0 }; +#endif + +#if WASM_ENABLE_MULTI_MODULE != 0 +static char * +handle_module_path(const char *module_path) +{ + // next character after = + return (strchr(module_path, '=')) + 1; +} + +static char *module_search_path = "."; +static bool +module_reader_callback(const char *module_name, uint8 **p_buffer, + uint32 *p_size) +{ + const char *format = "%s/%s.wasm"; + int sz = strlen(module_search_path) + strlen("/") + strlen(module_name) + + strlen(".wasm") + 1; + char *wasm_file_name = BH_MALLOC(sz); + if (!wasm_file_name) { + return false; + } + + snprintf(wasm_file_name, sz, format, module_search_path, module_name); + + *p_buffer = (uint8_t *)bh_read_file_to_buffer(wasm_file_name, p_size); + + wasm_runtime_free(wasm_file_name); + return *p_buffer != NULL; +} + +static void +moudle_destroyer(uint8 *buffer, uint32 size) +{ + if (!buffer) { + return; + } + + wasm_runtime_free(buffer); + buffer = NULL; +} +#endif /* WASM_ENABLE_MULTI_MODULE */ + +int +main(int argc, char *argv[]) +{ + char *wasm_file = NULL; + const char *func_name = NULL; + uint8 *wasm_file_buf = NULL; + uint32 wasm_file_size; + uint32 stack_size = 16 * 1024, heap_size = 16 * 1024; + wasm_module_t wasm_module = NULL; + wasm_module_inst_t wasm_module_inst = NULL; + RuntimeInitArgs init_args; + char error_buf[128] = { 0 }; +#if WASM_ENABLE_LOG != 0 + int log_verbose_level = 2; +#endif + bool is_repl_mode = false; +#if WASM_ENABLE_LIBC_WASI != 0 + const char *dir_list[8] = { NULL }; + uint32 dir_list_size = 0; + const char *env_list[8] = { NULL }; + uint32 env_list_size = 0; +#endif + + /* Process options. */ + // TODO: use a option name and option handler pair table to + // optimize + for (argc--, argv++; argc > 0 && argv[0][0] == '-'; argc--, argv++) { + if (!strcmp(argv[0], "-f") || !strcmp(argv[0], "--function")) { + argc--, argv++; + if (argc < 2) { + print_help(); + return 0; + } + func_name = argv[0]; + } +#if WASM_ENABLE_LOG != 0 + else if (!strncmp(argv[0], "-v=", 3)) { + log_verbose_level = atoi(argv[0] + 3); + if (log_verbose_level < 0 || log_verbose_level > 5) + return print_help(); + } +#endif + else if (!strcmp(argv[0], "--repl")) { + is_repl_mode = true; + } + else if (!strncmp(argv[0], "--stack-size=", 13)) { + if (argv[0][13] == '\0') + return print_help(); + stack_size = atoi(argv[0] + 13); + } + else if (!strncmp(argv[0], "--heap-size=", 12)) { + if (argv[0][12] == '\0') + return print_help(); + heap_size = atoi(argv[0] + 12); + } +#if WASM_ENABLE_LIBC_WASI != 0 + else if (!strncmp(argv[0], "--dir=", 6)) { + if (argv[0][6] == '\0') + return print_help(); + if (dir_list_size >= sizeof(dir_list) / sizeof(char *)) { + printf("Only allow max dir number %d\n", + (int)(sizeof(dir_list) / sizeof(char *))); + return -1; + } + dir_list[dir_list_size++] = argv[0] + 6; + } + else if (!strncmp(argv[0], "--env=", 6)) { + char *tmp_env; + + if (argv[0][6] == '\0') + return print_help(); + if (env_list_size >= sizeof(env_list) / sizeof(char *)) { + printf("Only allow max env number %d\n", + (int)(sizeof(env_list) / sizeof(char *))); + return -1; + } + tmp_env = argv[0] + 6; + if (validate_env_str(tmp_env)) + env_list[env_list_size++] = tmp_env; + else { + printf("Wasm parse env string failed: expect \"key=value\", " + "got \"%s\"\n", + tmp_env); + return print_help(); + } + } +#endif /* WASM_ENABLE_LIBC_WASI */ +#if WASM_ENABLE_MULTI_MODULE != 0 + else if (!strncmp(argv[0], MODULE_PATH, strlen(MODULE_PATH))) { + module_search_path = handle_module_path(argv[0]); + if (!strlen(module_search_path)) { + return print_help(); + } + } +#endif +#if WASM_ENABLE_LIB_PTHREAD != 0 + else if (!strncmp(argv[0], "--max-threads=", 14)) { + if (argv[0][14] == '\0') + return print_help(); + wasm_runtime_set_max_thread_num(atoi(argv[0] + 14)); + } +#endif + else + return print_help(); + } + + if (argc == 0) + return print_help(); + + wasm_file = argv[0]; + app_argc = argc; + app_argv = argv; + + memset(&init_args, 0, sizeof(RuntimeInitArgs)); + +#if USE_GLOBAL_HEAP_BUF != 0 + init_args.mem_alloc_type = Alloc_With_Pool; + init_args.mem_alloc_option.pool.heap_buf = global_heap_buf; + init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf); +#else + init_args.mem_alloc_type = Alloc_With_Allocator; + init_args.mem_alloc_option.allocator.malloc_func = malloc; + init_args.mem_alloc_option.allocator.realloc_func = realloc; + init_args.mem_alloc_option.allocator.free_func = free; +#endif + + /* initialize runtime environment */ + if (!wasm_runtime_full_init(&init_args)) { + printf("Init runtime environment failed.\n"); + return -1; + } + +#if WASM_ENABLE_LOG != 0 + bh_log_set_verbose_level(log_verbose_level); +#endif + + /* load WASM byte buffer from WASM bin file */ + if (!(wasm_file_buf = + (uint8 *)bh_read_file_to_buffer(wasm_file, &wasm_file_size))) + goto fail1; + +#if WASM_ENABLE_MULTI_MODULE != 0 + wasm_runtime_set_module_reader(module_reader_callback, moudle_destroyer); +#endif + + /* load WASM module */ + if (!(wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, + error_buf, sizeof(error_buf)))) { + printf("%s\n", error_buf); + goto fail2; + } + +#if WASM_ENABLE_LIBC_WASI != 0 + wasm_runtime_set_wasi_args(wasm_module, dir_list, dir_list_size, NULL, 0, + env_list, env_list_size, argv, argc); +#endif + + /* instantiate the module */ + if (!(wasm_module_inst = + wasm_runtime_instantiate(wasm_module, stack_size, heap_size, + error_buf, sizeof(error_buf)))) { + printf("%s\n", error_buf); + goto fail3; + } + + if (is_repl_mode) + app_instance_repl(wasm_module_inst); + else if (func_name) + app_instance_func(wasm_module_inst, func_name); + else + app_instance_main(wasm_module_inst); + + /* destroy the module instance */ + wasm_runtime_deinstantiate(wasm_module_inst); + +fail3: + /* unload the module */ + wasm_runtime_unload(wasm_module); + +fail2: + /* free the file buffer */ + wasm_runtime_free(wasm_file_buf); + +fail1: + /* destroy runtime environment */ + wasm_runtime_destroy(); + return 0; +} diff --git a/wamr-compiler/CMakeLists.txt b/wamr-compiler/CMakeLists.txt index d27de87c..7efe1c0e 100644 --- a/wamr-compiler/CMakeLists.txt +++ b/wamr-compiler/CMakeLists.txt @@ -1,8 +1,14 @@ # Copyright (C) 2019 Intel Corporation. All rights reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + cmake_minimum_required (VERSION 2.8) -project (aot-compiler) +if (NOT WAMR_BUILD_PLATFORM STREQUAL "windows") + project (aot-compiler) +else() + project (aot-compiler C ASM) + enable_language (ASM_MASM) +endif() if (NOT DEFINED WAMR_BUILD_PLATFORM) set (WAMR_BUILD_PLATFORM "linux") @@ -29,6 +35,11 @@ if (NOT WAMR_BUILD_TARGET) # Build as X86_32 by default in 32-bit platform set (WAMR_BUILD_TARGET "X86_32") endif () + if (WAMR_BUILD_PLATFORM STREQUAL "windows") + if (("${CMAKE_GENERATOR_PLATFORM}" STREQUAL "Win32")) + set (WAMR_BUILD_TARGET "X86_32") + endif() + endif() endif () string(TOUPPER ${WAMR_BUILD_TARGET} WAMR_BUILD_TARGET) @@ -71,10 +82,18 @@ message ("-- CMAKE_BUILD_TYPE = " ${CMAKE_BUILD_TYPE}) # Enable LLVM set (LLVM_SRC_ROOT "${PROJECT_SOURCE_DIR}/../core/deps/llvm") -if (NOT EXISTS "${LLVM_SRC_ROOT}/build") - message (FATAL_ERROR "Cannot find LLVM dir: ${LLVM_SRC_ROOT}/build") +if (WAMR_BUILD_PLATFORM STREQUAL "windows") + if (NOT EXISTS "${LLVM_SRC_ROOT}/win32build") + message (FATAL_ERROR "Cannot find LLVM dir: ${LLVM_SRC_ROOT}/win32build") + endif () + set (CMAKE_PREFIX_PATH "${LLVM_SRC_ROOT}/win32build;${CMAKE_PREFIX_PATH}") +else() + if (NOT EXISTS "${LLVM_SRC_ROOT}/build") + message (FATAL_ERROR "Cannot find LLVM dir: ${LLVM_SRC_ROOT}/build") + endif () + set (CMAKE_PREFIX_PATH "${LLVM_SRC_ROOT}/build;${CMAKE_PREFIX_PATH}") endif () -set (CMAKE_PREFIX_PATH "${LLVM_SRC_ROOT}/build;${CMAKE_PREFIX_PATH}") + find_package(LLVM REQUIRED CONFIG) include_directories(${LLVM_INCLUDE_DIRS}) add_definitions(${LLVM_DEFINITIONS}) @@ -83,10 +102,17 @@ message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}") message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}") if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang")) - set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") + if(NOT MSVC) + set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections") + else() + set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SAFESEH:NO") + endif() +endif() + +if (NOT MSVC) + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffunction-sections -fdata-sections \ + -Wall -Wno-unused-parameter -Wno-pedantic") endif() -set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffunction-sections -fdata-sections \ - -Wall -Wno-unused-parameter -Wno-pedantic") set (SHARED_DIR ../core/shared) set (IWASM_DIR ../core/iwasm) @@ -108,20 +134,28 @@ include (${IWASM_DIR}/interpreter/iwasm_interp.cmake) include (${IWASM_DIR}/aot/iwasm_aot.cmake) include (${IWASM_DIR}/compilation/iwasm_compl.cmake) -set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wformat -Wformat-security") +if (NOT MSVC) + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wformat -Wformat-security") +endif() + # set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wconversion -Wsign-conversion") if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64") - if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang")) + if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang" OR MSVC)) set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mindirect-branch-register") endif() endif () -set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector-strong --param ssp-buffer-size=4") -set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,-z,noexecstack,-z,relro,-z,now") + +if (NOT MSVC) + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector-strong --param ssp-buffer-size=4") + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,-z,noexecstack,-z,relro,-z,now") +endif() # We disable these flags by default to stay the same with wasm runtime # set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mindirect-branch=thunk -mfunction-return=thunk") -set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pie -fPIE -ftrapv -D_FORTIFY_SOURCE=2") +if (NOT MSVC) + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pie -fPIE -ftrapv -D_FORTIFY_SOURCE=2") +endif() # message ("-- CMAKE_C_FLAGS: ${CMAKE_C_FLAGS}") @@ -140,5 +174,8 @@ add_library (aotclib ${IWASM_COMPL_SOURCE}) add_executable (wamrc main.c) -target_link_libraries (wamrc aotclib vmlib ${LLVM_AVAILABLE_LIBS} -lm -ldl -lpthread) - +if (NOT MSVC) + target_link_libraries (wamrc aotclib vmlib LLVMDemangle ${LLVM_AVAILABLE_LIBS} -lm -ldl -lpthread) +else() + target_link_libraries (wamrc aotclib vmlib ${LLVM_AVAILABLE_LIBS}) +endif() diff --git a/wamr-compiler/build_llvm.py b/wamr-compiler/build_llvm.py new file mode 100644 index 00000000..ba965a35 --- /dev/null +++ b/wamr-compiler/build_llvm.py @@ -0,0 +1,98 @@ +# +# Copyright (C) 2019 Intel Corporation. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# + +#!/usr/bin/env python3 +import os +import sys +from pathlib import Path + +def clone_llvm(): + llvm_dir = Path("llvm") + if(llvm_dir.exists() == False): + print("Clone llvm to core/deps/ ..") + for line in os.popen("git clone --branch release/10.x https://github.com/llvm/llvm-project.git llvm"): + print(line) + else: + print("llvm source codes already existed") + return llvm_dir + +""" def detect_VS_version(): + program_dirs = [os.environ['ProgramFiles(x86)'], os.environ['ProgramFiles']] + for dir in program_dirs: + vswhere = Path("{}\\Microsoft Visual Studio\\Installer\\vswhere.exe".format(dir)) + if (vswhere.exists()): + print('"{}" -version 14.0,16.0'.format(vswhere)) + for line in os.popen('"{}" -version 14.0,16.0'.format(vswhere)): + keyvalue = line.split(':', maxsplit=1) + if(keyvalue[0] == "installationPath"): + value = keyvalue[1].strip() + for line in os.popen('"{}\\VC\\Auxiliary\\Build\\vcvars32.bat"'.format(value)): + print(line) + break """ + + +def main(): + current_os = sys.platform + print("current OS is ", current_os) + + current_dir = Path.cwd() + deps_dir = current_dir.joinpath( "../core/deps") + + os.chdir(deps_dir) + llvm_dir = clone_llvm() + os.chdir(llvm_dir) + + if(current_os == "linux"): + build_dir_name = "build" + llvm_file = "bin/llvm-lto" + # generator = '"Unix Makefiles"' + elif(current_os == "win32"): + build_dir_name = "win32build" + llvm_file = "LLVM.sln" + # generator = '"Visual Studio 15 2017"' + else: + build_dir_name = "build" + # generator = '""' + + Path(build_dir_name).mkdir(exist_ok = True) + build_dir = Path(build_dir_name) + os.chdir(build_dir) + + if ( not Path(llvm_file).exists()): + core_number = os.cpu_count() + print("Build llvm with", core_number, " cores") + cmd = 'cmake ../llvm \ + -DCMAKE_EXPORT_COMPILE_COMMANDS=ON \ + -DCMAKE_BUILD_TYPE:STRING="Release" \ + -DLLVM_TARGETS_TO_BUILD:STRING="X86;ARM;AArch64;Mips" \ + -DLLVM_INCLUDE_GO_TESTS=OFF \ + -DLLVM_INCLUDE_TOOLS=OFF \ + -DLLVM_INCLUDE_UTILS=OFF \ + -DLLVM_ENABLE_TERMINFO=OFF \ + -DLLVM_BUILD_LLVM_DYLIB:BOOL=OFF \ + -DLLVM_OPTIMIZED_TABLEGEN:BOOL=ON \ + -DLLVM_ENABLE_ZLIB:BOOL=OFF \ + -DLLVM_INCLUDE_DOCS:BOOL=OFF \ + -DLLVM_INCLUDE_EXAMPLES:BOOL=OFF \ + -DLLVM_INCLUDE_TESTS:BOOL=OFF \ + -DLLVM_INCLUDE_BENCHMARKS:BOOL=OFF \ + -DLLVM_APPEND_VC_REV:BOOL=OFF' + print(cmd) + for line in os.popen(cmd): + print(line) + else: + print("llvm has already been Cmaked") + + if(current_os == "linux"): + for line in os.popen("make -j {}".format(core_number)): + print(line) + elif(current_os == "win32"): + print("Please open LLVM.sln in {} to build *Release* version".format(build_dir.absolute())) + + os.chdir(current_dir) + + +if __name__ == "__main__": + main()