Add support for MSVC

master
Jonathan Marler 2017-09-10 14:05:18 -06:00 committed by Jonathan Marler
parent 373785ae8d
commit 7c81cd30de
17 changed files with 238 additions and 60 deletions

View File

@ -130,16 +130,21 @@ else()
add_library(embedded_lld_lib ${EMBEDDED_LLD_LIB_SOURCES}) add_library(embedded_lld_lib ${EMBEDDED_LLD_LIB_SOURCES})
add_library(embedded_lld_elf ${EMBEDDED_LLD_ELF_SOURCES}) add_library(embedded_lld_elf ${EMBEDDED_LLD_ELF_SOURCES})
add_library(embedded_lld_coff ${EMBEDDED_LLD_COFF_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 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 " " LINK_FLAGS " "
) )
set_target_properties(embedded_lld_elf PROPERTIES 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 " " LINK_FLAGS " "
) )
set_target_properties(embedded_lld_coff PROPERTIES 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 " " LINK_FLAGS " "
) )
target_include_directories(embedded_lld_lib PUBLIC target_include_directories(embedded_lld_lib PUBLIC
@ -211,14 +216,17 @@ include_directories(
"${CMAKE_SOURCE_DIR}/src" "${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) 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() 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 " ") set(EXE_LDFLAGS " ")
if(ZIG_TEST_COVERAGE) if(ZIG_TEST_COVERAGE)
set(EXE_CFLAGS "${EXE_CFLAGS} -fprofile-arcs -ftest-coverage") set(EXE_CFLAGS "${EXE_CFLAGS} -fprofile-arcs -ftest-coverage")
@ -230,16 +238,23 @@ set_target_properties(zig PROPERTIES
COMPILE_FLAGS ${EXE_CFLAGS} COMPILE_FLAGS ${EXE_CFLAGS}
LINK_FLAGS ${EXE_LDFLAGS} LINK_FLAGS ${EXE_LDFLAGS}
) )
if(MINGW)
set(PLATFORM_LIBRARIES quadmath)
endif()
target_link_libraries(zig LINK_PUBLIC target_link_libraries(zig LINK_PUBLIC
${CLANG_LIBRARIES} ${CLANG_LIBRARIES}
${LLD_LIBRARIES} ${LLD_LIBRARIES}
${LLVM_LIBRARIES} ${LLVM_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT} ${CMAKE_THREAD_LIBS_INIT}
quadmath ${PLATFORM_LIBRARIES}
) )
if(MINGW) if(MINGW OR MSVC)
target_link_libraries(zig LINK_PUBLIC version) target_link_libraries(zig LINK_PUBLIC version)
endif() 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(TARGETS zig DESTINATION bin)
install(FILES "${CMAKE_SOURCE_DIR}/c_headers/__clang_cuda_builtin_vars.h" DESTINATION "${C_HEADERS_DEST}") 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 COMMAND rm coverage.info coverage.info.cleaned
) )
endif() endif()

View File

