Commit 7c81cd30de

Jonathan Marler <johnnymarler@gmail.com>
2017-09-10 22:05:18
Add support for MSVC
1 parent 373785a
cmake/Findclang.cmake
@@ -8,14 +8,20 @@
 
 find_path(CLANG_INCLUDE_DIRS NAMES clang/Frontend/ASTUnit.h
     PATHS
+        ${LLVM_INSTALL_PREFIX}/include
         /usr/lib/llvm/5/include
         /usr/lib/llvm-5.0/include
         /mingw64/include)
 
-    macro(FIND_AND_ADD_CLANG_LIB _libname_)
+if(NOT CLANG_INCLUDE_DIRS)
+    message(FATAL_ERROR "Failed to find CLANG header files")
+endif()
+
+macro(FIND_AND_ADD_CLANG_LIB _libname_)
     string(TOUPPER ${_libname_} _prettylibname_)
     find_library(CLANG_${_prettylibname_}_LIB NAMES ${_libname_}
         PATHS
+            ${LLVM_INSTALL_PREFIX}/lib
             /usr/lib/llvm/5/lib
             /usr/lib/llvm-5.0/lib
             /mingw64/lib
cmake/Findllvm.cmake
@@ -2,28 +2,53 @@
 # This file is MIT licensed.
 # See http://opensource.org/licenses/MIT
 
-# LLVM_FOUND
 # LLVM_INCLUDE_DIR
 # LLVM_LIBRARIES
 # LLVM_LIBDIRS
 
-find_program(LLVM_CONFIG_EXE
-    NAMES llvm-config-5.0 llvm-config
-    PATHS
-        "/mingw64/bin"
-        "/c/msys64/mingw64/bin"
-        "c:/msys64/mingw64/bin"
-        "C:/Libraries/llvm-5.0.0/bin")
+if(LLVM_INSTALL_PREFIX)
+    find_program(LLVM_CONFIG_EXE
+        NAMES llvm-config-5.0 llvm-config
+        PATHS ${LLVM_INSTALL_PREFIX}/bin
+        NO_DEFAULT_PATH)
+    if(NOT LLVM_CONFIG_EXE)
+        message(FATAL_ERROR "Invalid LLVM_INSTALL_PREFIX \"${LLVM_INSTALL_PREFIX}\", could not find llvm-config")
+    endif()
+else()
+    find_program(LLVM_CONFIG_EXE
+        NAMES llvm-config-5.0 llvm-config
+        PATHS
+            "/mingw64/bin"
+            "/c/msys64/mingw64/bin"
+            "c:/msys64/mingw64/bin"
+            "C:/Libraries/llvm-5.0.0/bin")
+    if(NOT LLVM_CONFIG_EXE)
+        message(FATAL_ERROR "Could not find llvm-config, use -DLLVM_INSTALL_PREFIX to specify the install path")
+    endif()
+    execute_process(
+        COMMAND ${LLVM_CONFIG_EXE} --prefix
+        OUTPUT_VARIABLE LLVM_INSTALL_PREFIX
+        OUTPUT_STRIP_TRAILING_WHITESPACE)
+endif()
+
+if(${LLVM_INSTALL_PREFIX} MATCHES "^.* ")
+    # NOTE: this is a limitation due to llvm-config.  If the path contains spaces then there's
+    # no way to tell from the output of llvm-config whether a space is seperating a filename, or
+    # just a space in the path name.
+    message(FATAL_ERROR "The LLVM install path \"${LLVM_INSTALL_PREFIX}\" cannot contain spaces")
+endif()
 
 execute_process(
     COMMAND ${LLVM_CONFIG_EXE} --libs
-    OUTPUT_VARIABLE LLVM_LIBRARIES
+    OUTPUT_VARIABLE LLVM_LIBRARIES_STRING
     OUTPUT_STRIP_TRAILING_WHITESPACE)
+string(REPLACE " " ";" LLVM_LIBRARIES ${LLVM_LIBRARIES_STRING})
 
 execute_process(
     COMMAND ${LLVM_CONFIG_EXE} --system-libs
-    OUTPUT_VARIABLE LLVM_SYSTEM_LIBS
+    OUTPUT_VARIABLE LLVM_SYSTEM_LIBS_STRING
     OUTPUT_STRIP_TRAILING_WHITESPACE)
+string(REPLACE " " ";" LLVM_SYSTEM_LIBS ${LLVM_SYSTEM_LIBS_STRING})
 
 execute_process(
     COMMAND ${LLVM_CONFIG_EXE} --libdir
src/analyze.cpp
@@ -163,7 +163,7 @@ static TypeTableEntry *new_container_type_entry(TypeTableEntryId id, AstNode *so
 }
 
 static uint8_t log2_u64(uint64_t x) {
-    return (63 - __builtin_clzll(x));
+    return (63 - clzll(x));
 }
 
 static uint8_t bits_needed_for_unsigned(uint64_t x) {
src/bigfloat.hpp
@@ -13,6 +13,14 @@
 #include <stdint.h>
 #include <stddef.h>
 
+#if defined(_MSVC)
+/*
+ * For now this is a placeholder until a better solution comes along to
+ * support 128-bit floats with MSVC.
+ */
+typedef long double __float128;
+#endif
+
 struct BigFloat {
     __float128 value;
 };
src/bigint.cpp
@@ -141,7 +141,7 @@ void bigint_init_unsigned(BigInt *dest, uint64_t x) {
     dest->is_negative = false;
 }
 
-void bigint_init_u128(BigInt *dest, unsigned __int128 x) {
+void bigint_init_u128(BigInt *dest, uint128_t x) {
     uint64_t low = (uint64_t)(x & UINT64_MAX);
     uint64_t high = (uint64_t)(x >> 64);
 
@@ -201,9 +201,9 @@ void bigint_init_bigint(BigInt *dest, const BigInt *src) {
 
 void bigint_init_bigfloat(BigInt *dest, const BigFloat *op) {
     if (op->value >= 0) {
-        bigint_init_u128(dest, (unsigned __int128)(op->value));
+        bigint_init_u128(dest, (uint128_t)(op->value));
     } else {
-        bigint_init_u128(dest, (unsigned __int128)(-op->value));
+        bigint_init_u128(dest, (uint128_t)(-op->value));
         dest->is_negative = true;
     }
 }
@@ -377,6 +377,41 @@ void bigint_read_twos_complement(BigInt *dest, const uint8_t *buf, size_t bit_co
     }
 }
 
+#if defined(_MSVC)
+/*
+ * Inneficient implmentations for now
+ */
+static bool add_u64_overflow(uint64_t op1, uint64_t op2, uint64_t *result) {
+   *result = op1 + op2;
+   if(*result - op2 != op1) {
+       return true; // overflow
+   }
+   return false; // no overflow
+}
+
+static bool sub_u64_overflow(uint64_t op1, uint64_t op2, uint64_t *result) {
+   *result = op1 - op2;
+    if(*result > op1)
+    {
+        return true; // overflow
+    }
+    return false; // no overflow
+}
+
+bool mul_u64_overflow(uint64_t op1, uint64_t op2, uint64_t *result) {
+    *result = op1 * op2;
+    if(op1 <= op2) {
+        if(*result / op1 != op2) {
+            return true; // overflow
+        }
+    } else {
+        if(*result / op2 != op1) {
+            return true; // overflow
+        }
+    }
+    return false; // no overflow
+}
+#else
 static bool add_u64_overflow(uint64_t op1, uint64_t op2, uint64_t *result) {
     return __builtin_uaddll_overflow((unsigned long long)op1, (unsigned long long)op2,
             (unsigned long long *)result);
@@ -387,10 +422,11 @@ static bool sub_u64_overflow(uint64_t op1, uint64_t op2, uint64_t *result) {
             (unsigned long long *)result);
 }
 
-static bool mul_u64_overflow(uint64_t op1, uint64_t op2, uint64_t *result) {
+bool mul_u64_overflow(uint64_t op1, uint64_t op2, uint64_t *result) {
     return __builtin_umulll_overflow((unsigned long long)op1, (unsigned long long)op2,
             (unsigned long long *)result);
 }
+#endif
 
 void bigint_add(BigInt *dest, const BigInt *op1, const BigInt *op2) {
     if (op1->digit_count == 0) {
@@ -404,7 +440,7 @@ void bigint_add(BigInt *dest, const BigInt *op1, const BigInt *op2) {
 
         const uint64_t *op1_digits = bigint_ptr(op1);
         const uint64_t *op2_digits = bigint_ptr(op2);
-        uint64_t overflow = add_u64_overflow(op1_digits[0], op2_digits[0], &dest->data.digit);
+        bool overflow = add_u64_overflow(op1_digits[0], op2_digits[0], &dest->data.digit);
         if (overflow == 0 && op1->digit_count == 1 && op2->digit_count == 1) {
             dest->digit_count = 1;
             bigint_normalize(dest);
@@ -534,9 +570,9 @@ static void mul_overflow(uint64_t x, uint64_t y, uint64_t *result, uint64_t *car
         return;
     }
 
-    unsigned __int128 big_x = x;
-    unsigned __int128 big_y = y;
-    unsigned __int128 big_result = big_x * big_y;
+    uint128_t big_x = x;
+    uint128_t big_y = y;
+    uint128_t big_result = big_x * big_y;
     *carry = big_result >> 64;
 }
 
src/bigint.hpp
@@ -11,6 +11,15 @@
 #include <stdint.h>
 #include <stddef.h>
 
+#if defined(_MSVC)
+    // TEMPORARY WORKAROUND FOR MSVC NOT SUPPORTING __int128
+    typedef long long int128_t;
+    typedef unsigned long long uint128_t;
+#else
+    typedef __int128 int128_t;
+    typedef unsigned __int128 uint128_t;
+#endif
+
 struct BigInt {
     size_t digit_count;
     union {
@@ -30,7 +39,7 @@ enum Cmp {
 };
 
 void bigint_init_unsigned(BigInt *dest, uint64_t x);
-void bigint_init_u128(BigInt *dest, unsigned __int128 x);
+void bigint_init_u128(BigInt *dest, uint128_t x);
 void bigint_init_signed(BigInt *dest, int64_t x);
 void bigint_init_bigint(BigInt *dest, const BigInt *src);
 void bigint_init_bigfloat(BigInt *dest, const BigFloat *op);
@@ -89,4 +98,6 @@ size_t bigint_bits_needed(const BigInt *op);
 // convenience functions
 Cmp bigint_cmp_zero(const BigInt *op);
 
+bool mul_u64_overflow(uint64_t op1, uint64_t op2, uint64_t *result);
+
 #endif
src/buffer.hpp
@@ -24,7 +24,7 @@ struct Buf {
 };
 
 Buf *buf_sprintf(const char *format, ...)
-    __attribute__ ((format (printf, 1, 2)));
+    ATTRIBUTE_FORMAT(printf, 1, 2);
 Buf *buf_vprintf(const char *format, va_list ap);
 
 static inline size_t buf_len(Buf *buf) {
@@ -124,7 +124,7 @@ static inline void buf_append_char(Buf *buf, uint8_t c) {
 }
 
 void buf_appendf(Buf *buf, const char *format, ...)
-    __attribute__ ((format (printf, 2, 3)));
+    ATTRIBUTE_FORMAT(printf, 2, 3);
 
 static inline bool buf_eql_mem(Buf *buf, const char *mem, size_t mem_len) {
     assert(buf->list.length);
src/codegen.cpp
@@ -5194,7 +5194,19 @@ void codegen_add_object(CodeGen *g, Buf *object_path) {
     g->link_objects.append(object_path);
 }
 
-
+#if defined(_MSVC)
+// MSVC doesn't seem to support "designators" for array initialization
+static const char *c_int_type_names[] = {
+    "short",
+    "unsigned short",
+    "int",
+    "unsigned int",
+    "long",
+    "unsigned long",
+    "long long",
+    "unsigned long long",
+};
+#else
 static const char *c_int_type_names[] = {
     [CIntTypeShort] = "short",
     [CIntTypeUShort] = "unsigned short",
@@ -5205,6 +5217,7 @@ static const char *c_int_type_names[] = {
     [CIntTypeLongLong] = "long long",
     [CIntTypeULongLong] = "unsigned long long",
 };
+#endif
 
 static void get_c_type(CodeGen *g, TypeTableEntry *type_entry, Buf *out_buf) {
     assert(type_entry);
src/ir.cpp
@@ -6500,9 +6500,9 @@ static void float_init_bigint(BigInt *bigint, ConstExprValue *const_val) {
                 break;
             case 128:
                 if (const_val->data.x_f128 >= 0) {
-                    bigint_init_u128(bigint, (unsigned __int128)(const_val->data.x_f128));
+                    bigint_init_u128(bigint, (uint128_t)(const_val->data.x_f128));
                 } else {
-                    bigint_init_u128(bigint, (unsigned __int128)(-const_val->data.x_f128));
+                    bigint_init_u128(bigint, (uint128_t)(-const_val->data.x_f128));
                     bigint->is_negative = true;
                 }
                 break;
@@ -9731,8 +9731,7 @@ static TypeTableEntry *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp
     uint64_t old_array_len = array_type->data.array.len;
     uint64_t new_array_len;
 
-    if (__builtin_umulll_overflow((unsigned long long)old_array_len, (unsigned long long)mult_amt,
-                (unsigned long long*)&new_array_len))
+    if (mul_u64_overflow(old_array_len, mult_amt, &new_array_len))
     {
         ir_add_error(ira, &instruction->base, buf_sprintf("operation results in overflow"));
         return ira->codegen->builtin_types.entry_invalid;
src/os.cpp
@@ -25,6 +25,8 @@
 
 #include <windows.h>
 #include <io.h>
+
+typedef SSIZE_T ssize_t;
 #else
 #define ZIG_OS_POSIX
 
@@ -620,7 +622,7 @@ int os_get_cwd(Buf *out_cwd) {
 
 bool os_stderr_tty(void) {
 #if defined(ZIG_OS_WINDOWS)
-    return _isatty(STDERR_FILENO) != 0;
+    return _isatty(_fileno(stderr)) != 0;
 #elif defined(ZIG_OS_POSIX)
     return isatty(STDERR_FILENO) != 0;
 #else
@@ -777,12 +779,12 @@ int os_make_path(Buf *path) {
 
 int os_make_dir(Buf *path) {
 #if defined(ZIG_OS_WINDOWS)
-    if (mkdir(buf_ptr(path)) == -1) {
-        if (errno == EEXIST)
+    if (!CreateDirectory(buf_ptr(path), NULL)) {
+        if (GetLastError() == ERROR_ALREADY_EXISTS)
             return ErrorPathAlreadyExists;
-        if (errno == ENOENT)
+        if (GetLastError() == ERROR_PATH_NOT_FOUND)
             return ErrorFileNotFound;
-        if (errno == EACCES)
+        if (GetLastError() == ERROR_ACCESS_DENIED)
             return ErrorAccess;
         return ErrorUnexpected;
     }
src/parsec.cpp
@@ -56,7 +56,7 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl);
 static AstNode *resolve_typedef_decl(Context *c, const TypedefNameDecl *typedef_decl);
 
 
-__attribute__ ((format (printf, 3, 4)))
+ATTRIBUTE_FORMAT(printf, 3, 4)
 static void emit_warning(Context *c, const SourceLocation &sl, const char *format, ...) {
     if (!c->warnings_on) {
         return;
src/parser.cpp
@@ -24,8 +24,8 @@ struct ParseContext {
     Buf *void_buf;
 };
 
-__attribute__ ((format (printf, 4, 5)))
-__attribute__ ((noreturn))
+ATTRIBUTE_FORMAT(printf, 4, 5)
+LLVM_ATTRIBUTE_NORETURN
 static void ast_asm_error(ParseContext *pc, AstNode *node, size_t offset, const char *format, ...) {
     assert(node->type == NodeTypeAsmExpr);
 
@@ -46,8 +46,8 @@ static void ast_asm_error(ParseContext *pc, AstNode *node, size_t offset, const
     exit(EXIT_FAILURE);
 }
 
-__attribute__ ((format (printf, 3, 4)))
-__attribute__ ((noreturn))
+ATTRIBUTE_FORMAT(printf, 3, 4)
+LLVM_ATTRIBUTE_NORETURN
 static void ast_error(ParseContext *pc, Token *token, const char *format, ...) {
     va_list ap;
     va_start(ap, format);
@@ -205,7 +205,7 @@ static void ast_buf_from_token(ParseContext *pc, Token *token, Buf *buf) {
     }
 }
 
-__attribute__ ((noreturn))
+LLVM_ATTRIBUTE_NORETURN
 static void ast_invalid_token_error(ParseContext *pc, Token *token) {
     Buf token_value = BUF_INIT;
     ast_buf_from_token(pc, token, &token_value);
src/parser.hpp
@@ -12,7 +12,7 @@
 #include "tokenizer.hpp"
 #include "errmsg.hpp"
 
-__attribute__ ((format (printf, 2, 3)))
+ATTRIBUTE_FORMAT(printf, 2, 3)
 void ast_token_error(Token *token, const char *format, ...);
 
 
src/quadmath.hpp
@@ -8,12 +8,46 @@
 #ifndef ZIG_QUADMATH_HPP
 #define ZIG_QUADMATH_HPP
 
+#if defined(_MSVC)
+    #include <stdlib.h>
+    #include <stdio.h>
+    #include <stdarg.h>
+    #include <cmath>
+#endif
+
 extern "C" {
+#if defined(_MSVC)
+    static __float128 fmodq(__float128 a, __float128 b)
+    {
+        return fmod(a, b);
+    }
+    static __float128 ceilq(__float128 a)
+    {
+        return ceil(a);
+    }
+    static __float128 floorq(__float128 a)
+    {
+        return floor(a);
+    }
+    static __float128 strtoflt128(const char *s, char **sp)
+    {
+        return strtold(s, sp);
+    }
+    static int quadmath_snprintf(char *s, size_t size, const char *format, ...)
+    {
+        va_list args;
+        va_start(format, args);
+        int result = vsnprintf(s, size, format, args);
+        va_end(args);
+        return result;
+    }
+#else
     __float128 fmodq(__float128 a, __float128 b);
     __float128 ceilq(__float128 a);
     __float128 floorq(__float128 a);
     __float128 strtoflt128 (const char *s, char **sp);
     int quadmath_snprintf (char *s, size_t size, const char *format, ...);
+#endif
 }
 
 #endif
src/tokenizer.cpp
@@ -234,7 +234,7 @@ struct Tokenize {
     BigInt significand;
 };
 
-__attribute__ ((format (printf, 2, 3)))
+ATTRIBUTE_FORMAT(printf, 2, 3)
 static void tokenize_error(Tokenize *t, const char *format, ...) {
     t->state = TokenizeStateError;
 
@@ -331,7 +331,7 @@ static void end_float_token(Tokenize *t) {
         if (t->radix == 10) {
             zig_panic("TODO: decimal floats");
         } else {
-            int significand_magnitude_in_bin = __builtin_clzll(1) - __builtin_clzll(significand);
+            int significand_magnitude_in_bin = clzll(1) - clzll(significand);
             t->exponent_in_bin_or_dec += significand_magnitude_in_bin;
             if (!(-1022 <= t->exponent_in_bin_or_dec && t->exponent_in_bin_or_dec <= 1023)) {
                 t->cur_tok->data.float_lit.overflow = true;
src/util.hpp
@@ -12,24 +12,52 @@
 #include <stdint.h>
 #include <string.h>
 #include <assert.h>
+#include <llvm/Support/Compiler.h>
 
 #include <new>
 
+#if defined(_MSVC)
+    #define ATTRIBUTE_COLD
+    #define ATTRIBUTE_FORMAT(args)
+    static inline uint32_t popcnt(unsigned long long x)
+    {
+        x -= ((x >> 1) & 0x55555555);
+        x = (((x >> 2) & 0x33333333) + (x & 0x33333333));
+        x = (((x >> 4) + x) & 0x0f0f0f0f);
+        x += (x >> 8);
+        x += (x >> 16);
+        return x & 0x0000003f;
+    }
+    static inline uint32_t clzll(unsigned long long x)
+    {
+        x |= (x >> 1);
+        x |= (x >> 2);
+        x |= (x >> 4);
+        x |= (x >> 8);
+        x |= (x >> 16);
+        return 32 - popcnt(x);
+    }
+#else
+    #define ATTRIBUTE_COLD         __attribute__((cold))
+    #define ATTRIBUTE_FORMAT(args) __attribute__((format (args)))
+    #define clzll(x) __builtin_clzll(x)
+#endif
+
 #define BREAKPOINT __asm("int $0x03")
 
-void zig_panic(const char *format, ...)
-    __attribute__((cold))
-    __attribute__ ((noreturn))
-    __attribute__ ((format (printf, 1, 2)));
+LLVM_ATTRIBUTE_NOINLINE
+ATTRIBUTE_COLD
+ATTRIBUTE_FORMAT(printf, 1, 2)
+void zig_panic(const char *format, ...);
 
-__attribute__((cold))
-__attribute__ ((noreturn))
+ATTRIBUTE_COLD
+LLVM_ATTRIBUTE_NOINLINE
 static inline void zig_unreachable(void) {
     zig_panic("unreachable");
 }
 
 template<typename T>
-__attribute__((malloc)) static inline T *allocate_nonzero(size_t count) {
+LLVM_ATTRIBUTE_RETURNS_NOALIAS static inline T *allocate_nonzero(size_t count) {
     T *ptr = reinterpret_cast<T*>(malloc(count * sizeof(T)));
     if (!ptr)
         zig_panic("allocation failed");
@@ -37,7 +65,7 @@ __attribute__((malloc)) static inline T *allocate_nonzero(size_t count) {
 }
 
 template<typename T>
-__attribute__((malloc)) static inline T *allocate(size_t count) {
+LLVM_ATTRIBUTE_RETURNS_NOALIAS static inline T *allocate(size_t count) {
     T *ptr = reinterpret_cast<T*>(calloc(count, sizeof(T)));
     if (!ptr)
         zig_panic("allocation failed");
CMakeLists.txt
@@ -130,16 +130,21 @@ else()
     add_library(embedded_lld_lib ${EMBEDDED_LLD_LIB_SOURCES})
     add_library(embedded_lld_elf ${EMBEDDED_LLD_ELF_SOURCES})
     add_library(embedded_lld_coff ${EMBEDDED_LLD_COFF_SOURCES})
+    if(MINGW)
+        set(UNIQUE_COMPILE_FLAGS "-fno-exceptions -fno-rtti -Wno-comment")
+    elseif(MSVC)
+        set(UNIQUE_COMPILE_FLAGS "-D_MSVC")
+    endif()
     set_target_properties(embedded_lld_lib PROPERTIES
-        COMPILE_FLAGS "-std=c++11 -fno-exceptions -fno-rtti -Wno-comment"
+        COMPILE_FLAGS "-std=c++11 ${UNIQUE_COMPILE_FLAGS}"
         LINK_FLAGS " "
     )
     set_target_properties(embedded_lld_elf PROPERTIES
-        COMPILE_FLAGS "-std=c++11 -fno-exceptions -fno-rtti -Wno-comment"
+        COMPILE_FLAGS "-std=c++11 ${UNIQUE_COMPILE_FLAGS}"
         LINK_FLAGS " "
     )
     set_target_properties(embedded_lld_coff PROPERTIES
-        COMPILE_FLAGS "-std=c++11 -fno-exceptions -fno-rtti -Wno-comment"
+        COMPILE_FLAGS "-std=c++11 ${UNIQUE_COMPILE_FLAGS}"
         LINK_FLAGS " "
     )
     target_include_directories(embedded_lld_lib PUBLIC
@@ -211,14 +216,17 @@ include_directories(
     "${CMAKE_SOURCE_DIR}/src"
 )
 
-set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Werror -Wall")
-
-
+set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
 if(MINGW)
-    set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wno-error=format= -Wno-error=format -Wno-error=format-extra-args")
+    set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Wall -Werror -Wno-error=format= -Wno-error=format -Wno-error=format-extra-args")
 endif()
 
-set(EXE_CFLAGS "-std=c++11 -fno-exceptions -fno-rtti -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -Werror=strict-prototypes -Werror=old-style-definition -Werror=type-limits -Wno-missing-braces")
+set(EXE_CFLAGS "-std=c++11")
+if(MINGW)
+    set(EXE_CFLAGS "${EXE_CFLAGS} -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -D_GNU_SOURCE -fno-exceptions -fno-rtti  -Werror=strict-prototypes -Werror=old-style-definition -Werror=type-limits -Wno-missing-braces")
+elseif(MSVC)
+    set(EXE_CFLAGS "${EXE_CFLAGS} -D_MSVC")
+endif()
 set(EXE_LDFLAGS " ")
 if(ZIG_TEST_COVERAGE)
     set(EXE_CFLAGS "${EXE_CFLAGS} -fprofile-arcs -ftest-coverage")
@@ -230,16 +238,23 @@ set_target_properties(zig PROPERTIES
     COMPILE_FLAGS ${EXE_CFLAGS}
     LINK_FLAGS ${EXE_LDFLAGS}
 )
+
+if(MINGW)
+    set(PLATFORM_LIBRARIES quadmath)
+endif()
 target_link_libraries(zig LINK_PUBLIC
     ${CLANG_LIBRARIES}
     ${LLD_LIBRARIES}
     ${LLVM_LIBRARIES}
     ${CMAKE_THREAD_LIBS_INIT}
-    quadmath
+    ${PLATFORM_LIBRARIES}
 )
-if(MINGW)
+if(MINGW OR MSVC)
     target_link_libraries(zig LINK_PUBLIC version)
 endif()
+if(MSVC)
+    target_link_libraries(zig LINK_PUBLIC "C:/Program Files (x86)/Microsoft Visual Studio 14.0/DIA SDK/lib/diaguids.lib")
+endif()
 install(TARGETS zig DESTINATION bin)
 
 install(FILES "${CMAKE_SOURCE_DIR}/c_headers/__clang_cuda_builtin_vars.h" DESTINATION "${C_HEADERS_DEST}")
@@ -455,3 +470,4 @@ if (ZIG_TEST_COVERAGE)
         COMMAND rm coverage.info coverage.info.cleaned
     )
 endif()
+