Sfoglia il codice sorgente

Add wamrc AoT compiler building support for Windows(MSVC) (#332)

sophy228 5 anni fa
parent
commit
8ad9c1775f

+ 3 - 1
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
 ===================================
 

+ 2 - 0
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)

+ 4 - 0
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

+ 11 - 0
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,   \

+ 1 - 1
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,

+ 2 - 0
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

+ 27 - 0
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

+ 5 - 1
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)

+ 2 - 2
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;

+ 3 - 1
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;

+ 16 - 2
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 {

+ 18 - 0
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()
+{
+}
+

+ 66 - 0
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 <inttypes.h>
+#include <stdbool.h>
+#include <assert.h>
+#include <time.h>
+#include <sys/timeb.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include <stdarg.h>
+#include <ctype.h>
+#include <limits.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdint.h>
+#include <Windows.h>
+
+#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 */
+

+ 27 - 0
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);
+}
+
+
+

+ 18 - 0
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})

+ 79 - 0
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)
+{
+}

+ 162 - 0
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;
+}

+ 16 - 0
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;
+}
+

+ 52 - 1
core/shared/utils/uncommon/bh_read_file.c

@@ -2,8 +2,59 @@
 
 #include <sys/stat.h>
 #include <fcntl.h>
+#if defined(_WIN32) || defined(_WIN32_)
+#include <io.h>
+#else
 #include <unistd.h>
+#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_) */

+ 121 - 0
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})

+ 402 - 0
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 <stdlib.h>
+#include <string.h>
+
+#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=<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=<dir>            Grant wasi access to the given host directories\n");
+    printf("                         to the program, for example:\n");
+    printf("                           --dir=<dir1> --dir=<dir2>\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;
+}

+ 51 - 14
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()

+ 98 - 0
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()