@ -8,14 +8,20 @@
find_path(CLANG_INCLUDE_DIRS NAMES clang/Frontend/ASTUnit.h find_path(CLANG_INCLUDE_DIRS NAMES clang/Frontend/ASTUnit.h
PATHS PATHS
${LLVM_INSTALL_PREFIX}/include
/usr/lib/llvm/5/include /usr/lib/llvm/5/include
/usr/lib/llvm-5.0/include /usr/lib/llvm-5.0/include
/mingw64/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_) string(TOUPPER ${_libname_} _prettylibname_)
find_library(CLANG_${_prettylibname_}_LIB NAMES ${_libname_} find_library(CLANG_${_prettylibname_}_LIB NAMES ${_libname_}
PATHS PATHS
${LLVM_INSTALL_PREFIX}/lib
/usr/lib/llvm/5/lib /usr/lib/llvm/5/lib
/usr/lib/llvm-5.0/lib /usr/lib/llvm-5.0/lib
/mingw64/lib /mingw64/lib

View File

@ -2,28 +2,53 @@
# This file is MIT licensed. # This file is MIT licensed.
# See http://opensource.org/licenses/MIT # See http://opensource.org/licenses/MIT
# LLVM_FOUND
# LLVM_INCLUDE_DIR # LLVM_INCLUDE_DIR
# LLVM_LIBRARIES # LLVM_LIBRARIES
# LLVM_LIBDIRS # LLVM_LIBDIRS
find_program(LLVM_CONFIG_EXE if(LLVM_INSTALL_PREFIX)
NAMES llvm-config-5.0 llvm-config find_program(LLVM_CONFIG_EXE
PATHS NAMES llvm-config-5.0 llvm-config
"/mingw64/bin" PATHS ${LLVM_INSTALL_PREFIX}/bin
"/c/msys64/mingw64/bin" NO_DEFAULT_PATH)
"c:/msys64/mingw64/bin" if(NOT LLVM_CONFIG_EXE)
"C:/Libraries/llvm-5.0.0/bin") 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( execute_process(
COMMAND ${LLVM_CONFIG_EXE} --libs COMMAND ${LLVM_CONFIG_EXE} --libs
OUTPUT_VARIABLE LLVM_LIBRARIES OUTPUT_VARIABLE LLVM_LIBRARIES_STRING
OUTPUT_STRIP_TRAILING_WHITESPACE) OUTPUT_STRIP_TRAILING_WHITESPACE)
string(REPLACE " " ";" LLVM_LIBRARIES ${LLVM_LIBRARIES_STRING})
execute_process( execute_process(
COMMAND ${LLVM_CONFIG_EXE} --system-libs COMMAND ${LLVM_CONFIG_EXE} --system-libs
OUTPUT_VARIABLE LLVM_SYSTEM_LIBS OUTPUT_VARIABLE LLVM_SYSTEM_LIBS_STRING
OUTPUT_STRIP_TRAILING_WHITESPACE) OUTPUT_STRIP_TRAILING_WHITESPACE)
string(REPLACE " " ";" LLVM_SYSTEM_LIBS ${LLVM_SYSTEM_LIBS_STRING})
execute_process( execute_process(
COMMAND ${LLVM_CONFIG_EXE} --libdir COMMAND ${LLVM_CONFIG_EXE} --libdir

View File

@ -163,7 +163,7 @@ static TypeTableEntry *new_container_type_entry(TypeTableEntryId id, AstNode *so
} }
static uint8_t log2_u64(uint64_t x) { 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) { static uint8_t bits_needed_for_unsigned(uint64_t x) {

View File

@ -13,6 +13,14 @@
#include <stdint.h> #include <stdint.h>
#include <stddef.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 { struct BigFloat {
__float128 value; __float128 value;
}; };

View File

@ -141,7 +141,7 @@ void bigint_init_unsigned(BigInt *dest, uint64_t x) {
dest->is_negative = false; 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 low = (uint64_t)(x & UINT64_MAX);
uint64_t high = (uint64_t)(x >> 64); 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) { void bigint_init_bigfloat(BigInt *dest, const BigFloat *op) {
if (op->value >= 0) { if (op->value >= 0) {
bigint_init_u128(dest, (unsigned __int128)(op->value)); bigint_init_u128(dest, (uint128_t)(op->value));
} else { } else {
bigint_init_u128(dest, (unsigned __int128)(-op->value)); bigint_init_u128(dest, (uint128_t)(-op->value));
dest->is_negative = true; 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) { 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, return __builtin_uaddll_overflow((unsigned long long)op1, (unsigned long long)op2,
(unsigned long long *)result); (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); (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, return __builtin_umulll_overflow((unsigned long long)op1, (unsigned long long)op2,
(unsigned long long *)result); (unsigned long long *)result);
} }
#endif
void bigint_add(BigInt *dest, const BigInt *op1, const BigInt *op2) { void bigint_add(BigInt *dest, const BigInt *op1, const BigInt *op2) {
if (op1->digit_count == 0) { 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 *op1_digits = bigint_ptr(op1);
const uint64_t *op2_digits = bigint_ptr(op2); 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) { if (overflow == 0 && op1->digit_count == 1 && op2->digit_count == 1) {
dest->digit_count = 1; dest->digit_count = 1;
bigint_normalize(dest); bigint_normalize(dest);
@ -534,9 +570,9 @@ static void mul_overflow(uint64_t x, uint64_t y, uint64_t *result, uint64_t *car
return; return;
} }
unsigned __int128 big_x = x; uint128_t big_x = x;
unsigned __int128 big_y = y; uint128_t big_y = y;
unsigned __int128 big_result = big_x * big_y; uint128_t big_result = big_x * big_y;
*carry = big_result >> 64; *carry = big_result >> 64;
} }

View File

@ -11,6 +11,15 @@
#include <stdint.h> #include <stdint.h>
#include <stddef.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 { struct BigInt {
size_t digit_count; size_t digit_count;
union { union {
@ -30,7 +39,7 @@ enum Cmp {
}; };
void bigint_init_unsigned(BigInt *dest, uint64_t x); 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_signed(BigInt *dest, int64_t x);
void bigint_init_bigint(BigInt *dest, const BigInt *src); void bigint_init_bigint(BigInt *dest, const BigInt *src);
void bigint_init_bigfloat(BigInt *dest, const BigFloat *op); void bigint_init_bigfloat(BigInt *dest, const BigFloat *op);
@ -89,4 +98,6 @@ size_t bigint_bits_needed(const BigInt *op);
// convenience functions // convenience functions
Cmp bigint_cmp_zero(const BigInt *op); Cmp bigint_cmp_zero(const BigInt *op);
bool mul_u64_overflow(uint64_t op1, uint64_t op2, uint64_t *result);
#endif #endif

View File

@ -24,7 +24,7 @@ struct Buf {
}; };
Buf *buf_sprintf(const char *format, ...) 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); Buf *buf_vprintf(const char *format, va_list ap);
static inline size_t buf_len(Buf *buf) { 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, ...) 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) { static inline bool buf_eql_mem(Buf *buf, const char *mem, size_t mem_len) {
assert(buf->list.length); assert(buf->list.length);

View File

@ -5194,7 +5194,19 @@ void codegen_add_object(CodeGen *g, Buf *object_path) {
g->link_objects.append(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[] = { static const char *c_int_type_names[] = {
[CIntTypeShort] = "short", [CIntTypeShort] = "short",
[CIntTypeUShort] = "unsigned short", [CIntTypeUShort] = "unsigned short",
@ -5205,6 +5217,7 @@ static const char *c_int_type_names[] = {
[CIntTypeLongLong] = "long long", [CIntTypeLongLong] = "long long",
[CIntTypeULongLong] = "unsigned long long", [CIntTypeULongLong] = "unsigned long long",
}; };
#endif
static void get_c_type(CodeGen *g, TypeTableEntry *type_entry, Buf *out_buf) { static void get_c_type(CodeGen *g, TypeTableEntry *type_entry, Buf *out_buf) {
assert(type_entry); assert(type_entry);

View File

@ -6500,9 +6500,9 @@ static void float_init_bigint(BigInt *bigint, ConstExprValue *const_val) {
break; break;
case 128: case 128:
if (const_val->data.x_f128 >= 0) { 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 { } 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; bigint->is_negative = true;
} }
break; 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 old_array_len = array_type->data.array.len;
uint64_t new_array_len; uint64_t new_array_len;
if (__builtin_umulll_overflow((unsigned long long)old_array_len, (unsigned long long)mult_amt, if (mul_u64_overflow(old_array_len, mult_amt, &new_array_len))
(unsigned long long*)&new_array_len))
{ {
ir_add_error(ira, &instruction->base, buf_sprintf("operation results in overflow")); ir_add_error(ira, &instruction->base, buf_sprintf("operation results in overflow"));
return ira->codegen->builtin_types.entry_invalid; return ira->codegen->builtin_types.entry_invalid;

View File

@ -25,6 +25,8 @@
#include <windows.h> #include <windows.h>
#include <io.h> #include <io.h>
typedef SSIZE_T ssize_t;
#else #else
#define ZIG_OS_POSIX #define ZIG_OS_POSIX
@ -620,7 +622,7 @@ int os_get_cwd(Buf *out_cwd) {
bool os_stderr_tty(void) { bool os_stderr_tty(void) {
#if defined(ZIG_OS_WINDOWS) #if defined(ZIG_OS_WINDOWS)
return _isatty(STDERR_FILENO) != 0; return _isatty(_fileno(stderr)) != 0;
#elif defined(ZIG_OS_POSIX) #elif defined(ZIG_OS_POSIX)
return isatty(STDERR_FILENO) != 0; return isatty(STDERR_FILENO) != 0;
#else #else
@ -777,12 +779,12 @@ int os_make_path(Buf *path) {
int os_make_dir(Buf *path) { int os_make_dir(Buf *path) {
#if defined(ZIG_OS_WINDOWS) #if defined(ZIG_OS_WINDOWS)
if (mkdir(buf_ptr(path)) == -1) { if (!CreateDirectory(buf_ptr(path), NULL)) {
if (errno == EEXIST) if (GetLastError() == ERROR_ALREADY_EXISTS)
return ErrorPathAlreadyExists; return ErrorPathAlreadyExists;
if (errno == ENOENT) if (GetLastError() == ERROR_PATH_NOT_FOUND)
return ErrorFileNotFound; return ErrorFileNotFound;
if (errno == EACCES) if (GetLastError() == ERROR_ACCESS_DENIED)
return ErrorAccess; return ErrorAccess;
return ErrorUnexpected; return ErrorUnexpected;
} }

View File

@ -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); 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, ...) { static void emit_warning(Context *c, const SourceLocation &sl, const char *format, ...) {
if (!c->warnings_on) { if (!c->warnings_on) {
return; return;

View File

@ -24,8 +24,8 @@ struct ParseContext {
Buf *void_buf; Buf *void_buf;
}; };
__attribute__ ((format (printf, 4, 5))) ATTRIBUTE_FORMAT(printf, 4, 5)
__attribute__ ((noreturn)) LLVM_ATTRIBUTE_NORETURN
static void ast_asm_error(ParseContext *pc, AstNode *node, size_t offset, const char *format, ...) { static void ast_asm_error(ParseContext *pc, AstNode *node, size_t offset, const char *format, ...) {
assert(node->type == NodeTypeAsmExpr); assert(node->type == NodeTypeAsmExpr);
@ -46,8 +46,8 @@ static void ast_asm_error(ParseContext *pc, AstNode *node, size_t offset, const
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
__attribute__ ((format (printf, 3, 4))) ATTRIBUTE_FORMAT(printf, 3, 4)
__attribute__ ((noreturn)) LLVM_ATTRIBUTE_NORETURN
static void ast_error(ParseContext *pc, Token *token, const char *format, ...) { static void ast_error(ParseContext *pc, Token *token, const char *format, ...) {
va_list ap; va_list ap;
va_start(ap, format); 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) { static void ast_invalid_token_error(ParseContext *pc, Token *token) {
Buf token_value = BUF_INIT; Buf token_value = BUF_INIT;
ast_buf_from_token(pc, token, &token_value); ast_buf_from_token(pc, token, &token_value);

View File

@ -12,7 +12,7 @@
#include "tokenizer.hpp" #include "tokenizer.hpp"
#include "errmsg.hpp" #include "errmsg.hpp"
__attribute__ ((format (printf, 2, 3))) ATTRIBUTE_FORMAT(printf, 2, 3)
void ast_token_error(Token *token, const char *format, ...); void ast_token_error(Token *token, const char *format, ...);

View File

@ -8,12 +8,46 @@
#ifndef ZIG_QUADMATH_HPP #ifndef ZIG_QUADMATH_HPP
#define ZIG_QUADMATH_HPP #define ZIG_QUADMATH_HPP
#if defined(_MSVC)
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <cmath>
#endif
extern "C" { 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 fmodq(__float128 a, __float128 b);
__float128 ceilq(__float128 a); __float128 ceilq(__float128 a);
__float128 floorq(__float128 a); __float128 floorq(__float128 a);
__float128 strtoflt128 (const char *s, char **sp); __float128 strtoflt128 (const char *s, char **sp);
int quadmath_snprintf (char *s, size_t size, const char *format, ...); int quadmath_snprintf (char *s, size_t size, const char *format, ...);
#endif
} }
#endif #endif

View File

@ -234,7 +234,7 @@ struct Tokenize {
BigInt significand; BigInt significand;
}; };
__attribute__ ((format (printf, 2, 3))) ATTRIBUTE_FORMAT(printf, 2, 3)
static void tokenize_error(Tokenize *t, const char *format, ...) { static void tokenize_error(Tokenize *t, const char *format, ...) {
t->state = TokenizeStateError; t->state = TokenizeStateError;
@ -331,7 +331,7 @@ static void end_float_token(Tokenize *t) {
if (t->radix == 10) { if (t->radix == 10) {
zig_panic("TODO: decimal floats"); zig_panic("TODO: decimal floats");
} else { } 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; 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)) { if (!(-1022 <= t->exponent_in_bin_or_dec && t->exponent_in_bin_or_dec <= 1023)) {
t->cur_tok->data.float_lit.overflow = true; t->cur_tok->data.float_lit.overflow = true;

View File

@ -12,24 +12,52 @@
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
#include <assert.h> #include <assert.h>
#include <llvm/Support/Compiler.h>
#include <new> #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") #define BREAKPOINT __asm("int $0x03")
void zig_panic(const char *format, ...) LLVM_ATTRIBUTE_NOINLINE
__attribute__((cold)) ATTRIBUTE_COLD
__attribute__ ((noreturn)) ATTRIBUTE_FORMAT(printf, 1, 2)
__attribute__ ((format (printf, 1, 2))); void zig_panic(const char *format, ...);
__attribute__((cold)) ATTRIBUTE_COLD
__attribute__ ((noreturn)) LLVM_ATTRIBUTE_NOINLINE
static inline void zig_unreachable(void) { static inline void zig_unreachable(void) {
zig_panic("unreachable"); zig_panic("unreachable");
} }
template<typename T> 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))); T *ptr = reinterpret_cast<T*>(malloc(count * sizeof(T)));
if (!ptr) if (!ptr)
zig_panic("allocation failed"); zig_panic("allocation failed");
@ -37,7 +65,7 @@ __attribute__((malloc)) static inline T *allocate_nonzero(size_t count) {
} }
template<typename T> 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))); T *ptr = reinterpret_cast<T*>(calloc(count, sizeof(T)));
if (!ptr) if (!ptr)
zig_panic("allocation failed"); zig_panic("allocation failed");