diff --git a/CMakeLists.txt b/CMakeLists.txt index 9524411e8..5f8d4580f 100644 --- a/CMakeLists.txt +++ b/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() + diff --git a/cmake/Findclang.cmake b/cmake/Findclang.cmake index 04d3fb020..486999b53 100644 --- a/cmake/Findclang.cmake +++ b/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 diff --git a/cmake/Findllvm.cmake b/cmake/Findllvm.cmake index 97e0a9a67..480bd17ce 100644 --- a/cmake/Findllvm.cmake +++ b/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 diff --git a/src/analyze.cpp b/src/analyze.cpp index bfc3bbfa7..5606e25bb 100644 --- a/src/analyze.cpp +++ b/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) { diff --git a/src/bigfloat.hpp b/src/bigfloat.hpp index 1923bade0..7355b0d5c 100644 --- a/src/bigfloat.hpp +++ b/src/bigfloat.hpp @@ -13,6 +13,14 @@ #include #include +#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; }; diff --git a/src/bigint.cpp b/src/bigint.cpp index 395d9fce8..66d4068d7 100644 --- a/src/bigint.cpp +++ b/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; } diff --git a/src/bigint.hpp b/src/bigint.hpp index c77fb5224..242b64052 100644 --- a/src/bigint.hpp +++ b/src/bigint.hpp @@ -11,6 +11,15 @@ #include #include +#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 diff --git a/src/buffer.hpp b/src/buffer.hpp index 8c732f93e..67f7ab758 100644 --- a/src/buffer.hpp +++ b/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); diff --git a/src/codegen.cpp b/src/codegen.cpp index 15eac3368..5a273375f 100644 --- a/src/codegen.cpp +++ b/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); diff --git a/src/ir.cpp b/src/ir.cpp index 73f7b1df1..a06fc261c 100644 --- a/src/ir.cpp +++ b/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; diff --git a/src/os.cpp b/src/os.cpp index 363d6fbf3..65ca9d8cb 100644 --- a/src/os.cpp +++ b/src/os.cpp @@ -25,6 +25,8 @@ #include #include + +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; } diff --git a/src/parsec.cpp b/src/parsec.cpp index 32462407e..9bfb34ce7 100644 --- a/src/parsec.cpp +++ b/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; diff --git a/src/parser.cpp b/src/parser.cpp index c47d6a478..9e63911a2 100644 --- a/src/parser.cpp +++ b/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); diff --git a/src/parser.hpp b/src/parser.hpp index c95413309..1434871ad 100644 --- a/src/parser.hpp +++ b/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, ...); diff --git a/src/quadmath.hpp b/src/quadmath.hpp index 7343a11e3..1c5621cbd 100644 --- a/src/quadmath.hpp +++ b/src/quadmath.hpp @@ -8,12 +8,46 @@ #ifndef ZIG_QUADMATH_HPP #define ZIG_QUADMATH_HPP +#if defined(_MSVC) + #include + #include + #include + #include +#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 diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp index c0c78c15f..e99ad43f8 100644 --- a/src/tokenizer.cpp +++ b/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; diff --git a/src/util.hpp b/src/util.hpp index c57680138..338170ce9 100644 --- a/src/util.hpp +++ b/src/util.hpp @@ -12,24 +12,52 @@ #include #include #include +#include #include +#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 -__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(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 -__attribute__((malloc)) static inline T *allocate(size_t count) { +LLVM_ATTRIBUTE_RETURNS_NOALIAS static inline T *allocate(size_t count) { T *ptr = reinterpret_cast(calloc(count, sizeof(T))); if (!ptr) zig_panic("allocation failed");