From 32150e401e39bd68f9882c3983829e744603dac1 Mon Sep 17 00:00:00 2001 From: Ginger Bill Date: Fri, 17 Mar 2017 12:30:59 +0000 Subject: [PATCH] Update gb.h --- build.bat | 5 +- code/demo.odin | 9 +- core/os_windows.odin | 1 - core/sys/windows.odin | 17 +- src/check_expr.c | 12 +- src/gb/gb.h | 430 ++++++++++++++++++++++++++++++------------ src/ir.c | 8 +- src/ir_print.c | 2 +- src/parser.c | 5 +- src/ssa.c | 173 ++++++++++------- src/types.c | 26 +-- 11 files changed, 455 insertions(+), 233 deletions(-) diff --git a/build.bat b/build.bat index 890d87ecd..f023a3eef 100644 --- a/build.bat +++ b/build.bat @@ -44,7 +44,10 @@ del *.ilk > NUL 2> NUL cl %compiler_settings% "src\main.c" ^ /link %linker_settings% -OUT:%exe_name% ^ - && odin run code/demo.odin + && odin build code/metagen.odin ^ + && call "code\metagen.exe" "src\ast_nodes.metagen" + rem && odin build code/markdown.odin ^ + rem && call "code\markdown.exe" "misc\example.md" rem && odin run code/Jaze/src/main.odin del *.obj > NUL 2> NUL diff --git a/code/demo.odin b/code/demo.odin index 5241e29ce..7153c12f5 100644 --- a/code/demo.odin +++ b/code/demo.odin @@ -10,14 +10,7 @@ #import win32 "sys/windows.odin"; main :: proc() { - a := 1; - b := 2; - c := a + b; - - if c > 0 { - c = 0; - } - + fmt.println("Here"); when false { /* Version 0.1.1 diff --git a/core/os_windows.odin b/core/os_windows.odin index d040797ce..1adc80d18 100644 --- a/core/os_windows.odin +++ b/core/os_windows.odin @@ -247,7 +247,6 @@ read_entire_file :: proc(name: string) -> ([]byte, bool) { heap_alloc :: proc(size: int) -> rawptr { - assert(size > 0); return w.HeapAlloc(w.GetProcessHeap(), w.HEAP_ZERO_MEMORY, size); } heap_resize :: proc(ptr: rawptr, new_size: int) -> rawptr { diff --git a/core/sys/windows.odin b/core/sys/windows.odin index 0a5edf003..f218e15c1 100644 --- a/core/sys/windows.odin +++ b/core/sys/windows.odin @@ -2,6 +2,7 @@ #foreign_system_library "user32.lib" when ODIN_OS == "windows"; #foreign_system_library "gdi32.lib" when ODIN_OS == "windows"; #foreign_system_library "winmm.lib" when ODIN_OS == "windows"; +#foreign_system_library "shell32.lib" when ODIN_OS == "windows"; Handle :: rawptr; Hwnd :: Handle; @@ -181,15 +182,17 @@ GetQueryPerformanceFrequency :: proc() -> i64 { return r; } -GetCommandLineA :: proc() -> ^u8 #foreign kernel32; -GetSystemMetrics :: proc(index: i32) -> i32 #foreign kernel32; -GetCurrentThreadId :: proc() -> u32 #foreign kernel32; +GetCommandLineA :: proc() -> ^u8 #foreign kernel32; +GetCommandLineW :: proc() -> ^u16 #foreign kernel32; +GetSystemMetrics :: proc(index: i32) -> i32 #foreign kernel32; +GetCurrentThreadId :: proc() -> u32 #foreign kernel32; +CommandLineToArgvW :: proc(cmd_list: ^u16, num_args: ^i32) -> ^^u16 #foreign shell32; -timeGetTime :: proc() -> u32 #foreign winmm; -GetSystemTimeAsFileTime :: proc(system_time_as_file_time: ^Filetime) #foreign kernel32; +timeGetTime :: proc() -> u32 #foreign winmm; +GetSystemTimeAsFileTime :: proc(system_time_as_file_time: ^Filetime) #foreign kernel32; FileTimeToLocalFileTime :: proc(file_time: ^Filetime, local_file_time: ^Filetime) -> Bool #foreign kernel32; -FileTimeToSystemTime :: proc(file_time: ^Filetime, system_time: ^Systemtime) -> Bool #foreign kernel32; -SystemTimeToFileTime :: proc(system_time: ^Systemtime, file_time: ^Filetime) -> Bool #foreign kernel32; +FileTimeToSystemTime :: proc(file_time: ^Filetime, system_time: ^Systemtime) -> Bool #foreign kernel32; +SystemTimeToFileTime :: proc(system_time: ^Systemtime, file_time: ^Filetime) -> Bool #foreign kernel32; // File Stuff diff --git a/src/check_expr.c b/src/check_expr.c index 75105462b..c6c9e738b 100644 --- a/src/check_expr.c +++ b/src/check_expr.c @@ -1112,7 +1112,7 @@ Entity *check_ident(Checker *c, Operand *o, AstNode *n, Type *named_type, Type * e->flags |= EntityFlag_Used; Entity *original_e = e; - while (e->kind == Entity_Alias && e->Alias.original != NULL) { + while (e != NULL && e->kind == Entity_Alias && e->Alias.original != NULL) { e = e->Alias.original; } @@ -1672,7 +1672,7 @@ bool check_representable_as_constant(Checker *c, ExactValue in_value, Type *type return true; } - type = base_type(base_enum_type(type)); + type = core_type(type); if (is_type_boolean(type)) { return in_value.kind == ExactValue_Bool; @@ -2118,8 +2118,8 @@ bool check_is_castable_to(Checker *c, Operand *operand, Type *y) { } Type *x = operand->type; - Type *src = base_type(base_enum_type(x)); - Type *dst = base_type(base_enum_type(y)); + Type *src = core_type(x); + Type *dst = core_type(y); if (are_types_identical(src, dst)) { return true; } @@ -2527,7 +2527,7 @@ void convert_to_typed(Checker *c, Operand *operand, Type *target_type, i32 level return; } - Type *t = base_type(base_enum_type(target_type)); + Type *t = core_type(target_type); switch (t->kind) { case Type_Basic: if (operand->mode == Addressing_Constant) { @@ -2689,7 +2689,7 @@ Entity *check_selector(Checker *c, Operand *operand, AstNode *node, Type *type_h expr_entity = e; Entity *original_e = e; - while (e->kind == Entity_Alias && e->Alias.original != NULL) { + while (e != NULL && e->kind == Entity_Alias && e->Alias.original != NULL) { e = e->Alias.original; } diff --git a/src/gb/gb.h b/src/gb/gb.h index 9a665e050..4b048e60d 100644 --- a/src/gb/gb.h +++ b/src/gb/gb.h @@ -1,4 +1,4 @@ -/* gb.h - v0.27 - Ginger Bill's C Helper Library - public domain +/* gb.h - v0.28 - Ginger Bill's C Helper Library - public domain - no warranty implied; use at your own risk This is a single header file with a bunch of useful stuff @@ -58,6 +58,7 @@ TODOS - More date & time functions VERSION HISTORY + 0.28 - Handle UCS2 correctly in Win32 part 0.27 - OSX fixes and Linux gbAffinity 0.26d - Minor changes to how gbFile works 0.26c - gb_str_to_f* fix @@ -1929,6 +1930,7 @@ typedef enum gbSeekWhenceType { typedef enum gbFileError { gbFileError_None, gbFileError_Invalid, + gbFileError_InvalidFilename, gbFileError_Exists, gbFileError_NotExists, gbFileError_Permission, @@ -3242,6 +3244,8 @@ extern "C" { #define STD_OUTPUT_HANDLE ((DWORD)-11) #define STD_ERROR_HANDLE ((DWORD)-12) + GB_DLL_IMPORT int MultiByteToWideChar(UINT code_page, DWORD flags, char const * multi_byte_str, int multi_byte_len, wchar_t const *wide_char_str, int wide_char_len); + GB_DLL_IMPORT int WideCharToMultiByte(UINT code_page, DWORD flags, wchar_t const *wide_char_str, int wide_char_len, char const * multi_byte_str, int multi_byte_len); GB_DLL_IMPORT BOOL WINAPI SetFilePointerEx(HANDLE file, LARGE_INTEGER distance_to_move, LARGE_INTEGER *new_file_pointer, DWORD move_method); GB_DLL_IMPORT BOOL WINAPI ReadFile (HANDLE file, void *buffer, DWORD bytes_to_read, DWORD *bytes_read, OVERLAPPED *overlapped); @@ -3643,8 +3647,9 @@ gb_inline void *gb_memcopy(void *dest, void const *source, isize n) { u8 const *s = cast(u8 const *)source; u32 w, x; - for (; cast(uintptr)s % 4 && n; n--) + for (; cast(uintptr)s % 4 && n; n--) { *d++ = *s++; + } if (cast(uintptr)d % 4 == 0) { for (; n >= 16; @@ -5434,8 +5439,9 @@ GB_ALLOCATOR_PROC(gb_pool_allocator_proc) { gb_inline gbAllocationHeader *gb_allocation_header(void *data) { isize *p = cast(isize *)data; - while (p[-1] == cast(isize)(-1)) + while (p[-1] == cast(isize)(-1)) { p--; + } return cast(gbAllocationHeader *)p - 1; } @@ -5443,8 +5449,9 @@ gb_inline void gb_allocation_header_fill(gbAllocationHeader *header, void *data, isize *ptr; header->size = size; ptr = cast(isize *)(header + 1); - while (cast(void *)ptr < data) + while (cast(void *)ptr < data) { *ptr++ = cast(isize)(-1); + } } @@ -5887,8 +5894,9 @@ void gb_shuffle(void *base, isize count, isize size) { void gb_reverse(void *base, isize count, isize size) { isize i, j = count-1; - for (i = 0; i < j; i++, j++) + for (i = 0; i < j; i++, j++) { gb_memswap(cast(u8 *)base + i*size, cast(u8 *)base + j*size, size); + } } @@ -5993,18 +6001,21 @@ gb_inline isize gb_strlen(char const *str) { str++; } w = cast(isize const *)str; - while (!GB__HAS_ZERO(*w)) + while (!GB__HAS_ZERO(*w)) { w++; + } str = cast(char const *)w; - while (*str) + while (*str) { str++; + } return str - begin; } gb_inline isize gb_strnlen(char const *str, isize max_len) { char const *end = cast(char const *)gb_memchr(str, 0, max_len); - if (end) + if (end) { return end - str; + } return max_len; } @@ -6113,18 +6124,20 @@ gb_inline char *gb_strrev(char *str) { gb_inline i32 gb_strncmp(char const *s1, char const *s2, isize len) { for (; len > 0; s1++, s2++, len--) { - if (*s1 != *s2) + if (*s1 != *s2) { return ((s1 < s2) ? -1 : +1); - else if (*s1 == '\0') + } else if (*s1 == '\0') { return 0; + } } return 0; } gb_inline char const *gb_strtok(char *output, char const *src, char const *delimit) { - while (*src && gb_char_first_occurence(delimit, *src) != NULL) + while (*src && gb_char_first_occurence(delimit, *src) != NULL) { *output++ = *src++; + } *output = 0; return *src ? src+1 : src; @@ -6132,8 +6145,9 @@ gb_inline char const *gb_strtok(char *output, char const *src, char const *delim gb_inline b32 gb_str_has_prefix(char const *str, char const *prefix) { while (*prefix) { - if (*str++ != *prefix++) + if (*str++ != *prefix++) { return false; + } } return true; } @@ -6141,8 +6155,9 @@ gb_inline b32 gb_str_has_prefix(char const *str, char const *prefix) { gb_inline b32 gb_str_has_suffix(char const *str, char const *suffix) { isize i = gb_strlen(str); isize j = gb_strlen(suffix); - if (j <= i) + if (j <= i) { return gb_strcmp(str+i-j, suffix) == 0; + } return false; } @@ -6152,8 +6167,9 @@ gb_inline b32 gb_str_has_suffix(char const *str, char const *suffix) { gb_inline char const *gb_char_first_occurence(char const *s, char c) { char ch = c; for (; *s != ch; s++) { - if (*s == '\0') + if (*s == '\0') { return NULL; + } } return s; } @@ -6162,8 +6178,9 @@ gb_inline char const *gb_char_first_occurence(char const *s, char c) { gb_inline char const *gb_char_last_occurence(char const *s, char c) { char const *result = NULL; do { - if (*s == c) + if (*s == c) { result = s; + } } while (*s++); return result; @@ -6193,17 +6210,19 @@ gb_internal isize gb__scan_i64(char const *text, i32 base, i64 *value) { text++; } - if (base == 16 && gb_strncmp(text, "0x", 2) == 0) + if (base == 16 && gb_strncmp(text, "0x", 2) == 0) { text += 2; + } for (;;) { i64 v; - if (gb_char_is_digit(*text)) + if (gb_char_is_digit(*text)) { v = *text - '0'; - else if (base == 16 && gb_char_is_hex_digit(*text)) + } else if (base == 16 && gb_char_is_hex_digit(*text)) { v = gb_hex_digit_to_int(*text); - else + } else { break; + } result *= base; result += v; @@ -6222,16 +6241,17 @@ gb_internal isize gb__scan_u64(char const *text, i32 base, u64 *value) { char const *text_begin = text; u64 result = 0; - if (base == 16 && gb_strncmp(text, "0x", 2) == 0) + if (base == 16 && gb_strncmp(text, "0x", 2) == 0) { text += 2; + } for (;;) { u64 v; - if (gb_char_is_digit(*text)) + if (gb_char_is_digit(*text)) { v = *text - '0'; - else if (base == 16 && gb_char_is_hex_digit(*text)) + } else if (base == 16 && gb_char_is_hex_digit(*text)) { v = gb_hex_digit_to_int(*text); - else { + } else { break; } @@ -6240,9 +6260,7 @@ gb_internal isize gb__scan_u64(char const *text, i32 base, u64 *value) { text++; } - if (value) - *value = result; - + if (value) *value = result; return (text - text_begin); } @@ -6253,15 +6271,15 @@ u64 gb_str_to_u64(char const *str, char **end_ptr, i32 base) { u64 value = 0; if (!base) { - if ((gb_strlen(str) > 2) && (gb_strncmp(str, "0x", 2) == 0)) + if ((gb_strlen(str) > 2) && (gb_strncmp(str, "0x", 2) == 0)) { base = 16; - else + } else { base = 10; + } } len = gb__scan_u64(str, base, &value); - if (end_ptr) - *end_ptr = (char *)str + len; + if (end_ptr) *end_ptr = (char *)str + len; return value; } @@ -6270,15 +6288,15 @@ i64 gb_str_to_i64(char const *str, char **end_ptr, i32 base) { i64 value; if (!base) { - if ((gb_strlen(str) > 2) && (gb_strncmp(str, "0x", 2) == 0)) + if ((gb_strlen(str) > 2) && (gb_strncmp(str, "0x", 2) == 0)) { base = 16; - else + } else { base = 10; + } } len = gb__scan_i64(str, base, &value); - if (end_ptr) - *end_ptr = (char *)str + len; + if (end_ptr) *end_ptr = (char *)str + len; return value; } @@ -6424,8 +6442,9 @@ gbString gb_string_make_length(gbAllocator a, void const *init_str, isize num_by header->allocator = a; header->length = num_bytes; header->capacity = num_bytes; - if (num_bytes && init_str) + if (num_bytes && init_str) { gb_memcopy(str, init_str, num_bytes); + } str[num_bytes] = '\0'; return str; @@ -6446,8 +6465,9 @@ gb_inline isize gb_string_capacity(gbString const str) { return GB_STRING_HEADER gb_inline isize gb_string_available_space(gbString const str) { gbStringHeader *h = GB_STRING_HEADER(str); - if (h->capacity > h->length) + if (h->capacity > h->length) { return h->capacity - h->length; + } return 0; } @@ -6461,8 +6481,9 @@ gbString gb_string_append_length(gbString str, void const *other, isize other_le isize curr_len = gb_string_length(str); str = gb_string_make_space_for(str, other_len); - if (str == NULL) + if (str == NULL) { return NULL; + } gb_memcopy(str + curr_len, other, other_len); str[curr_len + other_len] = '\0'; @@ -6480,8 +6501,9 @@ gbString gb_string_set(gbString str, char const *cstr) { isize len = gb_strlen(cstr); if (gb_string_capacity(str) < len) { str = gb_string_make_space_for(str, len - gb_string_length(str)); - if (str == NULL) + if (str == NULL) { return NULL; + } } gb_memcopy(str, cstr, len); @@ -6533,12 +6555,14 @@ gb_inline b32 gb_string_are_equal(gbString const lhs, gbString const rhs) { isize lhs_len, rhs_len, i; lhs_len = gb_string_length(lhs); rhs_len = gb_string_length(rhs); - if (lhs_len != rhs_len) + if (lhs_len != rhs_len) { return false; + } for (i = 0; i < lhs_len; i++) { - if (lhs[i] != rhs[i]) + if (lhs[i] != rhs[i]) { return false; + } } return true; @@ -6552,10 +6576,12 @@ gbString gb_string_trim(gbString str, char const *cut_set) { start_pos = start = str; end_pos = end = str + gb_string_length(str) - 1; - while (start_pos <= end && gb_char_first_occurence(cut_set, *start_pos)) + while (start_pos <= end && gb_char_first_occurence(cut_set, *start_pos)) { start_pos++; - while (end_pos > start_pos && gb_char_first_occurence(cut_set, *end_pos)) + } + while (end_pos > start_pos && gb_char_first_occurence(cut_set, *end_pos)) { end_pos--; + } len = cast(isize)((start_pos > end_pos) ? 0 : ((end_pos - start_pos)+1)); @@ -6909,8 +6935,9 @@ u32 gb_adler32(void const *data, isize len) { bytes += 8; } - for (; i < block_len; i++) + for (; i < block_len; i++) { a += *bytes++, b += a; + } a %= MOD_ALDER, b %= MOD_ALDER; len -= block_len; @@ -7059,8 +7086,9 @@ u32 gb_crc32(void const *data, isize len) { isize remaining; u32 result = ~(cast(u32)0); u8 const *c = cast(u8 const *)data; - for (remaining = len; remaining--; c++) + for (remaining = len; remaining--; c++) { result = (result >> 8) ^ (GB__CRC32_TABLE[(result ^ *c) & 0xff]); + } return ~result; } @@ -7068,8 +7096,9 @@ u64 gb_crc64(void const *data, isize len) { isize remaining; u64 result = ~(cast(u64)0); u8 const *c = cast(u8 const *)data; - for (remaining = len; remaining--; c++) + for (remaining = len; remaining--; c++) { result = (result >> 8) ^ (GB__CRC64_TABLE[(result ^ *c) & 0xff]); + } return ~result; } @@ -7078,8 +7107,9 @@ u32 gb_fnv32(void const *data, isize len) { u32 h = 0x811c9dc5; u8 const *c = cast(u8 const *)data; - for (i = 0; i < len; i++) + for (i = 0; i < len; i++) { h = (h * 0x01000193) ^ c[i]; + } return h; } @@ -7089,8 +7119,9 @@ u64 gb_fnv64(void const *data, isize len) { u64 h = 0xcbf29ce484222325ull; u8 const *c = cast(u8 const *)data; - for (i = 0; i < len; i++) + for (i = 0; i < len; i++) { h = (h * 0x100000001b3ll) ^ c[i]; + } return h; } @@ -7100,8 +7131,9 @@ u32 gb_fnv32a(void const *data, isize len) { u32 h = 0x811c9dc5; u8 const *c = cast(u8 const *)data; - for (i = 0; i < len; i++) + for (i = 0; i < len; i++) { h = (h ^ c[i]) * 0x01000193; + } return h; } @@ -7111,8 +7143,9 @@ u64 gb_fnv64a(void const *data, isize len) { u64 h = 0xcbf29ce484222325ull; u8 const *c = cast(u8 const *)data; - for (i = 0; i < len; i++) + for (i = 0; i < len; i++) { h = (h ^ c[i]) * 0x100000001b3ll; + } return h; } @@ -7280,6 +7313,36 @@ u64 gb_murmur64_seed(void const *data_, isize len, u64 seed) { // #if defined(GB_SYSTEM_WINDOWS) + + gb_internal wchar_t *gb__alloc_utf8_to_ucs2(gbAllocator a, char const *text, isize *w_len_) { + wchar_t *w_text = NULL; + isize len = 0, w_len = 0, w_len1 = 0; + if (text == NULL) { + if (w_len_) *w_len_ = w_len; + return NULL; + } + len = gb_strlen(text); + if (len == 0) { + if (w_len_) *w_len_ = w_len; + return NULL; + } + w_len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, text, len, NULL, 0); + if (w_len == 0) { + if (w_len_) *w_len_ = w_len; + return NULL; + } + w_text = gb_alloc_array(a, wchar_t, w_len+1); + w_len1 = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, text, len, w_text, w_len); + if (w_len1 == 0) { + gb_free(a, w_text); + if (w_len_) *w_len_ = 0; + return NULL; + } + w_text[w_len] = 0; + if (w_len_) *w_len_ = w_len; + return w_text; + } + gb_internal GB_FILE_SEEK_PROC(gb__win32_file_seek) { LARGE_INTEGER li_offset; li_offset.QuadPart = offset; @@ -7330,7 +7393,7 @@ u64 gb_murmur64_seed(void const *data_, isize len, u64 seed) { DWORD desired_access; DWORD creation_disposition; void *handle; - u16 path[1024] = {0}; // TODO(bill): Is this really enough or should I heap allocate this if it's too large? + wchar_t *w_text; switch (mode & gbFileMode_Modes) { case gbFileMode_Read: @@ -7362,11 +7425,17 @@ u64 gb_murmur64_seed(void const *data_, isize len, u64 seed) { return gbFileError_Invalid; } - handle = CreateFileW(cast(wchar_t const *)gb_utf8_to_ucs2(path, gb_count_of(path), cast(u8 *)filename), + w_text = gb__alloc_utf8_to_ucs2(gb_heap_allocator(), filename, NULL); + if (w_text == NULL) { + return gbFileError_InvalidFilename; + } + handle = CreateFileW(w_text, desired_access, FILE_SHARE_READ|FILE_SHARE_DELETE, NULL, creation_disposition, FILE_ATTRIBUTE_NORMAL, NULL); + gb_free(gb_heap_allocator(), w_text); + if (handle == INVALID_HANDLE_VALUE) { DWORD err = GetLastError(); switch (err) { @@ -7497,23 +7566,27 @@ gbFileError gb_file_open_mode(gbFile *f, gbFileMode mode, char const *filename) #else err = gb__posix_file_open(&f->fd, &f->ops, mode, filename); #endif - if (err == gbFileError_None) + if (err == gbFileError_None) { return gb_file_new(f, f->fd, f->ops, filename); + } return err; } gbFileError gb_file_close(gbFile *f) { - if (!f) + if (!f) { return gbFileError_Invalid; + } if (f->filename) gb_free(gb_heap_allocator(), cast(char *)f->filename); #if defined(GB_SYSTEM_WINDOWS) - if (f->fd.p == INVALID_HANDLE_VALUE) + if (f->fd.p == INVALID_HANDLE_VALUE) { return gbFileError_Invalid; + } #else - if (f->fd.i < 0) + if (f->fd.i < 0) { return gbFileError_Invalid; + } #endif if (!f->ops.read_at) f->ops = gbDefaultFileOperations; @@ -7624,8 +7697,9 @@ gbFileError gb_file_truncate(gbFile *f, i64 size) { gbFileError err = gbFileError_None; i64 prev_offset = gb_file_tell(f); gb_file_seek(f, size); - if (!SetEndOfFile(f)) + if (!SetEndOfFile(f)) { err = gbFileError_TruncationFailure; + } gb_file_seek(f, prev_offset); return err; } @@ -7633,8 +7707,18 @@ gbFileError gb_file_truncate(gbFile *f, i64 size) { b32 gb_file_exists(char const *name) { WIN32_FIND_DATAW data; - void *handle = FindFirstFileW(cast(wchar_t const *)gb_utf8_to_ucs2_buf(cast(u8 *)name), &data); - b32 found = handle != INVALID_HANDLE_VALUE; + wchar_t *w_text; + void *handle; + b32 found = false; + gbAllocator a = gb_heap_allocator(); + + w_text = gb__alloc_utf8_to_ucs2(a, name, NULL); + if (w_text == NULL) { + return false; + } + handle = FindFirstFileW(w_text, &data); + gb_free(a, w_text); + found = handle != INVALID_HANDLE_VALUE; if (found) FindClose(handle); return found; } @@ -7678,14 +7762,20 @@ gb_inline b32 gb_file_exists(char const *name) { #if defined(GB_SYSTEM_WINDOWS) gbFileTime gb_file_last_write_time(char const *filepath) { - u16 path[1024] = {0}; ULARGE_INTEGER li = {0}; FILETIME last_write_time = {0}; WIN32_FILE_ATTRIBUTE_DATA data = {0}; + gbAllocator a = gb_heap_allocator(); - if (GetFileAttributesExW(cast(wchar_t const *)gb_utf8_to_ucs2(path, gb_count_of(path), cast(u8 *)filepath), - GetFileExInfoStandard, &data)) + wchar_t *w_text = gb__alloc_utf8_to_ucs2(a, filepath, NULL); + if (w_text == NULL) { + return 0; + } + + if (GetFileAttributesExW(w_text, GetFileExInfoStandard, &data)) { last_write_time = data.ftLastWriteTime; + } + gb_free(a, w_text); li.LowPart = last_write_time.dwLowDateTime; li.HighPart = last_write_time.dwHighDateTime; @@ -7694,20 +7784,41 @@ gbFileTime gb_file_last_write_time(char const *filepath) { gb_inline b32 gb_file_copy(char const *existing_filename, char const *new_filename, b32 fail_if_exists) { - u16 old_f[300] = {0}; - u16 new_f[300] = {0}; + wchar_t *w_old = NULL; + wchar_t *w_new = NULL; + gbAllocator a = gb_heap_allocator(); + b32 result = false; - return CopyFileW(cast(wchar_t const *)gb_utf8_to_ucs2(old_f, gb_count_of(old_f), cast(u8 *)existing_filename), - cast(wchar_t const *)gb_utf8_to_ucs2(new_f, gb_count_of(new_f), cast(u8 *)new_filename), - fail_if_exists); + w_old = gb__alloc_utf8_to_ucs2(a, existing_filename, NULL); + if (w_old == NULL) { + return false; + } + w_new = gb__alloc_utf8_to_ucs2(a, new_filename, NULL); + if (w_new != NULL) { + result = CopyFileW(w_old, w_new, fail_if_exists); + } + gb_free(a, w_new); + gb_free(a, w_old); + return result; } gb_inline b32 gb_file_move(char const *existing_filename, char const *new_filename) { - u16 old_f[300] = {0}; - u16 new_f[300] = {0}; + wchar_t *w_old = NULL; + wchar_t *w_new = NULL; + gbAllocator a = gb_heap_allocator(); + b32 result = false; - return MoveFileW(cast(wchar_t const *)gb_utf8_to_ucs2(old_f, gb_count_of(old_f), cast(u8 *)existing_filename), - cast(wchar_t const *)gb_utf8_to_ucs2(new_f, gb_count_of(new_f), cast(u8 *)new_filename)); + w_old = gb__alloc_utf8_to_ucs2(a, existing_filename, NULL); + if (w_old == NULL) { + return false; + } + w_new = gb__alloc_utf8_to_ucs2(a, new_filename, NULL); + if (w_new != NULL) { + result = MoveFileW(w_old, w_new); + } + gb_free(a, w_new); + gb_free(a, w_old); + return result; } @@ -7718,8 +7829,9 @@ gbFileTime gb_file_last_write_time(char const *filepath) { time_t result = 0; struct stat file_stat; - if (stat(filepath, &file_stat)) + if (stat(filepath, &file_stat)) { result = file_stat.st_mtime; + } return cast(gbFileTime)result; } @@ -7747,8 +7859,9 @@ gb_inline b32 gb_file_copy(char const *existing_filename, char const *new_filena gb_inline b32 gb_file_move(char const *existing_filename, char const *new_filename) { if (link(existing_filename, new_filename) == 0) { - if (unlink(existing_filename) != -1) + if (unlink(existing_filename) != -1) { return true; + } } return false; } @@ -7836,14 +7949,45 @@ gb_inline char const *gb_path_extension(char const *path) { #if !defined(_WINDOWS_) && defined(GB_SYSTEM_WINDOWS) GB_DLL_IMPORT DWORD WINAPI GetFullPathNameA(char const *lpFileName, DWORD nBufferLength, char *lpBuffer, char **lpFilePart); +GB_DLL_IMPORT DWORD WINAPI GetFullPathNameW(wchar_t const *lpFileName, DWORD nBufferLength, wchar_t *lpBuffer, wchar_t **lpFilePart); #endif char *gb_path_get_full_name(gbAllocator a, char const *path) { #if defined(GB_SYSTEM_WINDOWS) // TODO(bill): Make UTF-8 - char buf[300]; - isize len = GetFullPathNameA(path, gb_count_of(buf), buf, NULL); - return gb_alloc_str_len(a, buf, len+1); + wchar_t *w_path = NULL; + wchar_t *w_fullpath = NULL; + isize w_len = 0; + isize new_len = 0; + isize new_len1 = 0; + char *new_path = 0; + w_path = gb__alloc_utf8_to_ucs2(gb_heap_allocator(), path, NULL); + if (w_path == NULL) { + return NULL; + } + w_len = GetFullPathNameW(w_path, 0, NULL, NULL); + if (w_len == 0) { + return NULL; + } + w_fullpath = gb_alloc_array(gb_heap_allocator(), wchar_t, w_len+1); + GetFullPathNameW(w_path, w_len, w_fullpath, NULL); + w_fullpath[w_len] = 0; + gb_free(gb_heap_allocator(), w_path); + + new_len = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, w_fullpath, w_len, NULL, 0, NULL, NULL); + if (new_len == 0) { + gb_free(gb_heap_allocator(), w_fullpath); + return NULL; + } + new_path = gb_alloc_array(a, char, new_len+1); + new_len1 = WideCharToMultiByte(CP_UTF8, WC_ERR_INVALID_CHARS, w_fullpath, w_len, new_path, new_len, NULL, NULL); + if (new_len1 == 0) { + gb_free(gb_heap_allocator(), w_fullpath); + gb_free(a, new_path); + return NULL; + } + new_path[new_len] = 0; + return new_path; #else // TODO(bill): Make work on *nix, etc. char* p = realpath(path, 0); @@ -7982,29 +8126,33 @@ gb_internal isize gb__print_string(char *text, isize max_len, gbprivFmtInfo *inf isize res = 0, len; isize remaining = max_len; - if (info && info->precision >= 0) + if (info && info->precision >= 0) { len = gb_strnlen(str, info->precision); - else + } else { len = gb_strlen(str); + } if (info && (info->width == 0 || info->flags & gbFmt_Minus)) { - if (info->precision > 0) + if (info->precision > 0) { len = info->precision < len ? info->precision : len; + } res += gb_strlcpy(text, str, len); if (info->width > res) { isize padding = info->width - len; char pad = (info->flags & gbFmt_Zero) ? '0' : ' '; - while (padding --> 0 && remaining --> 0) + while (padding --> 0 && remaining --> 0) { *text++ = pad, res++; + } } } else { if (info && (info->width > res)) { isize padding = info->width - len; char pad = (info->flags & gbFmt_Zero) ? '0' : ' '; - while (padding --> 0 && remaining --> 0) + while (padding --> 0 && remaining --> 0) { *text++ = pad, res++; + } } res += gb_strlcpy(text, str, len); @@ -8012,10 +8160,11 @@ gb_internal isize gb__print_string(char *text, isize max_len, gbprivFmtInfo *inf if (info) { - if (info->flags & gbFmt_Upper) + if (info->flags & gbFmt_Upper) { gb_str_to_upper(text); - else if (info->flags & gbFmt_Lower) + } else if (info->flags & gbFmt_Lower) { gb_str_to_lower(text); + } } return res; @@ -8049,13 +8198,15 @@ gb_internal isize gb__print_f64(char *text, isize max_len, gbprivFmtInfo *info, if (arg) { u64 value; if (arg < 0) { - if (remaining > 1) + if (remaining > 1) { *text = '-', remaining--; + } text++; arg = -arg; } else if (info->flags & gbFmt_Minus) { - if (remaining > 1) + if (remaining > 1) { *text = '+', remaining--; + } text++; } @@ -8063,39 +8214,45 @@ gb_internal isize gb__print_f64(char *text, isize max_len, gbprivFmtInfo *info, len = gb__print_u64(text, remaining, NULL, value); text += len; - if (len >= remaining) + if (len >= remaining) { remaining = gb_min(remaining, 1); - else + } else { remaining -= len; + } arg -= value; - if (info->precision < 0) + if (info->precision < 0) { info->precision = 6; + } if ((info->flags & gbFmt_Alt) || info->precision > 0) { i64 mult = 10; - if (remaining > 1) + if (remaining > 1) { *text = '.', remaining--; + } text++; while (info->precision-- > 0) { value = cast(u64)(arg * mult); len = gb__print_u64(text, remaining, NULL, value); text += len; - if (len >= remaining) + if (len >= remaining) { remaining = gb_min(remaining, 1); - else + } else { remaining -= len; + } arg -= cast(f64)value / mult; mult *= 10; } } } else { - if (remaining > 1) + if (remaining > 1) { *text = '0', remaining--; + } text++; if (info->flags & gbFmt_Alt) { - if (remaining > 1) + if (remaining > 1) { *text = '.', remaining--; + } text++; } } @@ -8107,20 +8264,23 @@ gb_internal isize gb__print_f64(char *text, isize max_len, gbprivFmtInfo *info, len = (text - text_begin); for (len = (text - text_begin); len--; ) { - if ((text_begin+len+width) < end) + if ((text_begin+len+width) < end) { *(text_begin+len+width) = *(text_begin+len); + } } len = width; text += len; - if (len >= remaining) + if (len >= remaining) { remaining = gb_min(remaining, 1); - else + } else { remaining -= len; + } while (len--) { - if (text_begin+len < end) + if (text_begin+len < end) { text_begin[len] = fill; + } } } @@ -8138,8 +8298,9 @@ gb_no_inline isize gb_snprintf_va(char *text, isize max_len, char const *fmt, va isize len = 0; info.precision = -1; - while (*fmt && *fmt != '%' && remaining) + while (*fmt && *fmt != '%' && remaining) { *text++ = *fmt++; + } if (*fmt == '%') { do { @@ -8303,10 +8464,11 @@ gb_no_inline isize gb_snprintf_va(char *text, isize max_len, char const *fmt, va text += len; - if (len >= remaining) + if (len >= remaining) { remaining = gb_min(remaining, 1); - else + } else { remaining -= len; + } } *text++ = '\0'; @@ -8504,10 +8666,11 @@ gb_internal gb_inline u32 gb__permute_qpr(u32 x) { return x; } else { u32 residue = cast(u32)(cast(u64) x * x) % prime; - if (x <= prime / 2) + if (x <= prime / 2) { return residue; - else + } else { return prime - residue; + } } } @@ -8734,10 +8897,11 @@ GB_XINPUT_SET_STATE(gbXInputSetState_Stub) { gb_internal gb_inline f32 gb__process_xinput_stick_value(i16 value, i16 dead_zone_threshold) { f32 result = 0; - if (value < -dead_zone_threshold) + if (value < -dead_zone_threshold) { result = cast(f32) (value + dead_zone_threshold) / (32768.0f - dead_zone_threshold); - else if (value > dead_zone_threshold) + } else if (value > dead_zone_threshold) { result = cast(f32) (value - dead_zone_threshold) / (32767.0f - dead_zone_threshold); + } return result; } @@ -8747,8 +8911,9 @@ gb_internal void gb__platform_resize_dib_section(gbPlatform *p, i32 width, i32 h !(p->window_width == width && p->window_height == height)) { BITMAPINFO bmi = {0}; - if (width == 0 || height == 0) + if (width == 0 || height == 0) { return; + } p->window_width = width; p->window_height = height; @@ -8767,8 +8932,9 @@ gb_internal void gb__platform_resize_dib_section(gbPlatform *p, i32 width, i32 h p->sw_framebuffer.win32_bmi = bmi; - if (p->sw_framebuffer.memory) + if (p->sw_framebuffer.memory) { gb_vm_free(gb_virtual_memory(p->sw_framebuffer.memory, p->sw_framebuffer.memory_size)); + } { isize memory_size = p->sw_framebuffer.pitch * height; @@ -8892,8 +9058,9 @@ LRESULT CALLBACK gb__win32_window_callback(HWND hWnd, UINT msg, WPARAM wParam, L } } - if (!platform) + if (!platform) { return DefWindowProcW(hWnd, msg, wParam, lParam); + } switch (msg) { case WM_CLOSE: @@ -8907,8 +9074,9 @@ LRESULT CALLBACK gb__win32_window_callback(HWND hWnd, UINT msg, WPARAM wParam, L case WM_UNICHAR: { if (window_has_focus) { - if (wParam == '\r') + if (wParam == '\r') { wParam = '\n'; + } // TODO(bill): Does this need to be thread-safe? platform->char_buffer[platform->char_buffer_count++] = cast(Rune)wParam; } @@ -8953,10 +9121,11 @@ LRESULT CALLBACK gb__win32_window_callback(HWND hWnd, UINT msg, WPARAM wParam, L if (is_e1) { // NOTE(bill): Escaped sequences, turn vk into the correct scan code // except for VK_PAUSE (it's a bug) - if (vk == VK_PAUSE) + if (vk == VK_PAUSE) { scan_code = 0x45; - else + } else { scan_code = MapVirtualKeyW(vk, MAPVK_VK_TO_VSC); + } } switch (vk) { @@ -8992,8 +9161,9 @@ LRESULT CALLBACK gb__win32_window_callback(HWND hWnd, UINT msg, WPARAM wParam, L long dx = +raw_mouse->lLastX; long dy = -raw_mouse->lLastY; - if (flags & RI_MOUSE_WHEEL) + if (flags & RI_MOUSE_WHEEL) { platform->mouse_wheel_delta = cast(i16)raw_mouse->usButtonData; + } platform->mouse_raw_dx = dx; platform->mouse_raw_dy = dy; @@ -9277,8 +9447,9 @@ void gb_platform_update(gbPlatform *p) { h = window_rect.bottom - window_rect.top; if ((p->window_width != w) || (p->window_height != h)) { - if (p->renderer_type == gbRenderer_Software) + if (p->renderer_type == gbRenderer_Software) { gb__platform_resize_dib_section(p, w, h); + } } @@ -9303,8 +9474,9 @@ void gb_platform_update(gbPlatform *p) { // NOTE(bill): This needs to be GetAsyncKeyState as RAWMOUSE doesn't aways work for some odd reason // TODO(bill): Try and get RAWMOUSE to work for key presses - for (i = 0; i < gbMouseButton_Count; i++) + for (i = 0; i < gbMouseButton_Count; i++) { gb_key_state_update(p->mouse_buttons+i, GetAsyncKeyState(win_button_id[i]) < 0); + } GetCursorPos(&mouse_pos); ScreenToClient(cast(HWND)p->window_handle, &mouse_pos); @@ -9337,8 +9509,9 @@ void gb_platform_update(gbPlatform *p) { update = true; } - if (update) + if (update) { gb_platform_set_mouse_position(p, x, y); + } } @@ -9363,8 +9536,9 @@ void gb_platform_update(gbPlatform *p) { { // NOTE(bill): Set Controller states isize max_controller_count = XUSER_MAX_COUNT; - if (max_controller_count > gb_count_of(p->game_controllers)) + if (max_controller_count > gb_count_of(p->game_controllers)) { max_controller_count = gb_count_of(p->game_controllers); + } for (i = 0; i < max_controller_count; i++) { gbGameController *controller = &p->game_controllers[i]; @@ -9460,10 +9634,11 @@ void gb_platform_display(gbPlatform *p) { void gb_platform_destroy(gbPlatform *p) { - if (p->renderer_type == gbRenderer_Opengl) + if (p->renderer_type == gbRenderer_Opengl) { wglDeleteContext(cast(HGLRC)p->opengl.context); - else if (p->renderer_type == gbRenderer_Software) + } else if (p->renderer_type == gbRenderer_Software) { gb_vm_free(gb_virtual_memory(p->sw_framebuffer.memory, p->sw_framebuffer.memory_size)); + } DestroyWindow(cast(HWND)p->window_handle); } @@ -9517,8 +9692,9 @@ void gb_platform_set_window_title(gbPlatform *p, char const *title, ...) { gb_snprintf_va(str, gb_size_of(str), title, va); va_end(va); - if (str[0] != '\0') + if (str[0] != '\0') { SetWindowTextW(cast(HWND)p->window_handle, cast(wchar_t const *)gb_utf8_to_ucs2(buffer, gb_size_of(buffer), str)); + } } void gb_platform_toggle_fullscreen(gbPlatform *p, b32 fullscreen_desktop) { @@ -9543,10 +9719,11 @@ void gb_platform_toggle_fullscreen(gbPlatform *p, b32 fullscreen_desktop) { monitor_info.rcMonitor.bottom - monitor_info.rcMonitor.top, SWP_NOOWNERZORDER | SWP_FRAMECHANGED); - if (fullscreen_desktop) + if (fullscreen_desktop) { p->window_flags |= gbWindow_FullscreenDesktop; - else + } else { p->window_flags |= gbWindow_Fullscreen; + } } } else { style &= ~WS_POPUP; @@ -9621,8 +9798,9 @@ b32 gb_platform_has_clipboard_text(gbPlatform *p) { HANDLE mem = GetClipboardData(1/*CF_TEXT*/); if (mem) { char *str = cast(char *)GlobalLock(mem); - if (str && str[0] != '\0') + if (str && str[0] != '\0') { result = true; + } GlobalUnlock(mem); } else { return false; @@ -9657,8 +9835,9 @@ void gb_platform_set_clipboard_text(gbPlatform *p, char const *str) { } EmptyClipboard(); - if (!SetClipboardData(1/*CF_TEXT*/, mem)) + if (!SetClipboardData(1/*CF_TEXT*/, mem)) { return; + } CloseClipboard(); } } @@ -9751,8 +9930,9 @@ gb_internal void gb__osx_window_did_become_key(id self, SEL _sel, id notificatio } b32 gb__platform_init(gbPlatform *p, char const *window_title, gbVideoMode mode, gbRendererType type, u32 window_flags) { - if (p->is_initialized) + if (p->is_initialized) { return true; + } // Init Platform { // Initial OSX State Class appDelegateClass; @@ -10235,8 +10415,9 @@ void gb_platform_update(gbPlatform *p) { update = true; } - if (update) + if (update) { gb_platform_set_mouse_position(p, x, y); + } } } @@ -10441,8 +10622,9 @@ GB_COMPARE_PROC(gb_video_mode_cmp) { gbVideoMode const *y = cast(gbVideoMode const *)b; if (x->bits_per_pixel == y->bits_per_pixel) { - if (x->width == y->width) + if (x->width == y->width) { return x->height < y->height ? -1 : x->height > y->height; + } return x->width < y->width ? -1 : x->width > y->width; } return x->bits_per_pixel < y->bits_per_pixel ? -1 : +1; diff --git a/src/ir.c b/src/ir.c index 44f24d5d6..9d44d0188 100644 --- a/src/ir.c +++ b/src/ir.c @@ -1328,8 +1328,8 @@ irDebugInfo *ir_add_debug_info_proc(irProcedure *proc, Entity *entity, String na irValue *ir_emit_store(irProcedure *p, irValue *address, irValue *value) { #if 1 // NOTE(bill): Sanity check - Type *a = base_type(base_enum_type(type_deref(ir_type(address)))); - Type *b = base_type(base_enum_type(ir_type(value))); + Type *a = core_type(type_deref(ir_type(address))); + Type *b = core_type(ir_type(value)); if (!is_type_untyped(b)) { GB_ASSERT_MSG(are_types_identical(a, b), "%s %s", type_to_string(a), type_to_string(b)); } @@ -2218,8 +2218,8 @@ irValue *ir_emit_conv(irProcedure *proc, irValue *value, Type *t) { return value; } - Type *src = base_type(base_enum_type(src_type)); - Type *dst = base_type(base_enum_type(t)); + Type *src = core_type(src_type); + Type *dst = core_type(t); // if (is_type_untyped_nil(src) && type_has_nil(dst)) { diff --git a/src/ir_print.c b/src/ir_print.c index a25eef288..973b3d6a0 100644 --- a/src/ir_print.c +++ b/src/ir_print.c @@ -306,7 +306,7 @@ void ir_print_compound_element(irFileBuffer *f, irModule *m, ExactValue v, Type } void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type *type) { - type = base_type(base_enum_type(type)); + type = core_type(type); if (is_type_float(type)) { value = exact_value_to_float(value); } else if (is_type_integer(type)) { diff --git a/src/parser.c b/src/parser.c index 2905489d6..d80e2380d 100644 --- a/src/parser.c +++ b/src/parser.c @@ -402,7 +402,6 @@ String const ast_node_strings[] = { typedef struct AstNode { AstNodeKind kind; - // AstNode *prev, *next; // NOTE(bill): allow for Linked list u32 stmt_state_flags; union { #define AST_NODE_KIND(_kind_name_, name, ...) GB_JOIN2(AstNode, _kind_name_) _kind_name_; @@ -414,7 +413,9 @@ typedef struct AstNode { #define ast_node(n_, Kind_, node_) GB_JOIN2(AstNode, Kind_) *n_ = &(node_)->Kind_; GB_ASSERT((node_)->kind == GB_JOIN2(AstNode_, Kind_)) #define case_ast_node(n_, Kind_, node_) case GB_JOIN2(AstNode_, Kind_): { ast_node(n_, Kind_, node_); +#ifndef case_end #define case_end } break; +#endif gb_inline bool is_ast_node_expr(AstNode *node) { @@ -3841,7 +3842,7 @@ ParseFileError parse_files(Parser *p, char *init_filename) { gb_printf_err("File permissions problem"); break; case ParseFile_NotFound: - gb_printf_err("File cannot be found"); + gb_printf_err("File cannot be found (`%.*s`)", LIT(import_path)); break; case ParseFile_InvalidToken: gb_printf_err("Invalid token found in file"); diff --git a/src/ssa.c b/src/ssa.c index 7bccf027d..67c16a1e4 100644 --- a/src/ssa.c +++ b/src/ssa.c @@ -1,6 +1,7 @@ typedef enum ssaOp ssaOp; typedef struct ssaModule ssaModule; typedef struct ssaValue ssaValue; +typedef struct ssaValueArgs ssaValueArgs; typedef struct ssaBlock ssaBlock; typedef struct ssaProc ssaProc; typedef struct ssaEdge ssaEdge; @@ -294,7 +295,15 @@ String const ssa_op_strings[] = { #undef SSA_OP }; -#define SSA_MAX_ARGS 4 + +#define SSA_DEFAULT_VALUE_ARG_CAPACITY 8 +struct ssaValueArgs { + ssaValue ** e; + isize count; + isize capacity; + ssaValue * backing[SSA_DEFAULT_VALUE_ARG_CAPACITY]; + gbAllocator allocator; +}; struct ssaValue { i32 id; // Unique identifier but the pointer could be used too @@ -303,13 +312,7 @@ struct ssaValue { ssaBlock * block; // Containing basic block i32 uses; - // Most values will only a few number of arguments - // Procedure calls may need a lot more so they will use the `var_args` parameter instead - ssaValue * args[SSA_MAX_ARGS]; - isize arg_count; - - ssaValueArray var_args; // Only used in procedure calls as the SSA_MAX_ARGS may be too small - + ssaValueArgs args; ExactValue exact_value; // Used for constants String comment_string; @@ -501,21 +504,29 @@ void ssa_emit_jump(ssaProc *p, ssaBlock *edge) { ssa_add_edge_to(ssa_end_block(p), edge); } - -bool ssa_op_uses_var_args(ssaOp op) { - switch (op) { - case ssaOp_CallOdin: - case ssaOp_CallC: - case ssaOp_CallStd: - case ssaOp_CallFast: - return true; - - case ssaOp_Phi: - return true; - } - return false; +void ssa_init_value_args(ssaValueArgs *va, gbAllocator a) { + va->e = va->backing; + va->count = 0; + va->capacity = gb_count_of(va->backing); + va->allocator = a; } +void ssa_add_arg(ssaValueArgs *va, ssaValue *arg) { + if (va->count >= va->capacity) { + isize capacity = 2*va->capacity; + if (va->e == va->backing) { // Replace the backing with an allocated version instead + ssaValue **new_args = gb_alloc_array(va->allocator, ssaValue *, capacity); + gb_memcopy_array(new_args, va->e, va->count); + va->e = new_args; + } else { + isize old_cap_size = va->capacity * gb_size_of(ssaValue *); + isize new_cap_size = capacity * gb_size_of(ssaValue *); + va->e = gb_resize(va->allocator, va->e, old_cap_size, new_cap_size); + } + va->capacity = capacity; + } + va->e[va->count++] = arg; arg->uses++; +} @@ -525,6 +536,7 @@ ssaValue *ssa_new_value(ssaProc *p, ssaOp op, Type *t, ssaBlock *b) { v->op = op; v->type = t; v->block = b; + ssa_init_value_args(&v->args, p->module->allocator); array_add(&b->values, v); return v; } @@ -541,7 +553,7 @@ ssaValue *ssa_new_value0v(ssaBlock *b, ssaOp op, Type *t, ExactValue exact_value ssaValue *ssa_new_value1(ssaBlock *b, ssaOp op, Type *t, ssaValue *arg) { ssaValue *v = ssa_new_value(b->proc, op, t, b); - v->args[v->arg_count++] = arg; arg->uses++; + ssa_add_arg(&v->args, arg); return v; } ssaValue *ssa_new_value1v(ssaBlock *b, ssaOp op, Type *t, ExactValue exact_value, ssaValue *arg) { @@ -552,8 +564,8 @@ ssaValue *ssa_new_value1v(ssaBlock *b, ssaOp op, Type *t, ExactValue exact_value ssaValue *ssa_new_value2(ssaBlock *b, ssaOp op, Type *t, ssaValue *arg0, ssaValue *arg1) { ssaValue *v = ssa_new_value(b->proc, op, t, b); - v->args[v->arg_count++] = arg0; arg0->uses++; - v->args[v->arg_count++] = arg1; arg1->uses++; + ssa_add_arg(&v->args, arg0); + ssa_add_arg(&v->args, arg1); return v; } ssaValue *ssa_new_value2v(ssaBlock *b, ssaOp op, Type *t, ExactValue exact_value, ssaValue *arg0, ssaValue *arg1) { @@ -564,9 +576,9 @@ ssaValue *ssa_new_value2v(ssaBlock *b, ssaOp op, Type *t, ExactValue exact_value ssaValue *ssa_new_value3(ssaBlock *b, ssaOp op, Type *t, ssaValue *arg0, ssaValue *arg1, ssaValue *arg2) { ssaValue *v = ssa_new_value(b->proc, op, t, b); - v->args[v->arg_count++] = arg0; arg0->uses++; - v->args[v->arg_count++] = arg1; arg1->uses++; - v->args[v->arg_count++] = arg2; arg2->uses++; + ssa_add_arg(&v->args, arg0); + ssa_add_arg(&v->args, arg1); + ssa_add_arg(&v->args, arg2); return v; } ssaValue *ssa_new_value3v(ssaBlock *b, ssaOp op, Type *t, ExactValue exact_value, ssaValue *arg0, ssaValue *arg1, ssaValue *arg2) { @@ -577,10 +589,10 @@ ssaValue *ssa_new_value3v(ssaBlock *b, ssaOp op, Type *t, ExactValue exact_value ssaValue *ssa_new_value4(ssaBlock *b, ssaOp op, Type *t, ssaValue *arg0, ssaValue *arg1, ssaValue *arg2, ssaValue *arg3) { ssaValue *v = ssa_new_value(b->proc, op, t, b); - v->args[v->arg_count++] = arg0; arg0->uses++; - v->args[v->arg_count++] = arg1; arg1->uses++; - v->args[v->arg_count++] = arg2; arg2->uses++; - v->args[v->arg_count++] = arg3; arg3->uses++; + ssa_add_arg(&v->args, arg0); + ssa_add_arg(&v->args, arg1); + ssa_add_arg(&v->args, arg2); + ssa_add_arg(&v->args, arg3); return v; } @@ -612,17 +624,10 @@ ssaValue *ssa_const_int(ssaProc *p, Type *t, i64 c) { } void ssa_reset_value_args(ssaValue *v) { - if (ssa_op_uses_var_args(v->op)) { - for_array(i, v->var_args) { - v->var_args.e[i]->uses--; - } - v->var_args.count = 0; - } else { - for (isize i = 0; i < v->arg_count; i++) { - v->args[i]->uses--; - } - v->arg_count = 0; + for_array(i, v->args) { + v->args.e[i]->uses--; } + v->args.count = 0; } @@ -721,6 +726,55 @@ void ssa_emit_comment(ssaProc *p, String s) { // ssa_new_value0v(p->curr_block, ssaOp_Comment, NULL, exact_value_string(s)); } +#define SSA_MAX_STRUCT_FIELD_COUNT 4 + +bool can_ssa_type(Type *t) { + i64 s = type_size_of(heap_allocator(), t); + if (s > 4*build_context.word_size) { + return false; + } + t = core_type(t); + + switch (t->kind) { + case Type_Array: + return t->Array.count == 0; + case Type_Vector: + return s < 2*build_context.word_size; + + case Type_DynamicArray: + return false; + case Type_Map: + return false; + case Type_Tuple: + if (t->Tuple.variable_count > SSA_MAX_STRUCT_FIELD_COUNT) { + return false; + } + for (isize i = 0; i < t->Tuple.variable_count; i++) { + if (!can_ssa_type(t->Tuple.variables[i]->type)) { + return false; + } + } + return true; + case Type_Record: + if (t->Record.kind == TypeRecord_Union) { + return false; + } else if (t->Record.kind == TypeRecord_Struct) { + if (t->Record.field_count > SSA_MAX_STRUCT_FIELD_COUNT) { + return false; + } + for (isize i = 0; i < t->Record.field_count; i++) { + if (!can_ssa_type(t->Record.fields[i]->type)) { + return false; + } + } + } + return true; + } + return true; +} + + + void ssa_build_stmt(ssaProc *p, AstNode *node); void ssa_build_stmt_list(ssaProc *p, AstNodeArray nodes); @@ -815,7 +869,7 @@ ssaAddr ssa_build_addr(ssaProc *p, AstNode *expr) { Type *ssa_proper_type(Type *t) { - t = default_type(base_type(base_enum_type(t))); + t = default_type(core_type(t)); if (t->kind == Type_Basic) { switch (t->Basic.kind) { @@ -1041,7 +1095,7 @@ ssaValue *ssa_build_expr(ssaProc *p, AstNode *expr) { GB_ASSERT_NOT_NULL(tv); if (tv->value.kind != ExactValue_Invalid) { - Type *t = base_type(base_enum_type(tv->type)); + Type *t = core_type(tv->type); if (is_type_boolean(t)) { return ssa_const_bool(p, tv->type, tv->value.value_bool); } else if (is_type_string(t)) { @@ -1675,16 +1729,9 @@ void ssa_print_reg_value(gbFile *f, ssaValue *v) { ssa_print_exact_value(f, v); - if (ssa_op_uses_var_args(v->op)) { - for_array(i, v->var_args) { - gb_fprintf(f, " "); - ssa_print_value(f, v->var_args.e[i]); - } - } else { - for (isize i = 0; i < v->arg_count; i++) { - gb_fprintf(f, " "); - ssa_print_value(f, v->args[i]); - } + for_array(i, v->args) { + gb_fprintf(f, " "); + ssa_print_value(f, v->args.e[i]); } if (v->comment_string.len > 0) { @@ -1733,21 +1780,11 @@ void ssa_print_proc(gbFile *f, ssaProc *p) { continue; } bool skip = false; - if (ssa_op_uses_var_args(v->op)) { - for_array(k, v->var_args) { - ssaValue *w = v->var_args.e[k]; - if (w != NULL && w->block == b && !printed[w->id]) { - skip = true; - break; - } - } - } else { - for (isize k = 0; k < v->arg_count; k++) { - ssaValue *w = v->args[k]; - if (w != NULL && w->block == b && !printed[w->id]) { - skip = true; - break; - } + for_array(k, v->args) { + ssaValue *w = v->args.e[k]; + if (w != NULL && w->block == b && !printed[w->id]) { + skip = true; + break; } } diff --git a/src/types.c b/src/types.c index 0d986ea1b..8a342d9bd 100644 --- a/src/types.c +++ b/src/types.c @@ -375,6 +375,10 @@ Type *base_enum_type(Type *t) { return t; } +Type *core_type(Type *t) { + return base_type(base_enum_type(t)); +} + void set_base_type(Type *t, Type *base) { if (t && t->kind == Type_Named) { t->Named.base = base; @@ -530,28 +534,28 @@ bool is_type_named(Type *t) { return t->kind == Type_Named; } bool is_type_boolean(Type *t) { - t = base_type(base_enum_type(t)); + t = core_type(t); if (t->kind == Type_Basic) { return (t->Basic.flags & BasicFlag_Boolean) != 0; } return false; } bool is_type_integer(Type *t) { - t = base_type(base_enum_type(t)); + t = core_type(t); if (t->kind == Type_Basic) { return (t->Basic.flags & BasicFlag_Integer) != 0; } return false; } bool is_type_unsigned(Type *t) { - t = base_type(base_enum_type(t)); + t = core_type(t); if (t->kind == Type_Basic) { return (t->Basic.flags & BasicFlag_Unsigned) != 0; } return false; } bool is_type_numeric(Type *t) { - t = base_type(base_enum_type(t)); + t = core_type(t); if (t->kind == Type_Basic) { return (t->Basic.flags & BasicFlag_Numeric) != 0; } @@ -586,7 +590,7 @@ bool is_type_untyped(Type *t) { return false; } bool is_type_ordered(Type *t) { - t = base_type(base_enum_type(t)); + t = core_type(t); switch (t->kind) { case Type_Basic: return (t->Basic.flags & BasicFlag_Ordered) != 0; @@ -598,28 +602,28 @@ bool is_type_ordered(Type *t) { return false; } bool is_type_constant_type(Type *t) { - t = base_type(base_enum_type(t)); + t = core_type(t); if (t->kind == Type_Basic) { return (t->Basic.flags & BasicFlag_ConstantType) != 0; } return false; } bool is_type_float(Type *t) { - t = base_type(base_enum_type(t)); + t = core_type(t); if (t->kind == Type_Basic) { return (t->Basic.flags & BasicFlag_Float) != 0; } return false; } bool is_type_f32(Type *t) { - t = base_type(base_enum_type(t)); + t = core_type(t); if (t->kind == Type_Basic) { return t->Basic.kind == Basic_f32; } return false; } bool is_type_f64(Type *t) { - t = base_type(base_enum_type(t)); + t = core_type(t); if (t->kind == Type_Basic) { return t->Basic.kind == Basic_f64; } @@ -737,7 +741,7 @@ bool is_type_untyped_nil(Type *t) { bool is_type_valid_for_keys(Type *t) { - t = base_type(base_enum_type(t)); + t = core_type(t); if (is_type_untyped(t)) { return false; } @@ -798,7 +802,7 @@ bool is_type_comparable(Type *t) { return true; case Type_Record: { if (is_type_enum(t)) { - return is_type_comparable(base_enum_type(t)); + return is_type_comparable(core_type(t)); } return false; } break;