From ff275df5ea01d24960c60d43a14db274db4eefd8 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 6 Mar 2023 12:39:52 +0000 Subject: [PATCH 01/32] Fix parsing C-like hex floats --- core/strconv/strconv.odin | 50 ++++++++++++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 11 deletions(-) diff --git a/core/strconv/strconv.odin b/core/strconv/strconv.odin index 6d7374760..816322aee 100644 --- a/core/strconv/strconv.odin +++ b/core/strconv/strconv.odin @@ -556,19 +556,49 @@ parse_f32 :: proc(s: string, n: ^int = nil) -> (value: f32, ok: bool) { return f32(v), ok } + +parse_f64 :: proc(str: string, n: ^int = nil) -> (value: f64, ok: bool) { + value, n^, ok = parse_f64_prefix(str) + if ok && len(str) != n^ { + ok = false + } + return +} + + +// Parses a 32-bit floating point number from a string. +// +// Returns ok=false if a base 10 float could not be found, +// or if the input string contained more than just the number. +// +// ``` +// n, _, ok := strconv.parse_f32("12.34eee"); +// assert(n == 12.34 && ok); +// +// n, _, ok = strconv.parse_f32("12.34"); +// assert(n == 12.34 && ok); +// ``` +parse_f32_prefix :: proc(str: string) -> (value: f32, nr: int, ok: bool) { + f: f64 + f, nr, ok = parse_f64_prefix(str) + value = f32(f) + return +} + + // Parses a 64-bit floating point number from a string. // // Returns ok=false if a base 10 float could not be found, // or if the input string contained more than just the number. // // ``` -// n, ok := strconv.parse_f32("12.34eee"); +// n, _, ok := strconv.parse_f32("12.34eee"); // assert(n == 12.34 && ok); // -// n, ok = strconv.parse_f32("12.34"); +// n, _, ok = strconv.parse_f32("12.34"); // assert(n == 12.34 && ok); // ``` -parse_f64 :: proc(str: string, n: ^int = nil) -> (value: f64, ok: bool) { +parse_f64_prefix :: proc(str: string) -> (value: f64, nr: int, ok: bool) { common_prefix_len_ignore_case :: proc "contextless" (s, prefix: string) -> int { n := len(prefix) if n > len(s) { @@ -751,7 +781,7 @@ parse_f64 :: proc(str: string, n: ^int = nil) -> (value: f64, ok: bool) { mantissa |= 1 } - for mantissa >> (info.mantbits+2) == 0 { + for mantissa != 0 && mantissa >> (info.mantbits+2) == 0 { mantissa = mantissa>>1 | mantissa&1 exp += 1 } @@ -795,9 +825,6 @@ parse_f64 :: proc(str: string, n: ^int = nil) -> (value: f64, ok: bool) { } - nr: int - defer if n != nil { n^ = nr } - if value, nr, ok = check_special(str); ok { return } @@ -808,7 +835,8 @@ parse_f64 :: proc(str: string, n: ^int = nil) -> (value: f64, ok: bool) { mantissa, exp, neg, trunc, hex, nr = parse_components(str) or_return if hex { - return parse_hex(str, mantissa, exp, neg, trunc) + value, ok = parse_hex(str, mantissa, exp, neg, trunc) + return } trunc_block: if !trunc { @@ -827,7 +855,7 @@ parse_f64 :: proc(str: string, n: ^int = nil) -> (value: f64, ok: bool) { } switch { case exp == 0: - return f, true + return f, nr, true case exp > 0 && exp <= 15+22: if exp > 22 { f *= pow10[exp-22] @@ -836,9 +864,9 @@ parse_f64 :: proc(str: string, n: ^int = nil) -> (value: f64, ok: bool) { if f > 1e15 || f < 1e-15 { break trunc_block } - return f * pow10[exp], true + return f * pow10[exp], nr, true case -22 <= exp && exp < 0: - return f / pow10[-exp], true + return f / pow10[-exp], nr, true } } d: decimal.Decimal From eea92a3371037d97cb141656d58ff5e14e7e3efc Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 6 Mar 2023 13:31:23 +0000 Subject: [PATCH 02/32] Add booleans to `print_any_single` --- core/runtime/print.odin | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/core/runtime/print.odin b/core/runtime/print.odin index 9696488a4..326a29667 100644 --- a/core/runtime/print.odin +++ b/core/runtime/print.odin @@ -6,7 +6,7 @@ _INTEGER_DIGITS :: "0123456789abcdefghijklmnopqrstuvwxyz" _INTEGER_DIGITS_VAR := _INTEGER_DIGITS when !ODIN_DISALLOW_RTTI { - print_any_single :: proc(arg: any) { + print_any_single :: proc "contextless" (arg: any) { x := arg if loc, ok := x.(Source_Code_Location); ok { print_caller_location(loc) @@ -49,6 +49,12 @@ when !ODIN_DISALLOW_RTTI { case uint: print_uint(v) case uintptr: print_uintptr(v) + case bool: print_string("true" if v else "false") + case b8: print_string("true" if v else "false") + case b16: print_string("true" if v else "false") + case b32: print_string("true" if v else "false") + case b64: print_string("true" if v else "false") + case: ti := type_info_of(x.id) #partial switch v in ti.variant { @@ -60,7 +66,7 @@ when !ODIN_DISALLOW_RTTI { print_string("") } } - println_any :: proc(args: ..any) { + println_any :: proc "contextless" (args: ..any) { loop: for arg, i in args { if i != 0 { print_string(" ") From 8f1af2630d2996a110cac1688b4ca89f4dfc3184 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 6 Mar 2023 13:40:06 +0000 Subject: [PATCH 03/32] Fix typo in `parse_components` --- core/strconv/strconv.odin | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/core/strconv/strconv.odin b/core/strconv/strconv.odin index 816322aee..5c96f584c 100644 --- a/core/strconv/strconv.odin +++ b/core/strconv/strconv.odin @@ -2,6 +2,7 @@ package strconv import "core:unicode/utf8" import "decimal" +import "core:runtime" parse_bool :: proc(s: string, n: ^int = nil) -> (result: bool = false, ok: bool) { switch s { @@ -708,8 +709,8 @@ parse_f64_prefix :: proc(str: string) -> (value: f64, nr: int, ok: bool) { saw_digits = true nd += 1 if nd_mant < MAX_MANT_DIGITS { - MAX_MANT_DIGITS *= 16 - MAX_MANT_DIGITS += int(lower(c) - 'a' + 10) + mantissa *= 16 + mantissa += u64(lower(c) - 'a' + 10) nd_mant += 1 } else { trunc = true @@ -835,6 +836,7 @@ parse_f64_prefix :: proc(str: string) -> (value: f64, nr: int, ok: bool) { mantissa, exp, neg, trunc, hex, nr = parse_components(str) or_return if hex { + runtime.println_any(mantissa, exp, neg, trunc, hex, nr) value, ok = parse_hex(str, mantissa, exp, neg, trunc) return } From fad330acd1ef2ffbf139ca1f52e93e3b367cf46f Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 6 Mar 2023 15:21:20 +0000 Subject: [PATCH 04/32] Fix bug with nil pointer --- core/strconv/strconv.odin | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/core/strconv/strconv.odin b/core/strconv/strconv.odin index 5c96f584c..dc3d7dbf1 100644 --- a/core/strconv/strconv.odin +++ b/core/strconv/strconv.odin @@ -559,10 +559,12 @@ parse_f32 :: proc(s: string, n: ^int = nil) -> (value: f32, ok: bool) { parse_f64 :: proc(str: string, n: ^int = nil) -> (value: f64, ok: bool) { - value, n^, ok = parse_f64_prefix(str) - if ok && len(str) != n^ { + nr: int + value, nr, ok = parse_f64_prefix(str) + if ok && len(str) != nr { ok = false } + if n != nil { n^ = nr } return } @@ -760,7 +762,6 @@ parse_f64_prefix :: proc(str: string) -> (value: f64, nr: int, ok: bool) { if mantissa != 0 { exp = decimal_point - nd_mant } - // TODO(bill): check underscore correctness ok = true return } From ef999f660b412d9eada0fffa644d3139186031a1 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 6 Mar 2023 19:46:50 +0000 Subject: [PATCH 05/32] Remove debug code --- core/strconv/strconv.odin | 2 -- 1 file changed, 2 deletions(-) diff --git a/core/strconv/strconv.odin b/core/strconv/strconv.odin index dc3d7dbf1..b96dca19a 100644 --- a/core/strconv/strconv.odin +++ b/core/strconv/strconv.odin @@ -2,7 +2,6 @@ package strconv import "core:unicode/utf8" import "decimal" -import "core:runtime" parse_bool :: proc(s: string, n: ^int = nil) -> (result: bool = false, ok: bool) { switch s { @@ -837,7 +836,6 @@ parse_f64_prefix :: proc(str: string) -> (value: f64, nr: int, ok: bool) { mantissa, exp, neg, trunc, hex, nr = parse_components(str) or_return if hex { - runtime.println_any(mantissa, exp, neg, trunc, hex, nr) value, ok = parse_hex(str, mantissa, exp, neg, trunc) return } From 1c2301e2f1fa22cdd1f45fb2d8824dd366836b50 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 6 Mar 2023 19:52:03 +0000 Subject: [PATCH 06/32] Use `atof` in `float_from_string` to allow for debug C-like semantic purposes --- src/exact_value.cpp | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/src/exact_value.cpp b/src/exact_value.cpp index 1ab50800d..7d5f71d78 100644 --- a/src/exact_value.cpp +++ b/src/exact_value.cpp @@ -1,4 +1,5 @@ #include +#include gb_global BlockingMutex hash_exact_value_mutex; @@ -174,7 +175,36 @@ gb_internal ExactValue exact_value_integer_from_string(String const &string) { -gb_internal f64 float_from_string(String string) { +gb_internal f64 float_from_string(String const &string) { + if (string.len < 128) { + char buf[128] = {}; + isize n = 0; + for (isize i = 0; i < string.len; i++) { + u8 c = string.text[i]; + if (c == '_') { + continue; + } + if (c == 'E') { c = 'e'; } + buf[n++] = cast(char)c; + } + buf[n] = 0; + return atof(buf); + } else { + TEMPORARY_ALLOCATOR_GUARD(); + char *buf = gb_alloc_array(temporary_allocator(), char, string.len+1); + isize n = 0; + for (isize i = 0; i < string.len; i++) { + u8 c = string.text[i]; + if (c == '_') { + continue; + } + if (c == 'E') { c = 'e'; } + buf[n++] = cast(char)c; + } + buf[n] = 0; + return atof(buf); + } +/* isize i = 0; u8 *str = string.text; isize len = string.len; @@ -250,6 +280,7 @@ gb_internal f64 float_from_string(String string) { } return sign * (frac ? (value / scale) : (value * scale)); +*/ } gb_internal ExactValue exact_value_float_from_string(String string) { From 133af6f82611aff2cb90f11b0575646bd841cea7 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 7 Mar 2023 15:24:59 +0000 Subject: [PATCH 07/32] Remove `delete` with wrong allocator --- core/strings/strings.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/strings/strings.odin b/core/strings/strings.odin index 29d9a6e66..cd9e9a04f 100644 --- a/core/strings/strings.odin +++ b/core/strings/strings.odin @@ -1428,7 +1428,7 @@ split_multi :: proc(s: string, substrs: []string, allocator := context.allocator // sort substrings by string size, largest to smallest runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() temp_substrs := slice.clone(substrs, context.temp_allocator) - defer delete(temp_substrs) + slice.sort_by(temp_substrs, proc(a, b: string) -> bool { return len(a) > len(b) }) From 085db569f1a96a7a5b238224d7f101d4488daa09 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 7 Mar 2023 15:31:55 +0000 Subject: [PATCH 08/32] Add `-o:none` optimization mode (useful for `-debug` builds) --- src/build_settings.cpp | 2 +- src/llvm_backend_opt.cpp | 32 ++++++++++++++++++++------------ src/main.cpp | 5 ++++- 3 files changed, 25 insertions(+), 14 deletions(-) diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 562b669b5..9aee03676 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -1255,7 +1255,7 @@ gb_internal void init_build_context(TargetMetrics *cross_target) { gb_exit(1); } - bc->optimization_level = gb_clamp(bc->optimization_level, 0, 3); + bc->optimization_level = gb_clamp(bc->optimization_level, -1, 2); // ENFORCE DYNAMIC MAP CALLS bc->dynamic_map_calls = true; diff --git a/src/llvm_backend_opt.cpp b/src/llvm_backend_opt.cpp index d7a34d82a..e06042341 100644 --- a/src/llvm_backend_opt.cpp +++ b/src/llvm_backend_opt.cpp @@ -55,8 +55,17 @@ gb_internal void lb_populate_function_pass_manager_specific(lbModule *m, LLVMPas #define LLVM_ADD_CONSTANT_VALUE_PASS(fpm) #endif +gb_internal bool lb_opt_ignore(i32 optimization_level) { + optimization_level = gb_clamp(optimization_level, -1, 2); + return optimization_level == -1; +} + gb_internal void lb_basic_populate_function_pass_manager(LLVMPassManagerRef fpm, i32 optimization_level) { - if (false && optimization_level == 0 && build_context.ODIN_DEBUG) { + if (lb_opt_ignore(optimization_level)) { + return; + } + + if (false && optimization_level <= 0 && build_context.ODIN_DEBUG) { LLVMAddMergedLoadStoreMotionPass(fpm); } else { LLVMAddPromoteMemoryToRegisterPass(fpm); @@ -69,14 +78,14 @@ gb_internal void lb_basic_populate_function_pass_manager(LLVMPassManagerRef fpm, } gb_internal void lb_populate_function_pass_manager(lbModule *m, LLVMPassManagerRef fpm, bool ignore_memcpy_pass, i32 optimization_level) { - // NOTE(bill): Treat -opt:3 as if it was -opt:2 - // TODO(bill): Determine which opt definitions should exist in the first place - optimization_level = gb_clamp(optimization_level, 0, 2); + if (lb_opt_ignore(optimization_level)) { + return; + } if (ignore_memcpy_pass) { lb_basic_populate_function_pass_manager(fpm, optimization_level); return; - } else if (optimization_level == 0) { + } else if (optimization_level <= 0) { LLVMAddMemCpyOptPass(fpm); lb_basic_populate_function_pass_manager(fpm, optimization_level); return; @@ -103,11 +112,11 @@ gb_internal void lb_populate_function_pass_manager(lbModule *m, LLVMPassManagerR } gb_internal void lb_populate_function_pass_manager_specific(lbModule *m, LLVMPassManagerRef fpm, i32 optimization_level) { - // NOTE(bill): Treat -opt:3 as if it was -opt:2 - // TODO(bill): Determine which opt definitions should exist in the first place - optimization_level = gb_clamp(optimization_level, 0, 2); + if (lb_opt_ignore(optimization_level)) { + return; + } - if (optimization_level == 0) { + if (optimization_level <= 0) { LLVMAddMemCpyOptPass(fpm); lb_basic_populate_function_pass_manager(fpm, optimization_level); return; @@ -181,8 +190,7 @@ gb_internal void lb_populate_module_pass_manager(LLVMTargetMachineRef target_mac // NOTE(bill): Treat -opt:3 as if it was -opt:2 // TODO(bill): Determine which opt definitions should exist in the first place - optimization_level = gb_clamp(optimization_level, 0, 2); - if (optimization_level == 0 && build_context.ODIN_DEBUG) { + if (optimization_level <= 0 && build_context.ODIN_DEBUG) { return; } @@ -190,7 +198,7 @@ gb_internal void lb_populate_module_pass_manager(LLVMTargetMachineRef target_mac LLVMAddStripDeadPrototypesPass(mpm); LLVMAddAnalysisPasses(target_machine, mpm); LLVMAddPruneEHPass(mpm); - if (optimization_level == 0) { + if (optimization_level <= 0) { return; } diff --git a/src/main.cpp b/src/main.cpp index 0494df3e9..488aeb363 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1002,7 +1002,9 @@ gb_internal bool parse_build_flags(Array args) { } case BuildFlag_OptimizationMode: { GB_ASSERT(value.kind == ExactValue_String); - if (value.value_string == "minimal") { + if (value.value_string == "none") { + build_context.optimization_level = -1; + } else if (value.value_string == "minimal") { build_context.optimization_level = 0; } else if (value.value_string == "size") { build_context.optimization_level = 1; @@ -1014,6 +1016,7 @@ gb_internal bool parse_build_flags(Array args) { gb_printf_err("\tminimal\n"); gb_printf_err("\tsize\n"); gb_printf_err("\tspeed\n"); + gb_printf_err("\tnone (useful for -debug builds)\n"); bad_flags = true; } break; From 7f3f164736e9eafe67834f6b566a758da9a39011 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 7 Mar 2023 15:32:32 +0000 Subject: [PATCH 09/32] Update help usage --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 488aeb363..066675b36 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1958,7 +1958,7 @@ gb_internal void print_show_help(String const arg0, String const &command) { print_usage_line(1, "-o:"); print_usage_line(2, "Set the optimization mode for compilation"); - print_usage_line(2, "Accepted values: minimal, size, speed"); + print_usage_line(2, "Accepted values: minimal, size, speed, none"); print_usage_line(2, "Example: -o:speed"); print_usage_line(0, ""); } From a262c0bbf325051891debe1a86866f5c9059ee58 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 7 Mar 2023 16:25:46 +0000 Subject: [PATCH 10/32] Separate out the `read_reg` into three non-parapoly procedures --- core/sys/info/platform_windows.odin | 144 ++++++++++++++++------------ 1 file changed, 82 insertions(+), 62 deletions(-) diff --git a/core/sys/info/platform_windows.odin b/core/sys/info/platform_windows.odin index 5e922d904..9c1c7b04c 100644 --- a/core/sys/info/platform_windows.odin +++ b/core/sys/info/platform_windows.odin @@ -223,11 +223,10 @@ init_os_version :: proc () { // Grab Windows DisplayVersion (like 20H02) format_display_version :: proc (b: ^strings.Builder) -> (version: string) { - dv, ok := read_reg( + dv, ok := read_reg_string( sys.HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", "DisplayVersion", - string, ) defer delete(dv) // It'll be interned into `version_string_buf` @@ -243,11 +242,10 @@ init_os_version :: proc () { // Grab build number and UBR format_build_number :: proc (b: ^strings.Builder, major_build: int) -> (ubr: int) { - res, ok := read_reg( + res, ok := read_reg_i32( sys.HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", "UBR", - i32, ) if ok { @@ -289,17 +287,17 @@ init_gpu_info :: proc() { for { key := fmt.tprintf("%v\\%04d", GPU_INFO_BASE, gpu_index) - if vendor, ok := read_reg(sys.HKEY_LOCAL_MACHINE, key, "ProviderName", string); ok { + if vendor, ok := read_reg_string(sys.HKEY_LOCAL_MACHINE, key, "ProviderName"); ok { append(&gpu_list, GPU{vendor_name = vendor}) } else { break } - if desc, ok := read_reg(sys.HKEY_LOCAL_MACHINE, key, "DriverDesc", string); ok { + if desc, ok := read_reg_string(sys.HKEY_LOCAL_MACHINE, key, "DriverDesc"); ok { gpu_list[gpu_index].model_name = desc } - if vram, ok := read_reg(sys.HKEY_LOCAL_MACHINE, key, "HardwareInformation.qwMemorySize", i64); ok { + if vram, ok := read_reg_i64(sys.HKEY_LOCAL_MACHINE, key, "HardwareInformation.qwMemorySize"); ok { gpu_list[gpu_index].total_ram = int(vram) } gpu_index += 1 @@ -308,71 +306,93 @@ init_gpu_info :: proc() { } @(private) -read_reg :: proc(hkey: sys.HKEY, subkey, val: string, $T: typeid) -> (res: T, ok: bool) { - BUF_SIZE :: 1024 - +read_reg_string :: proc(hkey: sys.HKEY, subkey, val: string) -> (res: string, ok: bool) { if len(subkey) == 0 || len(val) == 0 { - return {}, false + return } runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() + BUF_SIZE :: 1024 key_name_wide := make([]u16, BUF_SIZE, context.temp_allocator) val_name_wide := make([]u16, BUF_SIZE, context.temp_allocator) utf16.encode_string(key_name_wide, subkey) utf16.encode_string(val_name_wide, val) - when T == string { - result_wide := make([]u16, BUF_SIZE, context.temp_allocator) - result_size := sys.DWORD(BUF_SIZE * size_of(u16)) + result_wide := make([]u16, BUF_SIZE, context.temp_allocator) + result_size := sys.DWORD(BUF_SIZE * size_of(u16)) - status := sys.RegGetValueW( - hkey, - &key_name_wide[0], - &val_name_wide[0], - sys.RRF_RT_REG_SZ, - nil, - raw_data(result_wide[:]), - &result_size, - ) - if status != 0 { - // Couldn't retrieve string - return - } - - // Result string will be allocated for the caller. - result_utf8 := make([]u8, BUF_SIZE * 4, context.temp_allocator) - utf16.decode_to_utf8(result_utf8, result_wide[:result_size]) - return strings.clone_from_cstring(cstring(raw_data(result_utf8))), true - - } else when T == i32 { - result_size := sys.DWORD(size_of(i32)) - status := sys.RegGetValueW( - hkey, - &key_name_wide[0], - &val_name_wide[0], - sys.RRF_RT_REG_DWORD, - nil, - &res, - &result_size, - ) - return res, status == 0 - - } else when T == i64 { - result_size := sys.DWORD(size_of(i64)) - status := sys.RegGetValueW( - hkey, - &key_name_wide[0], - &val_name_wide[0], - sys.RRF_RT_REG_QWORD, - nil, - &res, - &result_size, - ) - return res, status == 0 - } else { - #assert(false, "Unhandled type for read_reg") + status := sys.RegGetValueW( + hkey, + &key_name_wide[0], + &val_name_wide[0], + sys.RRF_RT_REG_SZ, + nil, + raw_data(result_wide[:]), + &result_size, + ) + if status != 0 { + // Couldn't retrieve string + return } - return -} \ No newline at end of file + + // Result string will be allocated for the caller. + result_utf8 := make([]u8, BUF_SIZE * 4, context.temp_allocator) + utf16.decode_to_utf8(result_utf8, result_wide[:result_size]) + return strings.clone_from_cstring(cstring(raw_data(result_utf8))), true +} +@(private) +read_reg_i32 :: proc(hkey: sys.HKEY, subkey, val: string) -> (res: i32, ok: bool) { + if len(subkey) == 0 || len(val) == 0 { + return + } + + runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() + + BUF_SIZE :: 1024 + key_name_wide := make([]u16, BUF_SIZE, context.temp_allocator) + val_name_wide := make([]u16, BUF_SIZE, context.temp_allocator) + + utf16.encode_string(key_name_wide, subkey) + utf16.encode_string(val_name_wide, val) + + result_size := sys.DWORD(size_of(i32)) + status := sys.RegGetValueW( + hkey, + &key_name_wide[0], + &val_name_wide[0], + sys.RRF_RT_REG_DWORD, + nil, + &res, + &result_size, + ) + return res, status == 0 +} +@(private) +read_reg_i64 :: proc(hkey: sys.HKEY, subkey, val: string) -> (res: i64, ok: bool) { + if len(subkey) == 0 || len(val) == 0 { + return + } + + runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() + + BUF_SIZE :: 1024 + key_name_wide := make([]u16, BUF_SIZE, context.temp_allocator) + val_name_wide := make([]u16, BUF_SIZE, context.temp_allocator) + + utf16.encode_string(key_name_wide, subkey) + utf16.encode_string(val_name_wide, val) + + result_size := sys.DWORD(size_of(i64)) + status := sys.RegGetValueW( + hkey, + &key_name_wide[0], + &val_name_wide[0], + sys.RRF_RT_REG_QWORD, + nil, + &res, + &result_size, + ) + return res, status == 0 +} From 1ecab2fcbc4a52b481f185ccf87bb38c9691c39e Mon Sep 17 00:00:00 2001 From: Sokus Date: Wed, 8 Mar 2023 13:17:59 +0100 Subject: [PATCH 11/32] Add `set_blocking` for network sockets --- core/net/common.odin | 1 + core/net/errors_darwin.odin | 6 ++++++ core/net/errors_linux.odin | 8 ++++++++ core/net/errors_windows.odin | 12 ++++++++++++ core/net/socket.odin | 4 ++++ core/net/socket_darwin.odin | 6 ++++++ core/net/socket_linux.odin | 23 +++++++++++++++++++++++ core/net/socket_windows.odin | 12 ++++++++++++ core/os/os_linux.odin | 13 +++++++++++++ core/sys/unix/syscalls_linux.odin | 4 ++++ 10 files changed, 89 insertions(+) diff --git a/core/net/common.odin b/core/net/common.odin index a9f2ba9bb..70a027138 100644 --- a/core/net/common.odin +++ b/core/net/common.odin @@ -64,6 +64,7 @@ Network_Error :: union #shared_nil { UDP_Recv_Error, Shutdown_Error, Socket_Option_Error, + Set_Blocking_Error, Parse_Endpoint_Error, Resolve_Error, DNS_Error, diff --git a/core/net/errors_darwin.odin b/core/net/errors_darwin.odin index 645bbe555..39cf4c665 100644 --- a/core/net/errors_darwin.odin +++ b/core/net/errors_darwin.odin @@ -197,4 +197,10 @@ Socket_Option_Error :: enum c.int { Invalid_Option_For_Socket = c.int(os.ENOPROTOOPT), Reset_When_Keepalive_Set = c.int(os.ENOTCONN), Not_Socket = c.int(os.ENOTSOCK), +} + +Set_Blocking_Error :: enum c.int { + None = 0, + + // TODO: Add errors for `set_blocking` } \ No newline at end of file diff --git a/core/net/errors_linux.odin b/core/net/errors_linux.odin index 9575d7c18..9366f4435 100644 --- a/core/net/errors_linux.odin +++ b/core/net/errors_linux.odin @@ -190,4 +190,12 @@ Socket_Option_Error :: enum c.int { Invalid_Option_For_Socket = c.int(os.ENOPROTOOPT), Reset_When_Keepalive_Set = c.int(os.ENOTCONN), Not_Socket = c.int(os.ENOTSOCK), +} + +Set_Blocking_Error :: enum c.int { + None = 0, + + // TODO: add errors occuring on followig calls: + // flags, _ := os.fcntl(sd, os.F_GETFL, 0) + // os.fcntl(sd, os.F_SETFL, flags | int(os.O_NONBLOCK)) } \ No newline at end of file diff --git a/core/net/errors_windows.odin b/core/net/errors_windows.odin index 154f6c2d8..272aa0a96 100644 --- a/core/net/errors_windows.odin +++ b/core/net/errors_windows.odin @@ -259,3 +259,15 @@ Socket_Option_Error :: enum c.int { Reset_When_Keepalive_Set = win.WSAENOTCONN, Not_Socket = win.WSAENOTSOCK, } + +Set_Blocking_Error :: enum c.int { + None = 0, + + Network_Subsystem_Failure = win.WSAENETDOWN, + Blocking_Call_In_Progress = win.WSAEINPROGRESS, + Not_Socket = win.WSAENOTSOCK, + + // TODO: are those errors possible? + Network_Subsystem_Not_Initialized = win.WSAENOTINITIALISED, + Invalid_Argument_Pointer = win.WSAEFAULT, +} \ No newline at end of file diff --git a/core/net/socket.odin b/core/net/socket.odin index 95eb50496..a24ae8a0b 100644 --- a/core/net/socket.odin +++ b/core/net/socket.odin @@ -173,4 +173,8 @@ shutdown :: proc(socket: Any_Socket, manner: Shutdown_Manner) -> (err: Network_E set_option :: proc(socket: Any_Socket, option: Socket_Option, value: any, loc := #caller_location) -> Network_Error { return _set_option(socket, option, value, loc) +} + +set_blocking :: proc(socket: Any_Socket, should_block: bool) -> (err: Network_Error) { + return _set_blocking(socket, should_block) } \ No newline at end of file diff --git a/core/net/socket_darwin.odin b/core/net/socket_darwin.odin index a0a5af6ca..0d8503cfd 100644 --- a/core/net/socket_darwin.odin +++ b/core/net/socket_darwin.odin @@ -301,6 +301,12 @@ _set_option :: proc(s: Any_Socket, option: Socket_Option, value: any, loc := #ca return nil } +@(private) +_set_blocking :: proc(socket: Any_Socket, should_block: bool) -> (err: Network_Error) { + // TODO: Implement + unimplemented() +} + @private _endpoint_to_sockaddr :: proc(ep: Endpoint) -> (sockaddr: os.SOCKADDR_STORAGE_LH) { switch a in ep.address { diff --git a/core/net/socket_linux.odin b/core/net/socket_linux.odin index 81419f6c9..690e09ab7 100644 --- a/core/net/socket_linux.odin +++ b/core/net/socket_linux.odin @@ -316,6 +316,29 @@ _set_option :: proc(s: Any_Socket, option: Socket_Option, value: any, loc := #ca return nil } +@(private) +_set_blocking :: proc(socket: Any_Socket, should_block: bool) -> (err: Network_Error) { + socket := any_socket_to_socket(socket) + + flags, getfl_err := os.fcntl(int(socket), os.F_GETFL, 0) + if getfl_err != os.ERROR_NONE { + return Set_Blocking_Error(getfl_err) + } + + if should_block { + flags &= ~int(os.O_NONBLOCK) + } else { + flags |= int(os.O_NONBLOCK) + } + + _, setfl_err := os.fcntl(int(socket), os.F_SETFL, flags) + if setfl_err != os.ERROR_NONE { + return Set_Blocking_Error(setfl_err) + } + + return nil +} + @(private) _endpoint_to_sockaddr :: proc(ep: Endpoint) -> (sockaddr: os.SOCKADDR_STORAGE_LH) { switch a in ep.address { diff --git a/core/net/socket_windows.odin b/core/net/socket_windows.odin index d7264d617..3b9623749 100644 --- a/core/net/socket_windows.odin +++ b/core/net/socket_windows.odin @@ -310,6 +310,18 @@ _set_option :: proc(s: Any_Socket, option: Socket_Option, value: any, loc := #ca return nil } +@(private) +_set_blocking :: proc(socket: Any_Socket, should_block: bool) -> (err: Network_Error) { + socket := any_socket_to_socket(socket) + arg: win.DWORD = 0 if should_block else 1 + res := win.ioctlsocket(win.SOCKET(socket), transmute(win.c_long)win.FIONBIO, &arg) + if res == win.SOCKET_ERROR { + return Set_Blocking_Error(win.WSAGetLastError()) + } + + return nil +} + @(private) _endpoint_to_sockaddr :: proc(ep: Endpoint) -> (sockaddr: win.SOCKADDR_STORAGE_LH) { switch a in ep.address { diff --git a/core/os/os_linux.odin b/core/os/os_linux.odin index 85abb0d21..d001d5ec7 100644 --- a/core/os/os_linux.odin +++ b/core/os/os_linux.odin @@ -225,6 +225,11 @@ TCP_CORK: int : 3 MSG_TRUNC : int : 0x20 +// TODO: add remaining fcntl commands +// reference: https://github.com/torvalds/linux/blob/master/include/uapi/asm-generic/fcntl.h +F_GETFL: int : 3 /* Get file flags */ +F_SETFL: int : 4 /* Set file flags */ + // NOTE(zangent): These are OS specific! // Do not mix these up! RTLD_LAZY :: 0x001 @@ -1074,3 +1079,11 @@ shutdown :: proc(sd: Socket, how: int) -> (Errno) { } return ERROR_NONE } + +fcntl :: proc(fd: int, cmd: int, arg: int) -> (int, Errno) { + result := unix.sys_fcntl(fd, cmd, arg) + if result < 0 { + return 0, _get_errno(result) + } + return result, ERROR_NONE +} \ No newline at end of file diff --git a/core/sys/unix/syscalls_linux.odin b/core/sys/unix/syscalls_linux.odin index 779bc3be3..abdcf0b92 100644 --- a/core/sys/unix/syscalls_linux.odin +++ b/core/sys/unix/syscalls_linux.odin @@ -2053,6 +2053,10 @@ sys_personality :: proc(persona: u64) -> int { return int(intrinsics.syscall(SYS_personality, uintptr(persona))) } +sys_fcntl :: proc "contextless" (fd: int, cmd: int, arg: int) -> int { + return int(intrinsics.syscall(SYS_fcntl, uintptr(fd), uintptr(cmd), uintptr(arg))) +} + get_errno :: proc "contextless" (res: int) -> i32 { if res < 0 && res > -4096 { return i32(-res) From 7c0257fcdad00cbb66d1d089715ec0ad684fd4c0 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 9 Mar 2023 15:39:41 +0000 Subject: [PATCH 12/32] Fix value elision on declaration --- src/llvm_backend.hpp | 2 ++ src/llvm_backend_const.cpp | 9 ++++++++- src/llvm_backend_debug.cpp | 1 - src/llvm_backend_opt.cpp | 6 +++++- src/llvm_backend_stmt.cpp | 27 ++++++++++++++++++--------- 5 files changed, 33 insertions(+), 12 deletions(-) diff --git a/src/llvm_backend.hpp b/src/llvm_backend.hpp index 4a78ca3a9..4104d5b5f 100644 --- a/src/llvm_backend.hpp +++ b/src/llvm_backend.hpp @@ -337,6 +337,8 @@ struct lbProcedure { LLVMMetadataRef debug_info; + lbAddr current_elision_hint; + PtrMap selector_values; PtrMap selector_addr; PtrMap tuple_fix_map; diff --git a/src/llvm_backend_const.cpp b/src/llvm_backend_const.cpp index 3da768cd1..286c01f74 100644 --- a/src/llvm_backend_const.cpp +++ b/src/llvm_backend_const.cpp @@ -484,7 +484,14 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bo LLVMValueRef indices[2] = {llvm_zero(m), llvm_zero(m)}; LLVMValueRef ptr = LLVMBuildInBoundsGEP2(p->builder, llvm_type, array_data, indices, 2, ""); LLVMValueRef len = LLVMConstInt(lb_type(m, t_int), count, true); - lbAddr slice = lb_add_local_generated(p, type, false); + + lbAddr slice = {}; + if (p->current_elision_hint.addr.value && are_types_identical(lb_addr_type(p->current_elision_hint), type)) { + slice = p->current_elision_hint; + p->current_elision_hint = {}; + } else { + slice = lb_add_local_generated(p, type, false); + } map_set(&m->exact_value_compound_literal_addr_map, value.value_compound, slice); lb_fill_slice(p, slice, {ptr, alloc_type_pointer(elem)}, {len, t_int}); diff --git a/src/llvm_backend_debug.cpp b/src/llvm_backend_debug.cpp index f65656494..fd26c41a0 100644 --- a/src/llvm_backend_debug.cpp +++ b/src/llvm_backend_debug.cpp @@ -989,7 +989,6 @@ gb_internal void lb_add_debug_local_variable(lbProcedure *p, LLVMValueRef ptr, T return; } - AstFile *file = p->body->file(); LLVMMetadataRef llvm_scope = lb_get_current_debug_scope(p); diff --git a/src/llvm_backend_opt.cpp b/src/llvm_backend_opt.cpp index e06042341..61f51b15b 100644 --- a/src/llvm_backend_opt.cpp +++ b/src/llvm_backend_opt.cpp @@ -275,6 +275,9 @@ gb_internal void lb_populate_module_pass_manager(LLVMTargetMachineRef target_mac **************************************************************************/ gb_internal void lb_run_remove_dead_instruction_pass(lbProcedure *p) { + unsigned debug_declare_id = LLVMLookupIntrinsicID("llvm.dbg.declare", 16); + GB_ASSERT(debug_declare_id != 0); + isize removal_count = 0; isize pass_count = 0; isize const max_pass_count = 10; @@ -310,6 +313,8 @@ gb_internal void lb_run_remove_dead_instruction_pass(lbProcedure *p) { // NOTE(bill): Explicit instructions are set here because some instructions could have side effects switch (LLVMGetInstructionOpcode(curr_instr)) { + // case LLVMAlloca: + case LLVMFNeg: case LLVMAdd: case LLVMFAdd: @@ -329,7 +334,6 @@ gb_internal void lb_run_remove_dead_instruction_pass(lbProcedure *p) { case LLVMAnd: case LLVMOr: case LLVMXor: - case LLVMAlloca: case LLVMLoad: case LLVMGetElementPtr: case LLVMTrunc: diff --git a/src/llvm_backend_stmt.cpp b/src/llvm_backend_stmt.cpp index ec6ac5886..456a262a4 100644 --- a/src/llvm_backend_stmt.cpp +++ b/src/llvm_backend_stmt.cpp @@ -2287,18 +2287,25 @@ gb_internal void lb_build_stmt(lbProcedure *p, Ast *node) { isize lval_index = 0; for (Ast *rhs : values) { + p->current_elision_hint = lvals[lval_index]; + rhs = unparen_expr(rhs); lbValue init = lb_build_expr(p, rhs); #if 1 - // NOTE(bill, 2023-02-17): lb_const_value might produce a stack local variable for the - // compound literal, so reusing that variable should minimize the stack wastage - if (rhs->kind == Ast_CompoundLit) { - lbAddr *comp_lit_addr = map_get(&p->module->exact_value_compound_literal_addr_map, rhs); - if (comp_lit_addr) { - Entity *e = entity_of_node(vd->names[lval_index]); - if (e) { - lb_add_entity(p->module, e, comp_lit_addr->addr); - lvals[lval_index] = {}; // do nothing so that nothing will assign to it + if (p->current_elision_hint.addr.value != lvals[lval_index].addr.value) { + lvals[lval_index] = {}; // do nothing so that nothing will assign to it + } else { + // NOTE(bill, 2023-02-17): lb_const_value might produce a stack local variable for the + // compound literal, so reusing that variable should minimize the stack wastage + if (rhs->kind == Ast_CompoundLit) { + lbAddr *comp_lit_addr = map_get(&p->module->exact_value_compound_literal_addr_map, rhs); + if (comp_lit_addr) { + Entity *e = entity_of_node(vd->names[lval_index]); + if (e) { + GB_ASSERT(p->current_elision_hint.addr.value == nullptr); + GB_ASSERT(p->current_elision_hint.addr.value != lvals[lval_index].addr.value); + lvals[lval_index] = {}; // do nothing so that nothing will assign to it + } } } } @@ -2308,6 +2315,8 @@ gb_internal void lb_build_stmt(lbProcedure *p, Ast *node) { } GB_ASSERT(lval_index == lvals.count); + p->current_elision_hint = {}; + GB_ASSERT(lvals.count == inits.count); for_array(i, inits) { lbAddr lval = lvals[i]; From 3470d986f0a850274f28ecc473082830c799c50e Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 9 Mar 2023 15:48:02 +0000 Subject: [PATCH 13/32] Fix debug symbols for range loops --- src/llvm_backend_stmt.cpp | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/llvm_backend_stmt.cpp b/src/llvm_backend_stmt.cpp index 456a262a4..019d3554d 100644 --- a/src/llvm_backend_stmt.cpp +++ b/src/llvm_backend_stmt.cpp @@ -791,15 +791,6 @@ gb_internal void lb_build_range_stmt(lbProcedure *p, AstRangeStmt *rs, Scope *sc val1_type = type_of_expr(rs->vals[1]); } - if (val0_type != nullptr) { - Entity *e = entity_of_node(rs->vals[0]); - lb_add_local(p, e->type, e, true); - } - if (val1_type != nullptr) { - Entity *e = entity_of_node(rs->vals[1]); - lb_add_local(p, e->type, e, true); - } - lbValue val = {}; lbValue key = {}; lbBlock *loop = nullptr; From c39bd7e0894d3ef9a8f1ac9b487710cc41baf629 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 9 Mar 2023 15:57:29 +0000 Subject: [PATCH 14/32] Fix range loop `&` vals debug info --- src/llvm_backend_stmt.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/llvm_backend_stmt.cpp b/src/llvm_backend_stmt.cpp index 019d3554d..99a16094a 100644 --- a/src/llvm_backend_stmt.cpp +++ b/src/llvm_backend_stmt.cpp @@ -1299,6 +1299,7 @@ gb_internal lbAddr lb_store_range_stmt_val(lbProcedure *p, Ast *stmt_val, lbValu if (LLVMIsALoadInst(value.value)) { lbValue ptr = lb_address_from_load_or_generate_local(p, value); lb_add_entity(p->module, e, ptr); + lb_add_debug_local_variable(p, ptr.value, e->type, e->token); return lb_addr(ptr); } } From 30ced041376fcfe6684f72f45ef16c335b8ed89d Mon Sep 17 00:00:00 2001 From: Colin Davidson Date: Thu, 9 Mar 2023 15:26:27 -0800 Subject: [PATCH 15/32] log buffer flushes to trace --- core/prof/spall/spall.odin | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/core/prof/spall/spall.odin b/core/prof/spall/spall.odin index ff8c69222..5d3fcdf83 100644 --- a/core/prof/spall/spall.odin +++ b/core/prof/spall/spall.odin @@ -95,7 +95,7 @@ context_destroy :: proc(ctx: ^Context) { } buffer_create :: proc(data: []byte, tid: u32 = 0, pid: u32 = 0) -> (buffer: Buffer, ok: bool) #optional_ok { - assert(len(data) > 0) + assert(len(data) >= 1024) buffer.data = data buffer.tid = tid buffer.pid = pid @@ -105,8 +105,13 @@ buffer_create :: proc(data: []byte, tid: u32 = 0, pid: u32 = 0) -> (buffer: Buff } buffer_flush :: proc(ctx: ^Context, buffer: ^Buffer) { + start := _trace_now(ctx) os.write(ctx.fd, buffer.data[:buffer.head]) buffer.head = 0 + end := _trace_now(ctx) + + buffer.head += _build_begin(buffer.data[buffer.head:], "Spall Trace Buffer Flush", "", start, buffer.tid, buffer.pid) + buffer.head += _build_end(buffer.data[buffer.head:], end, buffer.tid, buffer.pid) } buffer_destroy :: proc(ctx: ^Context, buffer: ^Buffer) { @@ -171,10 +176,11 @@ _build_begin :: proc "contextless" (buffer: []u8, name: string, args: string, ts mem.copy(raw_data(buffer[size_of(Begin_Event):]), raw_data(name), name_len) mem.copy(raw_data(buffer[size_of(Begin_Event)+name_len:]), raw_data(args), args_len) ok = true + return } -_build_end :: proc(buffer: []u8, ts: f64, tid: u32, pid: u32) -> (event_size: int, ok: bool) #optional_ok { +_build_end :: proc "contextless" (buffer: []u8, ts: f64, tid: u32, pid: u32) -> (event_size: int, ok: bool) #optional_ok { ev := (^End_Event)(raw_data(buffer)) event_size = size_of(End_Event) if event_size > len(buffer) { @@ -186,6 +192,7 @@ _build_end :: proc(buffer: []u8, ts: f64, tid: u32, pid: u32) -> (event_size: in ev.tid = u32le(tid) ev.ts = f64le(ts) ok = true + return } From 6f4f2754d6a8106bc922765d3006b6cce615d124 Mon Sep 17 00:00:00 2001 From: Colin Davidson Date: Thu, 9 Mar 2023 16:05:16 -0800 Subject: [PATCH 16/32] add basic usage example --- core/prof/spall/doc.odin | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 core/prof/spall/doc.odin diff --git a/core/prof/spall/doc.odin b/core/prof/spall/doc.odin new file mode 100644 index 000000000..a04c9e420 --- /dev/null +++ b/core/prof/spall/doc.odin @@ -0,0 +1,24 @@ +/* +import "core:prof/spall" + +spall_ctx: spall.Context +spall_buffer: spall.Buffer + +foo :: proc() { + spall.SCOPED_EVENT(&spall_ctx, &spall_buffer, #procedure) +} + +main :: proc() { + spall_ctx = spall.context_create("trace_test.spall") + defer spall.context_destroy(&spall_ctx) + + buffer_backing := make([]u8, spall.BUFFER_DEFAULT_SIZE) + spall_buffer = spall.buffer_create(buffer_backing) + defer spall.buffer_destroy(&spall_ctx, &spall_buffer) + + for i := 0; i < 9001; i += 1 { + foo() + } +} +*/ +package spall From 2334dadb6aa7650278213ec6364543ab8e47297c Mon Sep 17 00:00:00 2001 From: Colin Davidson Date: Thu, 9 Mar 2023 16:34:43 -0800 Subject: [PATCH 17/32] add main scope --- core/prof/spall/doc.odin | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/prof/spall/doc.odin b/core/prof/spall/doc.odin index a04c9e420..0f3cc8bb8 100644 --- a/core/prof/spall/doc.odin +++ b/core/prof/spall/doc.odin @@ -16,6 +16,8 @@ main :: proc() { spall_buffer = spall.buffer_create(buffer_backing) defer spall.buffer_destroy(&spall_ctx, &spall_buffer) + spall.SCOPED_EVENT(&spall_ctx, &spall_buffer, #procedure) + for i := 0; i < 9001; i += 1 { foo() } From 63b5d472fa6acb9c8d94a94fb0abe20436ffa32c Mon Sep 17 00:00:00 2001 From: William Roe Date: Fri, 10 Mar 2023 16:07:06 +0000 Subject: [PATCH 18/32] Fix documentation example of strings.to_upper This looks like it was a copy/paste mistake --- core/strings/conversion.odin | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/strings/conversion.odin b/core/strings/conversion.odin index ab827490d..8a67618da 100644 --- a/core/strings/conversion.odin +++ b/core/strings/conversion.odin @@ -78,8 +78,8 @@ to_lower :: proc(s: string, allocator := context.allocator) -> string { returns the input string `s` with all runes set to upper case always allocates using the `allocator` - strings.to_lower("test") -> TEST - strings.to_lower("Test") -> TEST + strings.to_upper("test") -> TEST + strings.to_upper("Test") -> TEST */ to_upper :: proc(s: string, allocator := context.allocator) -> string { b: Builder From ac0f3c84332feb66113db5069fd2126a875f5156 Mon Sep 17 00:00:00 2001 From: Jon Lipstate Date: Fri, 10 Mar 2023 19:24:11 -0800 Subject: [PATCH 19/32] resolve doc/spall package name conflict --- core/prof/spall/spall.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/prof/spall/spall.odin b/core/prof/spall/spall.odin index 5d3fcdf83..6a78c466e 100644 --- a/core/prof/spall/spall.odin +++ b/core/prof/spall/spall.odin @@ -1,4 +1,4 @@ -package prof_spall +package spall import "core:os" import "core:time" From 731b9c902f4ae1f66cf3a4b167fa394fe8ae7dec Mon Sep 17 00:00:00 2001 From: Marko <54064471+markodevv@users.noreply.github.com> Date: Sat, 11 Mar 2023 05:25:17 +0100 Subject: [PATCH 20/32] Add RegisterMessageCallback for d3d12 --- vendor/directx/d3d12/d3d12.odin | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/vendor/directx/d3d12/d3d12.odin b/vendor/directx/d3d12/d3d12.odin index 1e1d8de84..244b107e1 100644 --- a/vendor/directx/d3d12/d3d12.odin +++ b/vendor/directx/d3d12/d3d12.odin @@ -4870,6 +4870,26 @@ IInfoQueue_VTable :: struct { GetMuteDebugOutput: proc "stdcall" (this: ^IInfoQueue) -> BOOL, } +MESSAGE_CALLBACK_FLAGS :: distinct bit_set[MESSAGE_CALLBACK_FLAG; u32] +MESSAGE_CALLBACK_FLAG :: enum +{ + IGNORE_FILTERS = 0, +} + +PFN_MESSAGE_CALLBACK :: #type proc "c" (Category: MESSAGE_CATEGORY, Severity: MESSAGE_SEVERITY, ID: MESSAGE_ID, pDescription: cstring, pContext: rawptr) + +IInfoQueue1_UUID_STRING :: "2852dd88-b484-4c0c-b6b1-67168500e600" +IInfoQueue1_UUID := &IID{0x2852dd88, 0xb484, 0x4c0c, {0xb6, 0xb1, 0x67, 0x16, 0x85, 0x00, 0xe6, 0x00}} +IInfoQueue1 :: struct #raw_union { + #subtype iinfo_queue: IInfoQueue, + using idxgiinfoqueue1_vtable: ^IInfoQueue1_VTable, +} +IInfoQueue1_VTable :: struct { + using idxgiinfoqueue_vtable: IInfoQueue_VTable, + RegisterMessageCallback: proc "stdcall" (this: ^IInfoQueue1, CallbackFunc: PFN_MESSAGE_CALLBACK, CallbackFilterFlags: MESSAGE_CALLBACK_FLAGS, pContext: rawptr, pCallbackCookie: ^u32) -> HRESULT, + UnregisterMessageCallback: proc "stdcall" (this: ^IInfoQueue1, pCallbackCookie: u32) -> HRESULT, +} + PFN_CREATE_DEVICE :: #type proc "c" (a0: ^IUnknown, a1: FEATURE_LEVEL, a2: ^IID, a3: ^rawptr) -> HRESULT PFN_GET_DEBUG_INTERFACE :: #type proc "c" (a0: ^IID, a1: ^rawptr) -> HRESULT From bf91fcc6f72b854b6a63403f38b5c8d6817cb10d Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 12 Mar 2023 12:39:31 +0000 Subject: [PATCH 21/32] Improve type checking on polymorphic unions --- src/check_type.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/check_type.cpp b/src/check_type.cpp index fabbe54c4..7444f88be 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -674,6 +674,10 @@ gb_internal void check_union_type(CheckerContext *ctx, Type *union_type, Ast *no for_array(i, ut->variants) { Ast *node = ut->variants[i]; Type *t = check_type_expr(ctx, node, nullptr); + if (union_type->Union.is_polymorphic && poly_operands == nullptr) { + // NOTE(bill): don't add any variants if this is this is an unspecialized polymorphic record + continue; + } if (t != nullptr && t != t_invalid) { bool ok = true; t = default_type(t); @@ -686,8 +690,12 @@ gb_internal void check_union_type(CheckerContext *ctx, Type *union_type, Ast *no for_array(j, variants) { if (are_types_identical(t, variants[j])) { ok = false; + ERROR_BLOCK(); gbString str = type_to_string(t); error(node, "Duplicate variant type '%s'", str); + if (j < ut->variants.count) { + error_line("\tPrevious found at %s\n", token_pos_to_string(ast_token(ut->variants[j]).pos)); + } gb_string_free(str); break; } From 93f7d3bfb9addc2203596e3f281f1f5f99b2f6a2 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 12 Mar 2023 16:33:21 +0000 Subject: [PATCH 22/32] Allow `case nil` within a type switch statement (experimental idea) --- src/check_stmt.cpp | 28 ++++++++++++++++++++++++++-- src/llvm_backend_stmt.cpp | 19 ++++++++++++++----- 2 files changed, 40 insertions(+), 7 deletions(-) diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index fcd87e1a5..4e6623fc1 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -1184,6 +1184,8 @@ gb_internal void check_type_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_ return; } + + Ast *nil_seen = nullptr; PtrSet seen = {}; defer (ptr_set_destroy(&seen)); @@ -1194,6 +1196,7 @@ gb_internal void check_type_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_ } ast_node(cc, CaseClause, stmt); + bool saw_nil = false; // TODO(bill): Make robust Type *bt = base_type(type_deref(x.type)); @@ -1202,6 +1205,25 @@ gb_internal void check_type_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_ if (type_expr != nullptr) { // Otherwise it's a default expression Operand y = {}; check_expr_or_type(ctx, &y, type_expr); + + if (is_operand_nil(y)) { + if (!type_has_nil(type_deref(x.type))) { + error(type_expr, "'nil' case is not allowed for the type '%s'", type_to_string(type_deref(x.type))); + continue; + } + saw_nil = true; + + if (nil_seen) { + ERROR_BLOCK(); + error(type_expr, "'nil' case has already been handled previously"); + error_line("\t 'nil' was already previously seen at %s", token_pos_to_string(ast_token(nil_seen).pos)); + } else { + nil_seen = type_expr; + } + case_type = y.type; + continue; + } + if (y.mode != Addressing_Type) { gbString str = expr_to_string(type_expr); error(type_expr, "Expected a type as a case, got %s", str); @@ -1255,14 +1277,16 @@ gb_internal void check_type_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_ is_reference = true; } - if (cc->list.count > 1) { + if (cc->list.count > 1 || saw_nil) { case_type = nullptr; } if (case_type == nullptr) { case_type = x.type; } if (switch_kind == TypeSwitch_Any) { - add_type_info_type(ctx, case_type); + if (!is_type_untyped(case_type)) { + add_type_info_type(ctx, case_type); + } } check_open_scope(ctx, stmt); diff --git a/src/llvm_backend_stmt.cpp b/src/llvm_backend_stmt.cpp index 99a16094a..c7f8590f9 100644 --- a/src/llvm_backend_stmt.cpp +++ b/src/llvm_backend_stmt.cpp @@ -1423,9 +1423,11 @@ gb_internal void lb_build_type_switch_stmt(lbProcedure *p, AstTypeSwitchStmt *ss continue; } Entity *case_entity = implicit_entity_of_node(clause); - max_size = gb_max(max_size, type_size_of(case_entity->type)); - max_align = gb_max(max_align, type_align_of(case_entity->type)); - variants_found = true; + if (!is_type_untyped_nil(case_entity->type)) { + max_size = gb_max(max_size, type_size_of(case_entity->type)); + max_align = gb_max(max_align, type_align_of(case_entity->type)); + variants_found = true; + } } if (variants_found) { Type *t = alloc_type_array(t_u8, max_size); @@ -1449,6 +1451,8 @@ gb_internal void lb_build_type_switch_stmt(lbProcedure *p, AstTypeSwitchStmt *ss if (p->debug_info != nullptr) { LLVMSetCurrentDebugLocation2(p->builder, lb_debug_location_from_ast(p, clause)); } + + bool saw_nil = false; for (Ast *type_expr : cc->list) { Type *case_type = type_of_expr(type_expr); lbValue on_val = {}; @@ -1457,7 +1461,12 @@ gb_internal void lb_build_type_switch_stmt(lbProcedure *p, AstTypeSwitchStmt *ss on_val = lb_const_union_tag(m, ut, case_type); } else if (switch_kind == TypeSwitch_Any) { - on_val = lb_typeid(m, case_type); + if (is_type_untyped_nil(case_type)) { + saw_nil = true; + on_val = lb_const_nil(m, t_typeid); + } else { + on_val = lb_typeid(m, case_type); + } } GB_ASSERT(on_val.value != nullptr); LLVMAddCase(switch_instr, on_val.value, body->block); @@ -1469,7 +1478,7 @@ gb_internal void lb_build_type_switch_stmt(lbProcedure *p, AstTypeSwitchStmt *ss bool by_reference = (case_entity->flags & EntityFlag_Value) == 0; - if (cc->list.count == 1) { + if (cc->list.count == 1 && !saw_nil) { lbValue data = {}; if (switch_kind == TypeSwitch_Union) { data = union_data; From 5f3b6c9722007d731193a90f97e566127120f6ed Mon Sep 17 00:00:00 2001 From: bumbread Date: Mon, 13 Mar 2023 20:25:13 +1100 Subject: [PATCH 23/32] Added -no-tls flag --- src/build_settings.cpp | 1 + src/check_decl.cpp | 5 ++++- src/main.cpp | 9 +++++++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 9aee03676..1ca537c01 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -275,6 +275,7 @@ struct BuildContext { bool no_output_files; bool no_crt; bool no_entry_point; + bool no_tls; bool use_lld; bool vet; bool vet_extra; diff --git a/src/check_decl.cpp b/src/check_decl.cpp index 7978aa0ef..828009b3d 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -1143,9 +1143,12 @@ gb_internal void check_global_variable_decl(CheckerContext *ctx, Entity *&e, Ast if (is_arch_wasm() && e->Variable.thread_local_model.len != 0) { e->Variable.thread_local_model.len = 0; - // NOTE(bill): ignore this message for the time begin + // NOTE(bill): ignore this message for the time being // error(e->token, "@(thread_local) is not supported for this target platform"); } + if(build_context.no_tls) { + e->Variable.thread_local_model.len = 0; + } String context_name = str_lit("variable declaration"); diff --git a/src/main.cpp b/src/main.cpp index 066675b36..66d860bc0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -634,6 +634,7 @@ enum BuildFlagKind { BuildFlag_Microarch, BuildFlag_TargetFeatures, BuildFlag_MinimumOSVersion, + BuildFlag_NoTLS, BuildFlag_RelocMode, BuildFlag_DisableRedZone, @@ -794,6 +795,7 @@ gb_internal bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_Debug, str_lit("debug"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_DisableAssert, str_lit("disable-assert"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_NoBoundsCheck, str_lit("no-bounds-check"), BuildFlagParam_None, Command__does_check); + add_flag(&build_flags, BuildFlag_NoTLS, str_lit("no-tls"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_NoDynamicLiterals, str_lit("no-dynamic-literals"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_NoCRT, str_lit("no-crt"), BuildFlagParam_None, Command__does_build); add_flag(&build_flags, BuildFlag_NoEntryPoint, str_lit("no-entry-point"), BuildFlagParam_None, Command__does_check &~ Command_test); @@ -1312,6 +1314,9 @@ gb_internal bool parse_build_flags(Array args) { case BuildFlag_NoEntryPoint: build_context.no_entry_point = true; break; + case BuildFlag_NoTLS: + build_context.no_tls = true; + break; case BuildFlag_UseLLD: build_context.use_lld = true; break; @@ -2064,6 +2069,10 @@ gb_internal void print_show_help(String const arg0, String const &command) { print_usage_line(2, "Disables automatic linking with the C Run Time"); print_usage_line(0, ""); + print_usage_line(1, "-no-tls"); + print_usage_line(2, "Ignore @thread_local attribute, effectively treating the program as if it is single-threaded"); + print_usage_line(0, ""); + print_usage_line(1, "-lld"); print_usage_line(2, "Use the LLD linker rather than the default"); print_usage_line(0, ""); From ede57720fd90724c4f684fab3794575215b467ea Mon Sep 17 00:00:00 2001 From: Marko <54064471+markodevv@users.noreply.github.com> Date: Mon, 13 Mar 2023 23:08:15 +0100 Subject: [PATCH 24/32] Fix brace style and indentation --- vendor/directx/d3d12/d3d12.odin | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/vendor/directx/d3d12/d3d12.odin b/vendor/directx/d3d12/d3d12.odin index 244b107e1..e84474aac 100644 --- a/vendor/directx/d3d12/d3d12.odin +++ b/vendor/directx/d3d12/d3d12.odin @@ -4871,9 +4871,8 @@ IInfoQueue_VTable :: struct { } MESSAGE_CALLBACK_FLAGS :: distinct bit_set[MESSAGE_CALLBACK_FLAG; u32] -MESSAGE_CALLBACK_FLAG :: enum -{ - IGNORE_FILTERS = 0, +MESSAGE_CALLBACK_FLAG :: enum { + IGNORE_FILTERS = 0, } PFN_MESSAGE_CALLBACK :: #type proc "c" (Category: MESSAGE_CATEGORY, Severity: MESSAGE_SEVERITY, ID: MESSAGE_ID, pDescription: cstring, pContext: rawptr) From 5134d6bc63cf39cc987bf5a11a724ad3db69a0a1 Mon Sep 17 00:00:00 2001 From: bumbread Date: Tue, 14 Mar 2023 16:32:42 +1100 Subject: [PATCH 25/32] rename -no-tls to -no-thread-local --- src/build_settings.cpp | 2 +- src/check_decl.cpp | 2 +- src/main.cpp | 10 +++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 1ca537c01..c97973753 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -275,7 +275,7 @@ struct BuildContext { bool no_output_files; bool no_crt; bool no_entry_point; - bool no_tls; + bool no_thread_local; bool use_lld; bool vet; bool vet_extra; diff --git a/src/check_decl.cpp b/src/check_decl.cpp index 828009b3d..5c25dd6a3 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -1146,7 +1146,7 @@ gb_internal void check_global_variable_decl(CheckerContext *ctx, Entity *&e, Ast // NOTE(bill): ignore this message for the time being // error(e->token, "@(thread_local) is not supported for this target platform"); } - if(build_context.no_tls) { + if(build_context.no_thread_local) { e->Variable.thread_local_model.len = 0; } diff --git a/src/main.cpp b/src/main.cpp index 66d860bc0..9a2a1ebf8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -634,7 +634,7 @@ enum BuildFlagKind { BuildFlag_Microarch, BuildFlag_TargetFeatures, BuildFlag_MinimumOSVersion, - BuildFlag_NoTLS, + BuildFlag_NoThreadLocal, BuildFlag_RelocMode, BuildFlag_DisableRedZone, @@ -795,7 +795,7 @@ gb_internal bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_Debug, str_lit("debug"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_DisableAssert, str_lit("disable-assert"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_NoBoundsCheck, str_lit("no-bounds-check"), BuildFlagParam_None, Command__does_check); - add_flag(&build_flags, BuildFlag_NoTLS, str_lit("no-tls"), BuildFlagParam_None, Command__does_check); + add_flag(&build_flags, BuildFlag_NoThreadLocal, str_lit("no-thread-local"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_NoDynamicLiterals, str_lit("no-dynamic-literals"), BuildFlagParam_None, Command__does_check); add_flag(&build_flags, BuildFlag_NoCRT, str_lit("no-crt"), BuildFlagParam_None, Command__does_build); add_flag(&build_flags, BuildFlag_NoEntryPoint, str_lit("no-entry-point"), BuildFlagParam_None, Command__does_check &~ Command_test); @@ -1314,8 +1314,8 @@ gb_internal bool parse_build_flags(Array args) { case BuildFlag_NoEntryPoint: build_context.no_entry_point = true; break; - case BuildFlag_NoTLS: - build_context.no_tls = true; + case BuildFlag_NoThreadLocal: + build_context.no_thread_local = true; break; case BuildFlag_UseLLD: build_context.use_lld = true; @@ -2069,7 +2069,7 @@ gb_internal void print_show_help(String const arg0, String const &command) { print_usage_line(2, "Disables automatic linking with the C Run Time"); print_usage_line(0, ""); - print_usage_line(1, "-no-tls"); + print_usage_line(1, "-no-thread-local"); print_usage_line(2, "Ignore @thread_local attribute, effectively treating the program as if it is single-threaded"); print_usage_line(0, ""); From 8d5c8658148a7bfa8c1dd477f4b4ef7c55bc862e Mon Sep 17 00:00:00 2001 From: Florian Behr Date: Tue, 14 Mar 2023 13:39:08 +0100 Subject: [PATCH 26/32] Fix missing commas in -target-featues string by adding missing i increment. --- src/build_settings.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 9aee03676..a2881f801 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -1369,6 +1369,7 @@ gb_internal char const *target_features_set_to_cstring(gbAllocator allocator, bo gb_memmove(features + len, feature.text, feature.len); len += feature.len; if (with_quotes) features[len++] = '"'; + i += 1; } features[len++] = 0; From 5bbdbadc25f23ed85b18771c5dbf24ed053aa047 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 14 Mar 2023 14:05:23 +0000 Subject: [PATCH 27/32] Remove `where ORD(E)` on procedures that don't need it --- core/slice/sort.odin | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/slice/sort.odin b/core/slice/sort.odin index 8177205ed..b146e03c3 100644 --- a/core/slice/sort.odin +++ b/core/slice/sort.odin @@ -181,7 +181,7 @@ reverse_sort :: proc(data: $T/[]$E) where ORD(E) { } -reverse_sort_by :: proc(data: $T/[]$E, less: proc(i, j: E) -> bool) where ORD(E) { +reverse_sort_by :: proc(data: $T/[]$E, less: proc(i, j: E) -> bool) { context._internal = rawptr(less) sort_by(data, proc(i, j: E) -> bool { k := (proc(i, j: E) -> bool)(context._internal) @@ -189,7 +189,7 @@ reverse_sort_by :: proc(data: $T/[]$E, less: proc(i, j: E) -> bool) where ORD(E) }) } -reverse_sort_by_cmp :: proc(data: $T/[]$E, cmp: proc(i, j: E) -> Ordering) where ORD(E) { +reverse_sort_by_cmp :: proc(data: $T/[]$E, cmp: proc(i, j: E) -> Ordering) { context._internal = rawptr(cmp) sort_by_cmp(data, proc(i, j: E) -> Ordering { k := (proc(i, j: E) -> Ordering)(context._internal) From 4210aa9ab95becea22eac8c23a688a23aeb02d71 Mon Sep 17 00:00:00 2001 From: Elusive Porpoise <95202750+elusivePorpoise@users.noreply.github.com> Date: Wed, 15 Mar 2023 17:15:25 -0700 Subject: [PATCH 28/32] add SetConsoleOuputCP --- core/sys/windows/kernel32.odin | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/sys/windows/kernel32.odin b/core/sys/windows/kernel32.odin index cf4e9096b..13ffda371 100644 --- a/core/sys/windows/kernel32.odin +++ b/core/sys/windows/kernel32.odin @@ -45,7 +45,8 @@ foreign kernel32 { dwCursorPosition: COORD) -> BOOL --- SetConsoleTextAttribute :: proc(hConsoleOutput: HANDLE, wAttributes: WORD) -> BOOL --- - + SetConsoleOutputCP :: proc(wCodePageID: UINT) -> BOOL --- + GetFileInformationByHandle :: proc(hFile: HANDLE, lpFileInformation: LPBY_HANDLE_FILE_INFORMATION) -> BOOL --- SetHandleInformation :: proc(hObject: HANDLE, dwMask: DWORD, From 33ca85bd4e3b6aa7d26f6a601374d33a424849a0 Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Thu, 16 Mar 2023 10:59:19 +0100 Subject: [PATCH 29/32] Fix #2385 --- vendor/directx/dxc/dxcapi.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/directx/dxc/dxcapi.odin b/vendor/directx/dxc/dxcapi.odin index 8153976b6..aa0bb8443 100644 --- a/vendor/directx/dxc/dxcapi.odin +++ b/vendor/directx/dxc/dxcapi.odin @@ -102,7 +102,7 @@ IBlobEncoding :: struct #raw_union { } IBlobEncoding_VTable :: struct { using idxcblob_vtable: IBlob_VTable, - GetEncoding: proc "stdcall" (pKnown: ^BOOL, pCodePage: ^u32) -> HRESULT, + GetEncoding: proc "stdcall" (this: ^IBlobEncoding, pKnown: ^BOOL, pCodePage: ^u32) -> HRESULT, } IBlobUtf16_UUID_STRING :: "A3F84EAB-0FAA-497E-A39C-EE6ED60B2D84" From 243a3f50067de8aa2dd069cbc92afc906b40bea8 Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Thu, 16 Mar 2023 12:35:05 +0100 Subject: [PATCH 30/32] Fix #2386 --- core/net/socket.odin | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/net/socket.odin b/core/net/socket.odin index a24ae8a0b..8cdf7cceb 100644 --- a/core/net/socket.odin +++ b/core/net/socket.odin @@ -118,6 +118,9 @@ make_unbound_udp_socket :: proc(family: Address_Family) -> (socket: UDP_Socket, The `bound_address` is the address of the network interface that you want to use, or a loopback address if you don't care which to use. */ make_bound_udp_socket :: proc(bound_address: Address, port: int) -> (socket: UDP_Socket, err: Network_Error) { + if bound_address == nil { + return {}, .Bad_Address + } socket = make_unbound_udp_socket(family_from_address(bound_address)) or_return bind(socket, {bound_address, port}) or_return return From 09a0dad1159385f22a624258ba43069d3e20c368 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 16 Mar 2023 12:43:10 +0000 Subject: [PATCH 31/32] Add `contextless` to internal `parse_hex` call --- core/strconv/strconv.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/strconv/strconv.odin b/core/strconv/strconv.odin index b96dca19a..e11ce471d 100644 --- a/core/strconv/strconv.odin +++ b/core/strconv/strconv.odin @@ -765,7 +765,7 @@ parse_f64_prefix :: proc(str: string) -> (value: f64, nr: int, ok: bool) { return } - parse_hex :: proc(s: string, mantissa: u64, exp: int, neg, trunc: bool) -> (f64, bool) { + parse_hex :: proc "contextless" (s: string, mantissa: u64, exp: int, neg, trunc: bool) -> (f64, bool) { info := &_f64_info mantissa, exp := mantissa, exp From 0602a16ad66a02e315a71de721885e351b723a2b Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 16 Mar 2023 12:44:03 +0000 Subject: [PATCH 32/32] Reserve memory for procedures when generating the LLVM IR --- src/llvm_backend_general.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp index e398873ee..52ea4f399 100644 --- a/src/llvm_backend_general.cpp +++ b/src/llvm_backend_general.cpp @@ -63,7 +63,6 @@ gb_internal void lb_init_module(lbModule *m, Checker *c) { map_init(&m->values); map_init(&m->soa_values); string_map_init(&m->members); - map_init(&m->procedure_values); string_map_init(&m->procedures); string_map_init(&m->const_strings); map_init(&m->function_type_map); @@ -71,7 +70,13 @@ gb_internal void lb_init_module(lbModule *m, Checker *c) { map_init(&m->hasher_procs); map_init(&m->map_get_procs); map_init(&m->map_set_procs); - array_init(&m->procedures_to_generate, a, 0, 1024); + if (build_context.use_separate_modules) { + array_init(&m->procedures_to_generate, a, 0, 1<<10); + map_init(&m->procedure_values, 1<<11); + } else { + array_init(&m->procedures_to_generate, a, 0, c->info.all_procedures.count); + map_init(&m->procedure_values, c->info.all_procedures.count*2); + } array_init(&m->global_procedures_and_types_to_create, a, 0, 1024); array_init(&m->missing_procedures_to_check, a, 0, 16); map_init(&m->debug_values);