From 9c5e577792eff2cd9c95b590526c17a4e8762d5a Mon Sep 17 00:00:00 2001 From: Steve Waddicor Date: Tue, 29 Jul 2025 21:01:22 +0100 Subject: [PATCH 001/105] Additional obj-c methods for darwin Foundation Added support for NSBitmapImageRep class. Added ability to set contents to a CALayer. I needed these to support a port of Handmade Hero, but they are of general use. --- .../darwin/Foundation/NSBitmapImageRep.odin | 50 +++++++++++++++++++ core/sys/darwin/Foundation/NSWindow.odin | 8 +++ 2 files changed, 58 insertions(+) create mode 100644 core/sys/darwin/Foundation/NSBitmapImageRep.odin diff --git a/core/sys/darwin/Foundation/NSBitmapImageRep.odin b/core/sys/darwin/Foundation/NSBitmapImageRep.odin new file mode 100644 index 000000000..2fcdf6530 --- /dev/null +++ b/core/sys/darwin/Foundation/NSBitmapImageRep.odin @@ -0,0 +1,50 @@ +package objc_Foundation + +import "base:intrinsics" + +@(objc_class="NSBitmapImageRep") +BitmapImageRep :: struct { using _: Object } + +@(objc_type=BitmapImageRep, objc_name="alloc", objc_is_class_method=true) +BitmapImageRep_alloc :: proc "c" () -> ^BitmapImageRep { + return msgSend(^BitmapImageRep, BitmapImageRep, "alloc") +} + +@(objc_type=BitmapImageRep, objc_name="initWithBitmapDataPlanes") +BitmapImageRep_initWithBitmapDataPlanes :: proc "c" ( + self: ^BitmapImageRep, + bitmapDataPlanes: ^^u8, + pixelsWide: Integer, + pixelsHigh: Integer, + bitsPerSample: Integer, + samplesPerPixel: Integer, + hasAlpha: bool, + isPlanar: bool, + colorSpaceName: ^String, + bytesPerRow: Integer, + bitsPerPixel: Integer) -> ^BitmapImageRep { + + return msgSend(^BitmapImageRep, + self, + "initWithBitmapDataPlanes:pixelsWide:pixelsHigh:bitsPerSample:samplesPerPixel:hasAlpha:isPlanar:colorSpaceName:bytesPerRow:bitsPerPixel:", + bitmapDataPlanes, + pixelsWide, + pixelsHigh, + bitsPerSample, + samplesPerPixel, + hasAlpha, + isPlanar, + colorSpaceName, + bytesPerRow, + bitsPerPixel) +} + +@(objc_type=BitmapImageRep, objc_name="bitmapData") +BitmapImageRep_bitmapData :: proc "c" (self: ^BitmapImageRep) -> rawptr { + return msgSend(rawptr, self, "bitmapData") +} + +@(objc_type=BitmapImageRep, objc_name="CGImage") +BitmapImageRep_CGImage :: proc "c" (self: ^BitmapImageRep) -> rawptr { + return msgSend(rawptr, self, "CGImage") +} diff --git a/core/sys/darwin/Foundation/NSWindow.odin b/core/sys/darwin/Foundation/NSWindow.odin index f113dd3df..fb280aa79 100644 --- a/core/sys/darwin/Foundation/NSWindow.odin +++ b/core/sys/darwin/Foundation/NSWindow.odin @@ -568,6 +568,14 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla @(objc_class="CALayer") Layer :: struct { using _: Object } +@(objc_type=Layer, objc_name="contents") +Layer_contents :: proc "c" (self: ^Layer) -> rawptr { + return msgSend(rawptr, self, "contents") +} +@(objc_type=Layer, objc_name="setContents") +Layer_setContents :: proc "c" (self: ^Layer, contents: rawptr) { + msgSend(nil, self, "setContents:", contents) +} @(objc_type=Layer, objc_name="contentsScale") Layer_contentsScale :: proc "c" (self: ^Layer) -> Float { return msgSend(Float, self, "contentsScale") From 9dfce3da86419ae477a97113bea381c7f4be104d Mon Sep 17 00:00:00 2001 From: Steve Waddicor Date: Fri, 1 Aug 2025 23:06:04 +0100 Subject: [PATCH 002/105] Convert leading spaces to tabs --- .../darwin/Foundation/NSBitmapImageRep.odin | 52 +++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/core/sys/darwin/Foundation/NSBitmapImageRep.odin b/core/sys/darwin/Foundation/NSBitmapImageRep.odin index 2fcdf6530..059a75e43 100644 --- a/core/sys/darwin/Foundation/NSBitmapImageRep.odin +++ b/core/sys/darwin/Foundation/NSBitmapImageRep.odin @@ -7,44 +7,44 @@ BitmapImageRep :: struct { using _: Object } @(objc_type=BitmapImageRep, objc_name="alloc", objc_is_class_method=true) BitmapImageRep_alloc :: proc "c" () -> ^BitmapImageRep { - return msgSend(^BitmapImageRep, BitmapImageRep, "alloc") + return msgSend(^BitmapImageRep, BitmapImageRep, "alloc") } @(objc_type=BitmapImageRep, objc_name="initWithBitmapDataPlanes") BitmapImageRep_initWithBitmapDataPlanes :: proc "c" ( - self: ^BitmapImageRep, - bitmapDataPlanes: ^^u8, - pixelsWide: Integer, - pixelsHigh: Integer, - bitsPerSample: Integer, - samplesPerPixel: Integer, - hasAlpha: bool, - isPlanar: bool, - colorSpaceName: ^String, - bytesPerRow: Integer, - bitsPerPixel: Integer) -> ^BitmapImageRep { + self: ^BitmapImageRep, + bitmapDataPlanes: ^^u8, + pixelsWide: Integer, + pixelsHigh: Integer, + bitsPerSample: Integer, + samplesPerPixel: Integer, + hasAlpha: bool, + isPlanar: bool, + colorSpaceName: ^String, + bytesPerRow: Integer, + bitsPerPixel: Integer) -> ^BitmapImageRep { return msgSend(^BitmapImageRep, - self, - "initWithBitmapDataPlanes:pixelsWide:pixelsHigh:bitsPerSample:samplesPerPixel:hasAlpha:isPlanar:colorSpaceName:bytesPerRow:bitsPerPixel:", - bitmapDataPlanes, - pixelsWide, - pixelsHigh, - bitsPerSample, - samplesPerPixel, - hasAlpha, - isPlanar, - colorSpaceName, - bytesPerRow, - bitsPerPixel) + self, + "initWithBitmapDataPlanes:pixelsWide:pixelsHigh:bitsPerSample:samplesPerPixel:hasAlpha:isPlanar:colorSpaceName:bytesPerRow:bitsPerPixel:", + bitmapDataPlanes, + pixelsWide, + pixelsHigh, + bitsPerSample, + samplesPerPixel, + hasAlpha, + isPlanar, + colorSpaceName, + bytesPerRow, + bitsPerPixel) } @(objc_type=BitmapImageRep, objc_name="bitmapData") BitmapImageRep_bitmapData :: proc "c" (self: ^BitmapImageRep) -> rawptr { - return msgSend(rawptr, self, "bitmapData") + return msgSend(rawptr, self, "bitmapData") } @(objc_type=BitmapImageRep, objc_name="CGImage") BitmapImageRep_CGImage :: proc "c" (self: ^BitmapImageRep) -> rawptr { - return msgSend(rawptr, self, "CGImage") + return msgSend(rawptr, self, "CGImage") } From 2561427dd396a69cd49eb02c0814c4e8e8b3a08f Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 2 Aug 2025 11:00:15 +0100 Subject: [PATCH 003/105] Add `string16` and `cstring16` (UTF-16 based strings) --- base/runtime/core.odin | 13 ++- base/runtime/core_builtin.odin | 28 +++++- base/runtime/internal.odin | 87 +++++++++++++++++ core/fmt/fmt.odin | 76 +++++++++++++++ core/io/io.odin | 24 +++++ core/io/util.odin | 27 ++++++ core/unicode/utf16/utf16.odin | 20 ++++ src/build_settings.cpp | 8 +- src/cached.cpp | 2 +- src/check_builtin.cpp | 9 +- src/check_decl.cpp | 6 ++ src/check_expr.cpp | 88 +++++++++++++++++ src/checker.cpp | 16 +-- src/common.cpp | 2 +- src/exact_value.cpp | 52 +++++++++- src/llvm_backend_expr.cpp | 72 ++++++++++++++ src/llvm_backend_general.cpp | 31 ++++++ src/llvm_backend_proc.cpp | 9 ++ src/llvm_backend_type.cpp | 28 +++++- src/llvm_backend_utility.cpp | 12 +++ src/main.cpp | 8 +- src/microsoft_craziness.h | 4 +- src/path.cpp | 8 +- src/string.cpp | 172 +++++++++++++++++++++++++++++---- src/types.cpp | 133 +++++++++++++++++++++---- 25 files changed, 873 insertions(+), 62 deletions(-) diff --git a/base/runtime/core.odin b/base/runtime/core.odin index baecb4146..fe40427ff 100644 --- a/base/runtime/core.odin +++ b/base/runtime/core.odin @@ -73,7 +73,7 @@ Type_Info_Rune :: struct {} Type_Info_Float :: struct {endianness: Platform_Endianness} Type_Info_Complex :: struct {} Type_Info_Quaternion :: struct {} -Type_Info_String :: struct {is_cstring: bool} +Type_Info_String :: struct {is_cstring: bool, is_utf16: bool} Type_Info_Boolean :: struct {} Type_Info_Any :: struct {} Type_Info_Type_Id :: struct {} @@ -397,6 +397,11 @@ Raw_String :: struct { len: int, } +Raw_String16 :: struct { + data: [^]u16, + len: int, +} + Raw_Slice :: struct { data: rawptr, len: int, @@ -450,6 +455,12 @@ Raw_Cstring :: struct { } #assert(size_of(Raw_Cstring) == size_of(cstring)) +Raw_Cstring16 :: struct { + data: [^]u16, +} +#assert(size_of(Raw_Cstring16) == size_of(cstring16)) + + Raw_Soa_Pointer :: struct { data: rawptr, index: int, diff --git a/base/runtime/core_builtin.odin b/base/runtime/core_builtin.odin index e2ba14f3a..09118998c 100644 --- a/base/runtime/core_builtin.odin +++ b/base/runtime/core_builtin.odin @@ -86,11 +86,26 @@ copy_from_string :: proc "contextless" (dst: $T/[]$E/u8, src: $S/string) -> int } return n } + +// `copy_from_string16` is a built-in procedure that copies elements from a source string `src` to a destination slice `dst`. +// The source and destination may overlap. Copy returns the number of elements copied, which will be the minimum +// of len(src) and len(dst). +// +// Prefer the procedure group `copy`. +@builtin +copy_from_string16 :: proc "contextless" (dst: $T/[]$E/u16, src: $S/string16) -> int { + n := min(len(dst), len(src)) + if n > 0 { + intrinsics.mem_copy(raw_data(dst), raw_data(src), n*size_of(u16)) + } + return n +} + // `copy` is a built-in procedure that copies elements from a source slice/string `src` to a destination slice `dst`. // The source and destination may overlap. Copy returns the number of elements copied, which will be the minimum // of len(src) and len(dst). @builtin -copy :: proc{copy_slice, copy_from_string} +copy :: proc{copy_slice, copy_from_string, copy_from_string16} @@ -285,6 +300,15 @@ delete_map :: proc(m: $T/map[$K]$V, loc := #caller_location) -> Allocator_Error } +@builtin +delete_string16 :: proc(str: string16, allocator := context.allocator, loc := #caller_location) -> Allocator_Error { + return mem_free_with_size(raw_data(str), len(str)*size_of(u16), allocator, loc) +} +@builtin +delete_cstring16 :: proc(str: cstring16, allocator := context.allocator, loc := #caller_location) -> Allocator_Error { + return mem_free((^u16)(str), allocator, loc) +} + // `delete` will try to free the underlying data of the passed built-in data structure (string, cstring, dynamic array, slice, or map), with the given `allocator` if the allocator supports this operation. // // Note: Prefer `delete` over the specific `delete_*` procedures where possible. @@ -297,6 +321,8 @@ delete :: proc{ delete_map, delete_soa_slice, delete_soa_dynamic_array, + delete_string16, + delete_cstring16, } diff --git a/base/runtime/internal.odin b/base/runtime/internal.odin index 907b187f1..660af58ab 100644 --- a/base/runtime/internal.odin +++ b/base/runtime/internal.odin @@ -493,12 +493,40 @@ string_cmp :: proc "contextless" (a, b: string) -> int { return ret } + +string16_eq :: proc "contextless" (lhs, rhs: string16) -> bool { + x := transmute(Raw_String16)lhs + y := transmute(Raw_String16)rhs + if x.len != y.len { + return false + } + return #force_inline memory_equal(x.data, y.data, x.len*size_of(u16)) +} + +string16_cmp :: proc "contextless" (a, b: string16) -> int { + x := transmute(Raw_String16)a + y := transmute(Raw_String16)b + + ret := memory_compare(x.data, y.data, min(x.len, y.len)*size_of(u16)) + if ret == 0 && x.len != y.len { + return -1 if x.len < y.len else +1 + } + return ret +} + string_ne :: #force_inline proc "contextless" (a, b: string) -> bool { return !string_eq(a, b) } string_lt :: #force_inline proc "contextless" (a, b: string) -> bool { return string_cmp(a, b) < 0 } string_gt :: #force_inline proc "contextless" (a, b: string) -> bool { return string_cmp(a, b) > 0 } string_le :: #force_inline proc "contextless" (a, b: string) -> bool { return string_cmp(a, b) <= 0 } string_ge :: #force_inline proc "contextless" (a, b: string) -> bool { return string_cmp(a, b) >= 0 } +string16_ne :: #force_inline proc "contextless" (a, b: string16) -> bool { return !string16_eq(a, b) } +string16_lt :: #force_inline proc "contextless" (a, b: string16) -> bool { return string16_cmp(a, b) < 0 } +string16_gt :: #force_inline proc "contextless" (a, b: string16) -> bool { return string16_cmp(a, b) > 0 } +string16_le :: #force_inline proc "contextless" (a, b: string16) -> bool { return string16_cmp(a, b) <= 0 } +string16_ge :: #force_inline proc "contextless" (a, b: string16) -> bool { return string16_cmp(a, b) >= 0 } + + cstring_len :: proc "contextless" (s: cstring) -> int { p0 := uintptr((^byte)(s)) p := p0 @@ -508,6 +536,16 @@ cstring_len :: proc "contextless" (s: cstring) -> int { return int(p - p0) } +cstring16_len :: proc "contextless" (s: cstring16) -> int { + p := ([^]u16)(s) + n := 0 + for p != nil && p[0] != 0 { + p = p[1:] + n += 1 + } + return n +} + cstring_to_string :: proc "contextless" (s: cstring) -> string { if s == nil { return "" @@ -517,6 +555,15 @@ cstring_to_string :: proc "contextless" (s: cstring) -> string { return transmute(string)Raw_String{ptr, n} } +cstring16_to_string16 :: proc "contextless" (s: cstring16) -> string16 { + if s == nil { + return "" + } + ptr := (^u16)(s) + n := cstring16_len(s) + return transmute(string16)Raw_String16{ptr, n} +} + cstring_eq :: proc "contextless" (lhs, rhs: cstring) -> bool { x := ([^]byte)(lhs) @@ -559,6 +606,46 @@ cstring_gt :: #force_inline proc "contextless" (a, b: cstring) -> bool { return cstring_le :: #force_inline proc "contextless" (a, b: cstring) -> bool { return cstring_cmp(a, b) <= 0 } cstring_ge :: #force_inline proc "contextless" (a, b: cstring) -> bool { return cstring_cmp(a, b) >= 0 } +cstring16_eq :: proc "contextless" (lhs, rhs: cstring16) -> bool { + x := ([^]u16)(lhs) + y := ([^]u16)(rhs) + if x == y { + return true + } + if (x == nil) ~ (y == nil) { + return false + } + xn := cstring16_len(lhs) + yn := cstring16_len(rhs) + if xn != yn { + return false + } + return #force_inline memory_equal(x, y, xn*size_of(u16)) +} + +cstring16_cmp :: proc "contextless" (lhs, rhs: cstring16) -> int { + x := ([^]u16)(lhs) + y := ([^]u16)(rhs) + if x == y { + return 0 + } + if (x == nil) ~ (y == nil) { + return -1 if x == nil else +1 + } + xn := cstring16_len(lhs) + yn := cstring16_len(rhs) + ret := memory_compare(x, y, min(xn, yn)*size_of(u16)) + if ret == 0 && xn != yn { + return -1 if xn < yn else +1 + } + return ret +} + +cstring16_ne :: #force_inline proc "contextless" (a, b: cstring16) -> bool { return !cstring16_eq(a, b) } +cstring16_lt :: #force_inline proc "contextless" (a, b: cstring16) -> bool { return cstring16_cmp(a, b) < 0 } +cstring16_gt :: #force_inline proc "contextless" (a, b: cstring16) -> bool { return cstring16_cmp(a, b) > 0 } +cstring16_le :: #force_inline proc "contextless" (a, b: cstring16) -> bool { return cstring16_cmp(a, b) <= 0 } +cstring16_ge :: #force_inline proc "contextless" (a, b: cstring16) -> bool { return cstring16_cmp(a, b) >= 0 } complex32_eq :: #force_inline proc "contextless" (a, b: complex32) -> bool { return real(a) == real(b) && imag(a) == imag(b) } complex32_ne :: #force_inline proc "contextless" (a, b: complex32) -> bool { return real(a) != real(b) || imag(a) != imag(b) } diff --git a/core/fmt/fmt.odin b/core/fmt/fmt.odin index 0f6470cca..7fe6287d4 100644 --- a/core/fmt/fmt.odin +++ b/core/fmt/fmt.odin @@ -1551,6 +1551,79 @@ fmt_string :: proc(fi: ^Info, s: string, verb: rune) { fmt_cstring :: proc(fi: ^Info, s: cstring, verb: rune) { fmt_string(fi, string(s), verb) } + +// Formats a string UTF-16 with a specific format. +// +// Inputs: +// - fi: Pointer to the Info struct containing format settings. +// - s: The string to format. +// - verb: The format specifier character (e.g. 's', 'v', 'q', 'x', 'X'). +// +fmt_string16 :: proc(fi: ^Info, s: string16, verb: rune) { + s, verb := s, verb + if ol, ok := fi.optional_len.?; ok { + s = s[:clamp(ol, 0, len(s))] + } + if !fi.in_bad && fi.record_level > 0 && verb == 'v' { + verb = 'q' + } + + switch verb { + case 's', 'v': + if fi.width_set { + if fi.width > len(s) { + if fi.minus { + io.write_string16(fi.writer, s, &fi.n) + } + + for _ in 0.. 0 && space { + io.write_byte(fi.writer, ' ', &fi.n) + } + char_set := __DIGITS_UPPER + if verb == 'x' { + char_set = __DIGITS_LOWER + } + _fmt_int(fi, u64(s[i]), 16, false, bit_size=16, digits=char_set) + } + + case: + fmt_bad_verb(fi, verb) + } +} +// Formats a C-style UTF-16 string with a specific format. +// +// Inputs: +// - fi: Pointer to the Info struct containing format settings. +// - s: The C-style string to format. +// - verb: The format specifier character (Ref fmt_string). +// +fmt_cstring16 :: proc(fi: ^Info, s: cstring16, verb: rune) { + fmt_string16(fi, string16(s), verb) +} + // Formats a raw pointer with a specific format. // // Inputs: @@ -3210,6 +3283,9 @@ fmt_arg :: proc(fi: ^Info, arg: any, verb: rune) { case string: fmt_string(fi, a, verb) case cstring: fmt_cstring(fi, a, verb) + case string16: fmt_string16(fi, a, verb) + case cstring16: fmt_cstring16(fi, a, verb) + case typeid: reflect.write_typeid(fi.writer, a, &fi.n) case i16le: fmt_int(fi, u64(a), true, 16, verb) diff --git a/core/io/io.odin b/core/io/io.odin index c2b44cbdb..5431519bf 100644 --- a/core/io/io.odin +++ b/core/io/io.odin @@ -5,6 +5,7 @@ package io import "base:intrinsics" import "core:unicode/utf8" +import "core:unicode/utf16" // Seek whence values Seek_From :: enum { @@ -314,6 +315,29 @@ write_string :: proc(s: Writer, str: string, n_written: ^int = nil) -> (n: int, return write(s, transmute([]byte)str, n_written) } +// write_string16 writes the contents of the string16 s to w reencoded as utf-8 +write_string16 :: proc(s: Writer, str: string16, n_written: ^int = nil) -> (n: int, err: Error) { + for i := 0; i < len(str); i += 1 { + r := rune(utf16.REPLACEMENT_CHAR) + + switch c := str[i]; { + case c < utf16._surr1, utf16._surr3 <= c: + r = rune(c) + case utf16._surr1 <= c && c < utf16._surr2 && i+1 < len(str) && + utf16._surr2 <= str[i+1] && str[i+1] < utf16._surr3: + r = utf16.decode_surrogate_pair(rune(c), rune(str[i+1])) + i += 1 + } + + w, err := write_rune(s, r, n_written) + n += w + if err != nil { + return + } + } + return +} + // write_rune writes a UTF-8 encoded rune to w. write_rune :: proc(s: Writer, r: rune, n_written: ^int = nil) -> (size: int, err: Error) { defer if err == nil && n_written != nil { diff --git a/core/io/util.odin b/core/io/util.odin index fa98e007b..72983523a 100644 --- a/core/io/util.odin +++ b/core/io/util.odin @@ -264,6 +264,33 @@ write_quoted_string :: proc(w: Writer, str: string, quote: byte = '"', n_written return } +write_quoted_string16 :: proc(w: Writer, str: string16, quote: byte = '"', n_written: ^int = nil, for_json := false) -> (n: int, err: Error) { + defer if n_written != nil { + n_written^ += n + } + write_byte(w, quote, &n) or_return + for width, s := 0, str; len(s) > 0; s = s[width:] { + r := rune(s[0]) + width = 1 + if r >= utf8.RUNE_SELF { + r, width = utf16.decode_rune_in_string(s) + } + if width == 1 && r == utf8.RUNE_ERROR { + write_byte(w, '\\', &n) or_return + write_byte(w, 'x', &n) or_return + write_byte(w, DIGITS_LOWER[s[0]>>4], &n) or_return + write_byte(w, DIGITS_LOWER[s[0]&0xf], &n) or_return + continue + } + + n_wrapper(write_escaped_rune(w, r, quote, false, nil, for_json), &n) or_return + + } + write_byte(w, quote, &n) or_return + return +} + + // writer append a quoted rune into the byte buffer, return the written size write_quoted_rune :: proc(w: Writer, r: rune) -> (n: int) { _write_byte :: #force_inline proc(w: Writer, c: byte) -> int { diff --git a/core/unicode/utf16/utf16.odin b/core/unicode/utf16/utf16.odin index e2bcf7f68..9a8cfe438 100644 --- a/core/unicode/utf16/utf16.odin +++ b/core/unicode/utf16/utf16.odin @@ -106,6 +106,26 @@ decode :: proc(d: []rune, s: []u16) -> (n: int) { return } +decode_rune_in_string :: proc(s: string16) -> (r: rune, width: int) { + r = rune(REPLACEMENT_CHAR) + n := len(s) + if n < 1 { + return + } + width = 1 + + + switch c := s[0]; { + case c < _surr1, _surr3 <= c: + r = rune(c) + case _surr1 <= c && c < _surr2 && 1 < len(s) && + _surr2 <= s[1] && s[1] < _surr3: + r = decode_surrogate_pair(rune(c), rune(s[1])) + width += 1 + } + return +} + rune_count :: proc(s: []u16) -> (n: int) { for i := 0; i < len(s); i += 1 { c := s[i] diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 46a4f9ae5..40bbe41e5 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -1089,7 +1089,7 @@ gb_internal String internal_odin_root_dir(void) { text = gb_alloc_array(permanent_allocator(), wchar_t, len+1); GetModuleFileNameW(nullptr, text, cast(int)len); - path = string16_to_string(heap_allocator(), make_string16(text, len)); + path = string16_to_string(heap_allocator(), make_string16(cast(u16 *)text, len)); for (i = path.len-1; i >= 0; i--) { u8 c = path[i]; @@ -1387,14 +1387,14 @@ gb_internal String path_to_fullpath(gbAllocator a, String s, bool *ok_) { mutex_lock(&fullpath_mutex); - len = GetFullPathNameW(&string16[0], 0, nullptr, nullptr); + len = GetFullPathNameW(cast(wchar_t *)&string16[0], 0, nullptr, nullptr); if (len != 0) { wchar_t *text = gb_alloc_array(permanent_allocator(), wchar_t, len+1); - GetFullPathNameW(&string16[0], len, text, nullptr); + GetFullPathNameW(cast(wchar_t *)&string16[0], len, text, nullptr); mutex_unlock(&fullpath_mutex); text[len] = 0; - result = string16_to_string(a, make_string16(text, len)); + result = string16_to_string(a, make_string16(cast(u16 *)text, len)); result = string_trim_whitespace(result); // Replace Windows style separators diff --git a/src/cached.cpp b/src/cached.cpp index efdadce7b..61b5d01b4 100644 --- a/src/cached.cpp +++ b/src/cached.cpp @@ -231,7 +231,7 @@ Array cache_gather_envs() { wchar_t *curr_string = strings; while (curr_string && *curr_string) { - String16 wstr = make_string16_c(curr_string); + String16 wstr = make_string16_c(cast(u16 *)curr_string); curr_string += wstr.len+1; String str = string16_to_string(temporary_allocator(), wstr); if (string_starts_with(str, str_lit("CURR_DATE_TIME="))) { diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index 974224ed2..d36cf4520 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -2327,6 +2327,9 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As if (is_type_string(op_type) && id == BuiltinProc_len) { if (operand->mode == Addressing_Constant) { mode = Addressing_Constant; + + GB_ASSERT_MSG(!is_type_string16(op_type), "TODO(bill): constant utf-16 string len"); + String str = operand->value.value_string; value = exact_value_i64(str.len); type = t_untyped_integer; @@ -2334,6 +2337,8 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As mode = Addressing_Value; if (is_type_cstring(op_type)) { add_package_dependency(c, "runtime", "cstring_len"); + } else if (is_type_cstring16(op_type)) { + add_package_dependency(c, "runtime", "cstring16_len"); } } } else if (is_type_array(op_type)) { @@ -4683,7 +4688,9 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As break; case Type_Basic: if (t->Basic.kind == Basic_string) { - operand->type = alloc_type_multi_pointer(t_u8); + operand->type = t_u8_multi_ptr; + } else if (t->Basic.kind == Basic_string16) { + operand->type = t_u16_multi_ptr; } break; case Type_Pointer: diff --git a/src/check_decl.cpp b/src/check_decl.cpp index dd4c09e85..af46ee40e 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -815,6 +815,12 @@ gb_internal bool signature_parameter_similar_enough(Type *x, Type *y) { if (sig_compare(is_type_cstring, is_type_u8_multi_ptr, x, y)) { return true; } + if (sig_compare(is_type_cstring16, is_type_u16_ptr, x, y)) { + return true; + } + if (sig_compare(is_type_cstring16, is_type_u16_multi_ptr, x, y)) { + return true; + } if (sig_compare(is_type_uintptr, is_type_rawptr, x, y)) { return true; diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 6723a7580..57073e22f 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -2862,6 +2862,14 @@ gb_internal void add_comparison_procedures_for_fields(CheckerContext *c, Type *t add_package_dependency(c, "runtime", "string_eq"); add_package_dependency(c, "runtime", "string_ne"); break; + case Basic_cstring16: + add_package_dependency(c, "runtime", "cstring16_eq"); + add_package_dependency(c, "runtime", "cstring16_ne"); + break; + case Basic_string16: + add_package_dependency(c, "runtime", "string16_eq"); + add_package_dependency(c, "runtime", "string16_ne"); + break; } break; case Type_Struct: @@ -3035,6 +3043,24 @@ gb_internal void check_comparison(CheckerContext *c, Ast *node, Operand *x, Oper case Token_LtEq: add_package_dependency(c, "runtime", "cstring_le"); break; case Token_GtEq: add_package_dependency(c, "runtime", "cstring_gt"); break; } + } else if (is_type_cstring16(x->type) && is_type_cstring16(y->type)) { + switch (op) { + case Token_CmpEq: add_package_dependency(c, "runtime", "cstring16_eq"); break; + case Token_NotEq: add_package_dependency(c, "runtime", "cstring16_ne"); break; + case Token_Lt: add_package_dependency(c, "runtime", "cstring16_lt"); break; + case Token_Gt: add_package_dependency(c, "runtime", "cstring16_gt"); break; + case Token_LtEq: add_package_dependency(c, "runtime", "cstring16_le"); break; + case Token_GtEq: add_package_dependency(c, "runtime", "cstring16_gt"); break; + } + } else if (is_type_string16(x->type) || is_type_string16(y->type)) { + switch (op) { + case Token_CmpEq: add_package_dependency(c, "runtime", "string16_eq"); break; + case Token_NotEq: add_package_dependency(c, "runtime", "string16_ne"); break; + case Token_Lt: add_package_dependency(c, "runtime", "string16_lt"); break; + case Token_Gt: add_package_dependency(c, "runtime", "string16_gt"); break; + case Token_LtEq: add_package_dependency(c, "runtime", "string16_le"); break; + case Token_GtEq: add_package_dependency(c, "runtime", "string16_gt"); break; + } } else if (is_type_string(x->type) || is_type_string(y->type)) { switch (op) { case Token_CmpEq: add_package_dependency(c, "runtime", "string_eq"); break; @@ -3340,6 +3366,11 @@ gb_internal bool check_is_castable_to(CheckerContext *c, Operand *operand, Type return true; } + // []u16 <-> string16 (not cstring16) + if (is_type_u16_slice(src) && (is_type_string16(dst) && !is_type_cstring16(dst))) { + return true; + } + // cstring -> string if (are_types_identical(src, t_cstring) && are_types_identical(dst, t_string)) { if (operand->mode != Addressing_Constant) { @@ -3347,6 +3378,14 @@ gb_internal bool check_is_castable_to(CheckerContext *c, Operand *operand, Type } return true; } + // cstring16 -> string16 + if (are_types_identical(src, t_cstring16) && are_types_identical(dst, t_string16)) { + if (operand->mode != Addressing_Constant) { + add_package_dependency(c, "runtime", "cstring16_to_string16"); + } + return true; + } + // cstring -> ^u8 if (are_types_identical(src, t_cstring) && is_type_u8_ptr(dst)) { return !is_constant; @@ -3372,6 +3411,34 @@ gb_internal bool check_is_castable_to(CheckerContext *c, Operand *operand, Type if (is_type_rawptr(src) && are_types_identical(dst, t_cstring)) { return !is_constant; } + + // cstring -> ^u16 + if (are_types_identical(src, t_cstring16) && is_type_u16_ptr(dst)) { + return !is_constant; + } + // cstring -> [^]u16 + if (are_types_identical(src, t_cstring16) && is_type_u16_multi_ptr(dst)) { + return !is_constant; + } + // cstring -> rawptr + if (are_types_identical(src, t_cstring16) && is_type_rawptr(dst)) { + return !is_constant; + } + + + // ^u16 -> cstring16 + if (is_type_u16_ptr(src) && are_types_identical(dst, t_cstring16)) { + return !is_constant; + } + // [^]u16 -> cstring + if (is_type_u16_multi_ptr(src) && are_types_identical(dst, t_cstring16)) { + return !is_constant; + } + // rawptr -> cstring16 + if (is_type_rawptr(src) && are_types_identical(dst, t_cstring16)) { + return !is_constant; + } + // proc <-> proc if (is_type_proc(src) && is_type_proc(dst)) { if (is_type_polymorphic(dst)) { @@ -4558,6 +4625,8 @@ gb_internal void convert_to_typed(CheckerContext *c, Operand *operand, Type *tar // target_type = t_untyped_nil; } else if (is_type_cstring(target_type)) { // target_type = t_untyped_nil; + } else if (is_type_cstring16(target_type)) { + // target_type = t_untyped_nil; } else if (!type_has_nil(target_type)) { operand->mode = Addressing_Invalid; convert_untyped_error(c, operand, target_type); @@ -8226,6 +8295,7 @@ gb_internal bool check_set_index_data(Operand *o, Type *t, bool indirection, i64 case Type_Basic: if (t->Basic.kind == Basic_string) { if (o->mode == Addressing_Constant) { + GB_ASSERT(o->value.kind == ExactValue_String); *max_count = o->value.value_string.len; } if (o->mode != Addressing_Constant) { @@ -8233,6 +8303,16 @@ gb_internal bool check_set_index_data(Operand *o, Type *t, bool indirection, i64 } o->type = t_u8; return true; + } else if (t->Basic.kind == Basic_string16) { + if (o->mode == Addressing_Constant) { + GB_ASSERT(o->value.kind == ExactValue_String16); + *max_count = o->value.value_string16.len; + } + if (o->mode != Addressing_Constant) { + o->mode = Addressing_Value; + } + o->type = t_u16; + return true; } else if (t->Basic.kind == Basic_UntypedString) { if (o->mode == Addressing_Constant) { *max_count = o->value.value_string.len; @@ -10879,9 +10959,17 @@ gb_internal ExprKind check_slice_expr(CheckerContext *c, Operand *o, Ast *node, if (t->Basic.kind == Basic_string || t->Basic.kind == Basic_UntypedString) { valid = true; if (o->mode == Addressing_Constant) { + GB_ASSERT(o->value.kind == ExactValue_String); max_count = o->value.value_string.len; } o->type = type_deref(o->type); + } else if (t->Basic.kind == Basic_string16) { + valid = true; + if (o->mode == Addressing_Constant) { + GB_ASSERT(o->value.kind == ExactValue_String16); + max_count = o->value.value_string16.len; + } + o->type = type_deref(o->type); } break; diff --git a/src/checker.cpp b/src/checker.cpp index a1d8f98d7..20da5b19b 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -1363,13 +1363,15 @@ gb_internal void init_universal(void) { } - t_u8_ptr = alloc_type_pointer(t_u8); - t_u8_multi_ptr = alloc_type_multi_pointer(t_u8); - t_int_ptr = alloc_type_pointer(t_int); - t_i64_ptr = alloc_type_pointer(t_i64); - t_f64_ptr = alloc_type_pointer(t_f64); - t_u8_slice = alloc_type_slice(t_u8); - t_string_slice = alloc_type_slice(t_string); + t_u8_ptr = alloc_type_pointer(t_u8); + t_u8_multi_ptr = alloc_type_multi_pointer(t_u8); + t_u16_ptr = alloc_type_pointer(t_u16); + t_u16_multi_ptr = alloc_type_multi_pointer(t_u16); + t_int_ptr = alloc_type_pointer(t_int); + t_i64_ptr = alloc_type_pointer(t_i64); + t_f64_ptr = alloc_type_pointer(t_f64); + t_u8_slice = alloc_type_slice(t_u8); + t_string_slice = alloc_type_slice(t_string); // intrinsics types for objective-c stuff { diff --git a/src/common.cpp b/src/common.cpp index ad1e5a851..b3761fc36 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -669,7 +669,7 @@ gb_internal gb_inline f64 gb_sqrt(f64 x) { gb_internal wchar_t **command_line_to_wargv(wchar_t *cmd_line, int *_argc) { u32 i, j; - u32 len = cast(u32)string16_len(cmd_line); + u32 len = cast(u32)string16_len(cast(u16 *)cmd_line); i = ((len+2)/2)*gb_size_of(void *) + gb_size_of(void *); wchar_t **argv = cast(wchar_t **)GlobalAlloc(GMEM_FIXED, i + (len+2)*gb_size_of(wchar_t)); diff --git a/src/exact_value.cpp b/src/exact_value.cpp index 37751c8f1..f2aed84c2 100644 --- a/src/exact_value.cpp +++ b/src/exact_value.cpp @@ -29,6 +29,7 @@ enum ExactValueKind { ExactValue_Compound = 8, ExactValue_Procedure = 9, ExactValue_Typeid = 10, + ExactValue_String16 = 11, ExactValue_Count, }; @@ -46,6 +47,7 @@ struct ExactValue { Ast * value_compound; Ast * value_procedure; Type * value_typeid; + String16 value_string16; }; }; @@ -66,6 +68,9 @@ gb_internal uintptr hash_exact_value(ExactValue v) { case ExactValue_String: res = gb_fnv32a(v.value_string.text, v.value_string.len); break; + case ExactValue_String16: + res = gb_fnv32a(v.value_string.text, v.value_string.len*gb_size_of(u16)); + break; case ExactValue_Integer: { u32 key = gb_fnv32a(v.value_integer.dp, gb_size_of(*v.value_integer.dp) * v.value_integer.used); @@ -118,6 +123,11 @@ gb_internal ExactValue exact_value_string(String string) { result.value_string = string; return result; } +gb_internal ExactValue exact_value_string16(String16 string) { + ExactValue result = {ExactValue_String16}; + result.value_string16 = string; + return result; +} gb_internal ExactValue exact_value_i64(i64 i) { ExactValue result = {ExactValue_Integer}; @@ -656,6 +666,7 @@ gb_internal i32 exact_value_order(ExactValue const &v) { return 0; case ExactValue_Bool: case ExactValue_String: + case ExactValue_String16: return 1; case ExactValue_Integer: return 2; @@ -689,6 +700,7 @@ gb_internal void match_exact_values(ExactValue *x, ExactValue *y) { case ExactValue_Bool: case ExactValue_String: + case ExactValue_String16: case ExactValue_Quaternion: case ExactValue_Pointer: case ExactValue_Compound: @@ -891,7 +903,18 @@ gb_internal ExactValue exact_binary_operator_value(TokenKind op, ExactValue x, E gb_memmove(data, sx.text, sx.len); gb_memmove(data+sx.len, sy.text, sy.len); return exact_value_string(make_string(data, len)); - break; + } + case ExactValue_String16: { + if (op != Token_Add) goto error; + + // NOTE(bill): How do you minimize this over allocation? + String sx = x.value_string; + String sy = y.value_string; + isize len = sx.len+sy.len; + u16 *data = gb_alloc_array(permanent_allocator(), u16, len); + gb_memmove(data, sx.text, sx.len*gb_size_of(u16)); + gb_memmove(data+sx.len, sy.text, sy.len*gb_size_of(u16)); + return exact_value_string16(make_string16(data, len)); } } @@ -994,6 +1017,19 @@ gb_internal bool compare_exact_values(TokenKind op, ExactValue x, ExactValue y) } break; } + case ExactValue_String16: { + String16 a = x.value_string16; + String16 b = y.value_string16; + switch (op) { + case Token_CmpEq: return a == b; + case Token_NotEq: return a != b; + case Token_Lt: return a < b; + case Token_LtEq: return a <= b; + case Token_Gt: return a > b; + case Token_GtEq: return a >= b; + } + break; + } case ExactValue_Pointer: { switch (op) { @@ -1050,6 +1086,20 @@ gb_internal gbString write_exact_value_to_string(gbString str, ExactValue const gb_free(heap_allocator(), s.text); return str; } + case ExactValue_String16: { + String s = quote_to_ascii(heap_allocator(), v.value_string16); + string_limit = gb_max(string_limit, 36); + if (s.len <= string_limit) { + str = gb_string_append_length(str, s.text, s.len); + } else { + isize n = string_limit/5; + str = gb_string_append_length(str, s.text, n); + str = gb_string_append_fmt(str, "\"..%lld chars..\"", s.len-(2*n)); + str = gb_string_append_length(str, s.text+s.len-n, n); + } + gb_free(heap_allocator(), s.text); + return str; + } case ExactValue_Integer: { String s = big_int_to_string(heap_allocator(), &v.value_integer); str = gb_string_append_length(str, s.text, s.len); diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index 74aea82f1..fbf0dea11 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -1656,6 +1656,8 @@ gb_internal lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) { res.type = t; res.value = llvm_cstring(m, str); return res; + } else if (src->kind == Type_Basic && src->Basic.kind == Basic_string16 && dst->Basic.kind == Basic_cstring16) { + GB_PANIC("TODO(bill): UTF-16 string"); } // if (is_type_float(dst)) { // return value; @@ -1795,6 +1797,38 @@ gb_internal lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) { } + + if (is_type_cstring16(src) && is_type_u16_ptr(dst)) { + return lb_emit_transmute(p, value, dst); + } + if (is_type_u16_ptr(src) && is_type_cstring16(dst)) { + return lb_emit_transmute(p, value, dst); + } + if (is_type_cstring16(src) && is_type_u16_multi_ptr(dst)) { + return lb_emit_transmute(p, value, dst); + } + if (is_type_u8_multi_ptr(src) && is_type_cstring16(dst)) { + return lb_emit_transmute(p, value, dst); + } + if (is_type_cstring16(src) && is_type_rawptr(dst)) { + return lb_emit_transmute(p, value, dst); + } + if (is_type_rawptr(src) && is_type_cstring16(dst)) { + return lb_emit_transmute(p, value, dst); + } + + if (are_types_identical(src, t_cstring16) && are_types_identical(dst, t_string16)) { + TEMPORARY_ALLOCATOR_GUARD(); + + lbValue c = lb_emit_conv(p, value, t_cstring16); + auto args = array_make(temporary_allocator(), 1); + args[0] = c; + lbValue s = lb_emit_runtime_call(p, "cstring16_to_string16", args); + return lb_emit_conv(p, s, dst); + } + + + // integer -> boolean if (is_type_integer(src) && is_type_boolean(dst)) { lbValue res = {}; @@ -2296,6 +2330,14 @@ gb_internal lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) { return res; } + // []u16 <-> string16 + if (is_type_u16_slice(src) && is_type_string16(dst)) { + return lb_emit_transmute(p, value, t); + } + if (is_type_string16(src) && is_type_u16_slice(dst)) { + return lb_emit_transmute(p, value, t); + } + // []byte/[]u8 <-> string if (is_type_u8_slice(src) && is_type_string(dst)) { return lb_emit_transmute(p, value, t); @@ -2304,6 +2346,7 @@ gb_internal lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) { return lb_emit_transmute(p, value, t); } + if (is_type_array_like(dst)) { Type *elem = base_array_type(dst); isize index_count = cast(isize)get_array_type_count(dst); @@ -2483,6 +2526,12 @@ gb_internal lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) { if (is_type_untyped(src)) { + if (is_type_string(src) && is_type_string16(dst)) { + GB_PANIC("TODO(bill): UTF-16 string"); + lbAddr result = lb_add_local_generated(p, t, false); + lb_addr_store(p, result, value); + return lb_addr_load(p, result); + } if (is_type_string(src) && is_type_string(dst)) { lbAddr result = lb_add_local_generated(p, t, false); lb_addr_store(p, result, value); @@ -3056,6 +3105,13 @@ gb_internal lbValue lb_emit_comp_against_nil(lbProcedure *p, TokenKind op_kind, res.value = LLVMBuildIsNotNull(p->builder, x.value, ""); } return res; + case Basic_cstring16: + if (op_kind == Token_CmpEq) { + res.value = LLVMBuildIsNull(p->builder, x.value, ""); + } else if (op_kind == Token_NotEq) { + res.value = LLVMBuildIsNotNull(p->builder, x.value, ""); + } + return res; case Basic_any: { // TODO(bill): is this correct behaviour for nil comparison for any? @@ -4432,6 +4488,22 @@ gb_internal lbAddr lb_build_addr_slice_expr(lbProcedure *p, Ast *expr) { } case Type_Basic: { + if (is_type_string16(type)) { + GB_ASSERT_MSG(are_types_identical(type, t_string16), "got %s", type_to_string(type)); + lbValue len = lb_string_len(p, base); + if (high.value == nullptr) high = len; + + if (!no_indices) { + lb_emit_slice_bounds_check(p, se->open, low, high, len, se->low != nullptr); + } + + lbValue elem = lb_emit_ptr_offset(p, lb_string_elem(p, base), low); + lbValue new_len = lb_emit_arith(p, Token_Sub, high, low, t_int); + + lbAddr str = lb_add_local_generated(p, t_string16, false); + lb_fill_string(p, str, elem, new_len); + return str; + } GB_ASSERT_MSG(are_types_identical(type, t_string), "got %s", type_to_string(type)); lbValue len = lb_string_len(p, base); if (high.value == nullptr) high = len; diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp index 3ce0c725f..d9771a75b 100644 --- a/src/llvm_backend_general.cpp +++ b/src/llvm_backend_general.cpp @@ -1812,6 +1812,37 @@ gb_internal LLVMTypeRef lb_type_internal(lbModule *m, Type *type) { return type; } case Basic_cstring: return LLVMPointerType(LLVMInt8TypeInContext(ctx), 0); + + + case Basic_string16: + { + char const *name = "..string16"; + LLVMTypeRef type = LLVMGetTypeByName(m->mod, name); + if (type != nullptr) { + return type; + } + type = LLVMStructCreateNamed(ctx, name); + + if (build_context.metrics.ptr_size < build_context.metrics.int_size) { + GB_ASSERT(build_context.metrics.ptr_size == 4); + GB_ASSERT(build_context.metrics.int_size == 8); + LLVMTypeRef fields[3] = { + LLVMPointerType(lb_type(m, t_u16), 0), + lb_type(m, t_i32), + lb_type(m, t_int), + }; + LLVMStructSetBody(type, fields, 3, false); + } else { + LLVMTypeRef fields[2] = { + LLVMPointerType(lb_type(m, t_u16), 0), + lb_type(m, t_int), + }; + LLVMStructSetBody(type, fields, 2, false); + } + return type; + } + case Basic_cstring16: return LLVMPointerType(LLVMInt16TypeInContext(ctx), 0); + case Basic_any: { char const *name = "..any"; diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index e63c92f6f..8f306b771 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -2289,6 +2289,10 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu } if (is_type_cstring(t)) { return lb_cstring_len(p, v); + } else if (is_type_cstring16(t)) { + return lb_cstring16_len(p, v); + } else if (is_type_string16(t)) { + return lb_string_len(p, v); } else if (is_type_string(t)) { return lb_string_len(p, v); } else if (is_type_array(t)) { @@ -2728,6 +2732,11 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu res = lb_emit_conv(p, res, tv.type); } else if (t->Basic.kind == Basic_cstring) { res = lb_emit_conv(p, x, tv.type); + } else if (t->Basic.kind == Basic_string16) { + res = lb_string_elem(p, x); + res = lb_emit_conv(p, res, tv.type); + } else if (t->Basic.kind == Basic_cstring16) { + res = lb_emit_conv(p, x, tv.type); } break; case Type_Pointer: diff --git a/src/llvm_backend_type.cpp b/src/llvm_backend_type.cpp index 43c5f0b40..a91d77fe5 100644 --- a/src/llvm_backend_type.cpp +++ b/src/llvm_backend_type.cpp @@ -531,7 +531,33 @@ gb_internal void lb_setup_type_info_data_giant_array(lbModule *m, i64 global_typ case Basic_cstring: { tag_type = t_type_info_string; - LLVMValueRef vals[1] = { + LLVMValueRef vals[2] = { + lb_const_bool(m, t_bool, true).value, + lb_const_bool(m, t_bool, false).value, + }; + + variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals)); + } + break; + + case Basic_string16: + { + tag_type = t_type_info_string; + LLVMValueRef vals[2] = { + lb_const_bool(m, t_bool, false).value, + lb_const_bool(m, t_bool, true).value, + }; + + variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals)); + } + break; + + + case Basic_cstring16: + { + tag_type = t_type_info_string; + LLVMValueRef vals[2] = { + lb_const_bool(m, t_bool, true).value, lb_const_bool(m, t_bool, true).value, }; diff --git a/src/llvm_backend_utility.cpp b/src/llvm_backend_utility.cpp index 521553147..d4117b7ff 100644 --- a/src/llvm_backend_utility.cpp +++ b/src/llvm_backend_utility.cpp @@ -1626,11 +1626,17 @@ gb_internal void lb_fill_string(lbProcedure *p, lbAddr const &string, lbValue ba gb_internal lbValue lb_string_elem(lbProcedure *p, lbValue string) { Type *t = base_type(string.type); + if (t->kind == Type_Basic && t->Basic.kind == Basic_string16) { + return lb_emit_struct_ev(p, string, 0); + } GB_ASSERT(t->kind == Type_Basic && t->Basic.kind == Basic_string); return lb_emit_struct_ev(p, string, 0); } gb_internal lbValue lb_string_len(lbProcedure *p, lbValue string) { Type *t = base_type(string.type); + if (t->kind == Type_Basic && t->Basic.kind == Basic_string16) { + return lb_emit_struct_ev(p, string, 1); + } GB_ASSERT_MSG(t->kind == Type_Basic && t->Basic.kind == Basic_string, "%s", type_to_string(t)); return lb_emit_struct_ev(p, string, 1); } @@ -1641,6 +1647,12 @@ gb_internal lbValue lb_cstring_len(lbProcedure *p, lbValue value) { args[0] = lb_emit_conv(p, value, t_cstring); return lb_emit_runtime_call(p, "cstring_len", args); } +gb_internal lbValue lb_cstring16_len(lbProcedure *p, lbValue value) { + GB_ASSERT(is_type_cstring16(value.type)); + auto args = array_make(permanent_allocator(), 1); + args[0] = lb_emit_conv(p, value, t_cstring16); + return lb_emit_runtime_call(p, "cstring16_len", args); +} gb_internal lbValue lb_array_elem(lbProcedure *p, lbValue array_ptr) { diff --git a/src/main.cpp b/src/main.cpp index 112d1208a..5a43e3c02 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -142,9 +142,9 @@ gb_internal i32 system_exec_command_line_app_internal(bool exit_on_err, char con } wcmd = string_to_string16(permanent_allocator(), make_string(cast(u8 *)cmd_line, cmd_len-1)); - if (CreateProcessW(nullptr, wcmd.text, - nullptr, nullptr, true, 0, nullptr, nullptr, - &start_info, &pi)) { + if (CreateProcessW(nullptr, cast(wchar_t *)wcmd.text, + nullptr, nullptr, true, 0, nullptr, nullptr, + &start_info, &pi)) { WaitForSingleObject(pi.hProcess, INFINITE); GetExitCodeProcess(pi.hProcess, cast(DWORD *)&exit_code); @@ -232,7 +232,7 @@ gb_internal Array setup_args(int argc, char const **argv) { wchar_t **wargv = command_line_to_wargv(GetCommandLineW(), &wargc); auto args = array_make(a, 0, wargc); for (isize i = 0; i < wargc; i++) { - wchar_t *warg = wargv[i]; + u16 *warg = cast(u16 *)wargv[i]; isize wlen = string16_len(warg); String16 wstr = make_string16(warg, wlen); String arg = string16_to_string(a, wstr); diff --git a/src/microsoft_craziness.h b/src/microsoft_craziness.h index b0fd22a23..933607a2a 100644 --- a/src/microsoft_craziness.h +++ b/src/microsoft_craziness.h @@ -59,7 +59,7 @@ struct Find_Result { }; gb_internal String mc_wstring_to_string(wchar_t const *str) { - return string16_to_string(mc_allocator, make_string16_c(str)); + return string16_to_string(mc_allocator, make_string16_c(cast(u16 *)str)); } gb_internal String16 mc_string_to_wstring(String str) { @@ -103,7 +103,7 @@ gb_internal HANDLE mc_find_first(String wildcard, MC_Find_Data *find_data) { String16 wildcard_wide = mc_string_to_wstring(wildcard); defer (mc_free(wildcard_wide)); - HANDLE handle = FindFirstFileW(wildcard_wide.text, &_find_data); + HANDLE handle = FindFirstFileW(cast(wchar_t *)wildcard_wide.text, &_find_data); if (handle == INVALID_HANDLE_VALUE) return INVALID_HANDLE_VALUE; find_data->file_attributes = _find_data.dwFileAttributes; diff --git a/src/path.cpp b/src/path.cpp index d5e982088..2b97a04df 100644 --- a/src/path.cpp +++ b/src/path.cpp @@ -130,7 +130,7 @@ gb_internal String directory_from_path(String const &s) { String16 wstr = string_to_string16(a, path); defer (gb_free(a, wstr.text)); - i32 attribs = GetFileAttributesW(wstr.text); + i32 attribs = GetFileAttributesW(cast(wchar_t *)wstr.text); if (attribs < 0) return false; return (attribs & FILE_ATTRIBUTE_DIRECTORY) != 0; @@ -360,7 +360,7 @@ gb_internal ReadDirectoryError read_directory(String path, Array *fi) defer (gb_free(a, wstr.text)); WIN32_FIND_DATAW file_data = {}; - HANDLE find_file = FindFirstFileW(wstr.text, &file_data); + HANDLE find_file = FindFirstFileW(cast(wchar_t *)wstr.text, &file_data); if (find_file == INVALID_HANDLE_VALUE) { return ReadDirectory_Unknown; } @@ -372,7 +372,7 @@ gb_internal ReadDirectoryError read_directory(String path, Array *fi) wchar_t *filename_w = file_data.cFileName; u64 size = cast(u64)file_data.nFileSizeLow; size |= (cast(u64)file_data.nFileSizeHigh) << 32; - String name = string16_to_string(a, make_string16_c(filename_w)); + String name = string16_to_string(a, make_string16_c(cast(u16 *)filename_w)); if (name == "." || name == "..") { gb_free(a, name.text); continue; @@ -494,7 +494,7 @@ gb_internal bool write_directory(String path) { #else gb_internal bool write_directory(String path) { String16 wstr = string_to_string16(heap_allocator(), path); - LPCWSTR wdirectory_name = wstr.text; + LPCWSTR wdirectory_name = cast(wchar_t *)wstr.text; HANDLE directory = CreateFileW(wdirectory_name, GENERIC_WRITE, diff --git a/src/string.cpp b/src/string.cpp index ae8d066b1..8405938f4 100644 --- a/src/string.cpp +++ b/src/string.cpp @@ -26,15 +26,14 @@ struct String_Iterator { // NOTE(bill): String16 is only used for Windows due to its file directories struct String16 { - wchar_t *text; - isize len; - wchar_t const &operator[](isize i) const { + u16 * text; + isize len; + u16 const &operator[](isize i) const { GB_ASSERT_MSG(0 <= i && i < len, "[%td]", i); return text[i]; } }; - gb_internal gb_inline String make_string(u8 const *text, isize len) { String s; s.text = cast(u8 *)text; @@ -45,19 +44,19 @@ gb_internal gb_inline String make_string(u8 const *text, isize len) { return s; } - -gb_internal gb_inline String16 make_string16(wchar_t const *text, isize len) { +gb_internal gb_inline String16 make_string16(u16 const *text, isize len) { String16 s; - s.text = cast(wchar_t *)text; + s.text = cast(u16 *)text; s.len = len; return s; } -gb_internal isize string16_len(wchar_t const *s) { + +gb_internal isize string16_len(u16 const *s) { if (s == nullptr) { return 0; } - wchar_t const *p = s; + u16 const *p = s; while (*p) { p++; } @@ -69,7 +68,7 @@ gb_internal gb_inline String make_string_c(char const *text) { return make_string(cast(u8 *)cast(void *)text, gb_strlen(text)); } -gb_internal gb_inline String16 make_string16_c(wchar_t const *text) { +gb_internal gb_inline String16 make_string16_c(u16 const *text) { return make_string16(text, string16_len(text)); } @@ -145,6 +144,27 @@ gb_internal int string_compare(String const &a, String const &b) { return res; } + +gb_internal int string16_compare(String16 const &a, String16 const &b) { + if (a.text == b.text) { + return cast(int)(a.len - b.len); + } + if (a.text == nullptr) { + return -1; + } + if (b.text == nullptr) { + return +1; + } + + uintptr n = gb_min(a.len, b.len); + int res = memcmp(a.text, b.text, n*gb_size_of(u16)); + if (res == 0) { + res = cast(int)(a.len - b.len); + } + return res; +} + + gb_internal isize string_index_byte(String const &s, u8 x) { for (isize i = 0; i < s.len; i++) { if (s.text[i] == x) { @@ -182,6 +202,26 @@ template gb_internal bool operator >= (String const &a, char const (&b template <> bool operator == (String const &a, char const (&b)[1]) { return a.len == 0; } template <> bool operator != (String const &a, char const (&b)[1]) { return a.len != 0; } + +gb_internal gb_inline bool str_eq(String16 const &a, String16 const &b) { + if (a.len != b.len) return false; + if (a.len == 0) return true; + return memcmp(a.text, b.text, a.len) == 0; +} +gb_internal gb_inline bool str_ne(String16 const &a, String16 const &b) { return !str_eq(a, b); } +gb_internal gb_inline bool str_lt(String16 const &a, String16 const &b) { return string16_compare(a, b) < 0; } +gb_internal gb_inline bool str_gt(String16 const &a, String16 const &b) { return string16_compare(a, b) > 0; } +gb_internal gb_inline bool str_le(String16 const &a, String16 const &b) { return string16_compare(a, b) <= 0; } +gb_internal gb_inline bool str_ge(String16 const &a, String16 const &b) { return string16_compare(a, b) >= 0; } + +gb_internal gb_inline bool operator == (String16 const &a, String16 const &b) { return str_eq(a, b); } +gb_internal gb_inline bool operator != (String16 const &a, String16 const &b) { return str_ne(a, b); } +gb_internal gb_inline bool operator < (String16 const &a, String16 const &b) { return str_lt(a, b); } +gb_internal gb_inline bool operator > (String16 const &a, String16 const &b) { return str_gt(a, b); } +gb_internal gb_inline bool operator <= (String16 const &a, String16 const &b) { return str_le(a, b); } +gb_internal gb_inline bool operator >= (String16 const &a, String16 const &b) { return str_ge(a, b); } + + gb_internal gb_inline bool string_starts_with(String const &s, String const &prefix) { if (prefix.len > s.len) { return false; @@ -614,7 +654,7 @@ gb_internal String normalize_path(gbAllocator a, String const &path, String cons // TODO(bill): Make this non-windows specific gb_internal String16 string_to_string16(gbAllocator a, String s) { int len, len1; - wchar_t *text; + u16 *text; if (s.len < 1) { return make_string16(nullptr, 0); @@ -625,9 +665,9 @@ gb_internal String16 string_to_string16(gbAllocator a, String s) { return make_string16(nullptr, 0); } - text = gb_alloc_array(a, wchar_t, len+1); + text = gb_alloc_array(a, u16, len+1); - len1 = convert_multibyte_to_widechar(cast(char *)s.text, cast(int)s.len, text, cast(int)len); + len1 = convert_multibyte_to_widechar(cast(char *)s.text, cast(int)s.len, cast(wchar_t *)text, cast(int)len); if (len1 == 0) { gb_free(a, text); return make_string16(nullptr, 0); @@ -646,7 +686,7 @@ gb_internal String string16_to_string(gbAllocator a, String16 s) { return make_string(nullptr, 0); } - len = convert_widechar_to_multibyte(s.text, cast(int)s.len, nullptr, 0); + len = convert_widechar_to_multibyte(cast(wchar_t *)s.text, cast(int)s.len, nullptr, 0); if (len == 0) { return make_string(nullptr, 0); } @@ -654,7 +694,7 @@ gb_internal String string16_to_string(gbAllocator a, String16 s) { text = gb_alloc_array(a, u8, len+1); - len1 = convert_widechar_to_multibyte(s.text, cast(int)s.len, cast(char *)text, cast(int)len); + len1 = convert_widechar_to_multibyte(cast(wchar_t *)s.text, cast(int)s.len, cast(char *)text, cast(int)len); if (len1 == 0) { gb_free(a, text); return make_string(nullptr, 0); @@ -674,9 +714,9 @@ gb_internal String temporary_directory(gbAllocator allocator) { return String{0}; } DWORD len = gb_max(MAX_PATH, n); - wchar_t *b = gb_alloc_array(heap_allocator(), wchar_t, len+1); + u16 *b = gb_alloc_array(heap_allocator(), u16, len+1); defer (gb_free(heap_allocator(), b)); - n = GetTempPathW(len, b); + n = GetTempPathW(len, cast(wchar_t *)b); if (n == 3 && b[1] == ':' && b[2] == '\\') { } else if (n > 0 && b[n-1] == '\\') { @@ -791,6 +831,104 @@ gb_internal String quote_to_ascii(gbAllocator a, String str, u8 quote='"') { return res; } +gb_internal Rune decode_surrogate_pair(u16 r1, u16 r2) { + static Rune const _surr1 = 0xd800; + static Rune const _surr2 = 0xdc00; + static Rune const _surr3 = 0xe000; + static Rune const _surr_self = 0x10000; + + if (_surr1 <= r1 && r1 < _surr2 && _surr2 <= r2 && r2 < _surr3) { + return (((r1-_surr1)<<10) | (r2 - _surr2)) + _surr_self; + } + return GB_RUNE_INVALID; +} + +gb_internal String quote_to_ascii(gbAllocator a, String16 str, u8 quote='"') { + static Rune const _surr1 = 0xd800; + static Rune const _surr2 = 0xdc00; + static Rune const _surr3 = 0xe000; + static Rune const _surr_self = 0x10000; + + u16 *s = cast(u16 *)str.text; + isize n = str.len; + auto buf = array_make(a, 0, n*2); + array_add(&buf, quote); + for (isize width = 0; n > 0; s += width, n -= width) { + Rune r = cast(Rune)s[0]; + width = 1; + if (r < _surr1 || _surr3 <= r) { + r = cast(Rune)r; + } else if (_surr1 <= r && r < _surr2) { + if (n>1) { + r = decode_surrogate_pair(s[0], s[1]); + if (r != GB_RUNE_INVALID) { + width = 2; + } + } else { + r = GB_RUNE_INVALID; + } + } + if (width == 1 && r == GB_RUNE_INVALID) { + array_add(&buf, cast(u8)'\\'); + array_add(&buf, cast(u8)'x'); + array_add(&buf, cast(u8)lower_hex[s[0]>>4]); + array_add(&buf, cast(u8)lower_hex[s[0]&0xf]); + continue; + } + + if (r == quote || r == '\\') { + array_add(&buf, cast(u8)'\\'); + array_add(&buf, u8(r)); + continue; + } + if (r < 0x80 && is_printable(r)) { + array_add(&buf, u8(r)); + continue; + } + switch (r) { + case '\a': + case '\b': + case '\f': + case '\n': + case '\r': + case '\t': + case '\v': + default: + if (r < ' ') { + u8 b = cast(u8)r; + array_add(&buf, cast(u8)'\\'); + array_add(&buf, cast(u8)'x'); + array_add(&buf, cast(u8)lower_hex[b>>4]); + array_add(&buf, cast(u8)lower_hex[b&0xf]); + } + if (r > GB_RUNE_MAX) { + r = 0XFFFD; + } + if (r < 0x10000) { + array_add(&buf, cast(u8)'\\'); + array_add(&buf, cast(u8)'u'); + for (isize i = 12; i >= 0; i -= 4) { + array_add(&buf, cast(u8)lower_hex[(r>>i)&0xf]); + } + } else { + array_add(&buf, cast(u8)'\\'); + array_add(&buf, cast(u8)'U'); + for (isize i = 28; i >= 0; i -= 4) { + array_add(&buf, cast(u8)lower_hex[(r>>i)&0xf]); + } + } + } + } + + + + array_add(&buf, quote); + String res = {}; + res.text = buf.data; + res.len = buf.count; + return res; +} + diff --git a/src/types.cpp b/src/types.cpp index 2e696810d..ad576c8af 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -41,8 +41,13 @@ enum BasicKind { Basic_uint, Basic_uintptr, Basic_rawptr, - Basic_string, // ^u8 + int - Basic_cstring, // ^u8 + + Basic_string, // [^]u8 + int + Basic_cstring, // [^]u8 + + Basic_string16, // [^]u16 + int + Basic_cstring16, // [^]u16 + int + Basic_any, // rawptr + ^Type_Info Basic_typeid, @@ -500,8 +505,14 @@ gb_global Type basic_types[] = { {Type_Basic, {Basic_uintptr, BasicFlag_Integer | BasicFlag_Unsigned, -1, STR_LIT("uintptr")}}, {Type_Basic, {Basic_rawptr, BasicFlag_Pointer, -1, STR_LIT("rawptr")}}, + {Type_Basic, {Basic_string, BasicFlag_String, -1, STR_LIT("string")}}, {Type_Basic, {Basic_cstring, BasicFlag_String, -1, STR_LIT("cstring")}}, + + {Type_Basic, {Basic_string16, BasicFlag_String, -1, STR_LIT("string16")}}, + {Type_Basic, {Basic_cstring16, BasicFlag_String, -1, STR_LIT("cstring16")}}, + + {Type_Basic, {Basic_any, 0, 16, STR_LIT("any")}}, {Type_Basic, {Basic_typeid, 0, 8, STR_LIT("typeid")}}, @@ -591,8 +602,12 @@ gb_global Type *t_uint = &basic_types[Basic_uint]; gb_global Type *t_uintptr = &basic_types[Basic_uintptr]; gb_global Type *t_rawptr = &basic_types[Basic_rawptr]; + gb_global Type *t_string = &basic_types[Basic_string]; gb_global Type *t_cstring = &basic_types[Basic_cstring]; +gb_global Type *t_string16 = &basic_types[Basic_string16]; +gb_global Type *t_cstring16 = &basic_types[Basic_cstring16]; + gb_global Type *t_any = &basic_types[Basic_any]; gb_global Type *t_typeid = &basic_types[Basic_typeid]; @@ -630,6 +645,8 @@ gb_global Type *t_untyped_uninit = &basic_types[Basic_UntypedUninit]; gb_global Type *t_u8_ptr = nullptr; gb_global Type *t_u8_multi_ptr = nullptr; +gb_global Type *t_u16_ptr = nullptr; +gb_global Type *t_u16_multi_ptr = nullptr; gb_global Type *t_int_ptr = nullptr; gb_global Type *t_i64_ptr = nullptr; gb_global Type *t_f64_ptr = nullptr; @@ -1292,6 +1309,14 @@ gb_internal bool is_type_string(Type *t) { } return false; } +gb_internal bool is_type_string16(Type *t) { + t = base_type(t); + if (t == nullptr) { return false; } + if (t->kind == Type_Basic) { + return t->Basic.kind == Basic_string16; + } + return false; +} gb_internal bool is_type_cstring(Type *t) { t = base_type(t); if (t == nullptr) { return false; } @@ -1300,6 +1325,14 @@ gb_internal bool is_type_cstring(Type *t) { } return false; } +gb_internal bool is_type_cstring16(Type *t) { + t = base_type(t); + if (t == nullptr) { return false; } + if (t->kind == Type_Basic) { + return t->Basic.kind == Basic_cstring16; + } + return false; +} gb_internal bool is_type_typed(Type *t) { t = base_type(t); if (t == nullptr) { return false; } @@ -1429,6 +1462,12 @@ gb_internal bool is_type_u8(Type *t) { } return false; } +gb_internal bool is_type_u16(Type *t) { + if (t->kind == Type_Basic) { + return t->Basic.kind == Basic_u16; + } + return false; +} gb_internal bool is_type_array(Type *t) { t = base_type(t); if (t == nullptr) { return false; } @@ -1690,6 +1729,39 @@ gb_internal bool is_type_rune_array(Type *t) { return false; } +gb_internal bool is_type_u16_slice(Type *t) { + t = base_type(t); + if (t == nullptr) { return false; } + if (t->kind == Type_Slice) { + return is_type_u16(t->Slice.elem); + } + return false; +} +gb_internal bool is_type_u16_array(Type *t) { + t = base_type(t); + if (t == nullptr) { return false; } + if (t->kind == Type_Array) { + return is_type_u16(t->Array.elem); + } + return false; +} +gb_internal bool is_type_u16_ptr(Type *t) { + t = base_type(t); + if (t == nullptr) { return false; } + if (t->kind == Type_Pointer) { + return is_type_u16(t->Slice.elem); + } + return false; +} +gb_internal bool is_type_u16_multi_ptr(Type *t) { + t = base_type(t); + if (t == nullptr) { return false; } + if (t->kind == Type_MultiPointer) { + return is_type_u16(t->Slice.elem); + } + return false; +} + gb_internal bool is_type_array_like(Type *t) { return is_type_array(t) || is_type_enumerated_array(t); @@ -2109,7 +2181,7 @@ gb_internal bool is_type_indexable(Type *t) { Type *bt = base_type(t); switch (bt->kind) { case Type_Basic: - return bt->Basic.kind == Basic_string; + return bt->Basic.kind == Basic_string || bt->Basic.kind == Basic_string16; case Type_Array: case Type_Slice: case Type_DynamicArray: @@ -2129,7 +2201,7 @@ gb_internal bool is_type_sliceable(Type *t) { Type *bt = base_type(t); switch (bt->kind) { case Type_Basic: - return bt->Basic.kind == Basic_string; + return bt->Basic.kind == Basic_string || bt->Basic.kind == Basic_string16; case Type_Array: case Type_Slice: case Type_DynamicArray: @@ -2376,6 +2448,7 @@ gb_internal bool type_has_nil(Type *t) { case Basic_any: return true; case Basic_cstring: + case Basic_cstring16: return true; case Basic_typeid: return true; @@ -2443,8 +2516,9 @@ gb_internal bool is_type_comparable(Type *t) { case Basic_rune: return true; case Basic_string: - return true; case Basic_cstring: + case Basic_string16: + case Basic_cstring16: return true; case Basic_typeid: return true; @@ -3774,10 +3848,12 @@ gb_internal i64 type_size_of(Type *t) { if (t->kind == Type_Basic) { GB_ASSERT_MSG(is_type_typed(t), "%s", type_to_string(t)); switch (t->Basic.kind) { - case Basic_string: size = 2*build_context.int_size; break; - case Basic_cstring: size = build_context.ptr_size; break; - case Basic_any: size = 16; break; - case Basic_typeid: size = 8; break; + case Basic_string: size = 2*build_context.int_size; break; + case Basic_cstring: size = build_context.ptr_size; break; + case Basic_string16: size = 2*build_context.int_size; break; + case Basic_cstring16: size = build_context.ptr_size; break; + case Basic_any: size = 16; break; + case Basic_typeid: size = 8; break; case Basic_int: case Basic_uint: size = build_context.int_size; @@ -3837,10 +3913,12 @@ gb_internal i64 type_align_of_internal(Type *t, TypePath *path) { case Type_Basic: { GB_ASSERT(is_type_typed(t)); switch (t->Basic.kind) { - case Basic_string: return build_context.int_size; - case Basic_cstring: return build_context.ptr_size; - case Basic_any: return 8; - case Basic_typeid: return 8; + case Basic_string: return build_context.int_size; + case Basic_cstring: return build_context.ptr_size; + case Basic_string16: return build_context.int_size; + case Basic_cstring16: return build_context.ptr_size; + case Basic_any: return 8; + case Basic_typeid: return 8; case Basic_int: case Basic_uint: return build_context.int_size; @@ -4088,10 +4166,12 @@ gb_internal i64 type_size_of_internal(Type *t, TypePath *path) { return size; } switch (kind) { - case Basic_string: return 2*build_context.int_size; - case Basic_cstring: return build_context.ptr_size; - case Basic_any: return 16; - case Basic_typeid: return 8; + case Basic_string: return 2*build_context.int_size; + case Basic_cstring: return build_context.ptr_size; + case Basic_string16: return 2*build_context.int_size; + case Basic_cstring16: return build_context.ptr_size; + case Basic_any: return 16; + case Basic_typeid: return 8; case Basic_int: case Basic_uint: return build_context.int_size; @@ -4320,6 +4400,15 @@ gb_internal i64 type_offset_of(Type *t, i64 index, Type **field_type_) { if (field_type_) *field_type_ = t_int; return build_context.int_size; // len } + } else if (t->Basic.kind == Basic_string16) { + switch (index) { + case 0: + if (field_type_) *field_type_ = t_u16_ptr; + return 0; // data + case 1: + if (field_type_) *field_type_ = t_int; + return build_context.int_size; // len + } } else if (t->Basic.kind == Basic_any) { switch (index) { case 0: @@ -4396,6 +4485,11 @@ gb_internal i64 type_offset_of_from_selection(Type *type, Selection sel) { case 0: t = t_rawptr; break; case 1: t = t_int; break; } + } else if (t->Basic.kind == Basic_string16) { + switch (index) { + case 0: t = t_rawptr; break; + case 1: t = t_int; break; + } } else if (t->Basic.kind == Basic_any) { switch (index) { case 0: t = t_rawptr; break; @@ -4637,6 +4731,11 @@ gb_internal Type *type_internal_index(Type *t, isize index) { GB_ASSERT(index == 0 || index == 1); return index == 0 ? t_u8_ptr : t_int; } + case Basic_string16: + { + GB_ASSERT(index == 0 || index == 1); + return index == 0 ? t_u16_ptr : t_int; + } case Basic_any: { GB_ASSERT(index == 0 || index == 1); From ae02d3d02d2eb5132fa7c6573ed7db20d7e18f3e Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 2 Aug 2025 11:55:16 +0100 Subject: [PATCH 004/105] Begin supporting `string16` across the core library --- base/intrinsics/intrinsics.odin | 1 + base/runtime/print.odin | 6 +++ core/encoding/cbor/tags.odin | 2 +- core/encoding/cbor/unmarshal.odin | 2 + core/encoding/json/marshal.odin | 8 ++-- core/encoding/json/unmarshal.odin | 4 +- core/flags/internal_rtti.odin | 2 + core/fmt/fmt.odin | 16 +++---- core/io/io.odin | 4 +- core/reflect/types.odin | 8 ++-- src/check_builtin.cpp | 2 + src/check_expr.cpp | 42 ++++++++++++++--- src/checker_builtin_procs.hpp | 2 + src/llvm_backend.cpp | 6 +++ src/llvm_backend_const.cpp | 77 +++++++++++++++++++++++++++++-- src/llvm_backend_debug.cpp | 14 ++++++ src/llvm_backend_expr.cpp | 3 +- src/llvm_backend_general.cpp | 37 +++++++++++++++ src/llvm_backend_utility.cpp | 19 +++++++- src/string.cpp | 7 +++ 20 files changed, 230 insertions(+), 32 deletions(-) diff --git a/base/intrinsics/intrinsics.odin b/base/intrinsics/intrinsics.odin index be75739fe..d45d24f48 100644 --- a/base/intrinsics/intrinsics.odin +++ b/base/intrinsics/intrinsics.odin @@ -141,6 +141,7 @@ type_is_quaternion :: proc($T: typeid) -> bool --- type_is_string :: proc($T: typeid) -> bool --- type_is_typeid :: proc($T: typeid) -> bool --- type_is_any :: proc($T: typeid) -> bool --- +type_is_string16 :: proc($T: typeid) -> bool --- type_is_endian_platform :: proc($T: typeid) -> bool --- type_is_endian_little :: proc($T: typeid) -> bool --- diff --git a/base/runtime/print.odin b/base/runtime/print.odin index 145f002d1..85ed49445 100644 --- a/base/runtime/print.odin +++ b/base/runtime/print.odin @@ -293,7 +293,13 @@ print_type :: #force_no_inline proc "contextless" (ti: ^Type_Info) { print_string("quaternion") print_u64(u64(8*ti.size)) case Type_Info_String: + if info.is_cstring { + print_byte('c') + } print_string("string") + if info.is_utf16 { + print_string("16") + } case Type_Info_Boolean: switch ti.id { case bool: print_string("bool") diff --git a/core/encoding/cbor/tags.odin b/core/encoding/cbor/tags.odin index 17420af46..e0e69cbf5 100644 --- a/core/encoding/cbor/tags.odin +++ b/core/encoding/cbor/tags.odin @@ -298,7 +298,7 @@ tag_base64_unmarshal :: proc(_: ^Tag_Implementation, d: Decoder, _: Tag_Number, #partial switch t in ti.variant { case reflect.Type_Info_String: - + assert(!t.is_utf16) if t.is_cstring { length := base64.decoded_len(bytes) builder := strings.builder_make(0, length+1) diff --git a/core/encoding/cbor/unmarshal.odin b/core/encoding/cbor/unmarshal.odin index 365ac5d6f..2840429f5 100644 --- a/core/encoding/cbor/unmarshal.odin +++ b/core/encoding/cbor/unmarshal.odin @@ -335,6 +335,8 @@ _unmarshal_value :: proc(d: Decoder, v: any, hdr: Header, allocator := context.a _unmarshal_bytes :: proc(d: Decoder, v: any, ti: ^reflect.Type_Info, hdr: Header, add: Add, allocator := context.allocator, loc := #caller_location) -> (err: Unmarshal_Error) { #partial switch t in ti.variant { case reflect.Type_Info_String: + assert(!t.is_utf16) + bytes := err_conv(_decode_bytes(d, add, allocator=allocator, loc=loc)) or_return if t.is_cstring { diff --git a/core/encoding/json/marshal.odin b/core/encoding/json/marshal.odin index ebb9a639c..cdb00a354 100644 --- a/core/encoding/json/marshal.odin +++ b/core/encoding/json/marshal.odin @@ -353,10 +353,10 @@ marshal_to_writer :: proc(w: io.Writer, v: any, opt: ^Marshal_Options) -> (err: #partial switch info in ti.variant { case runtime.Type_Info_String: switch x in v { - case string: - return x == "" - case cstring: - return x == nil || x == "" + case string: return x == "" + case cstring: return x == nil || x == "" + case string16: return x == "" + case cstring16: return x == nil || x == "" } case runtime.Type_Info_Any: return v.(any) == nil diff --git a/core/encoding/json/unmarshal.odin b/core/encoding/json/unmarshal.odin index b9ed1476f..51e7e3b81 100644 --- a/core/encoding/json/unmarshal.odin +++ b/core/encoding/json/unmarshal.odin @@ -570,7 +570,9 @@ unmarshal_object :: proc(p: ^Parser, v: any, end_token: Token_Kind) -> (err: Unm key_ptr: rawptr #partial switch tk in t.key.variant { - case runtime.Type_Info_String: + case runtime.Type_Info_String: + assert(!tk.is_utf16) + key_ptr = rawptr(&key) key_cstr: cstring if reflect.is_cstring(t.key) { diff --git a/core/flags/internal_rtti.odin b/core/flags/internal_rtti.odin index 1c559ca55..58224cc87 100644 --- a/core/flags/internal_rtti.odin +++ b/core/flags/internal_rtti.odin @@ -127,6 +127,8 @@ parse_and_set_pointer_by_base_type :: proc(ptr: rawptr, str: string, type_info: } case runtime.Type_Info_String: + assert(!specific_type_info.is_utf16) + if specific_type_info.is_cstring { cstr_ptr := (^cstring)(ptr) if cstr_ptr != nil { diff --git a/core/fmt/fmt.odin b/core/fmt/fmt.odin index 7fe6287d4..9c245de94 100644 --- a/core/fmt/fmt.odin +++ b/core/fmt/fmt.odin @@ -2346,14 +2346,14 @@ fmt_array :: proc(fi: ^Info, data: rawptr, n: int, elem_size: int, elem: ^reflec } switch reflect.type_info_base(elem).id { - case byte: fmt_string(fi, string(([^]byte)(data)[:n]), verb); return - case u16: print_utf16(fi, ([^]u16)(data)[:n]); return - case u16le: print_utf16(fi, ([^]u16le)(data)[:n]); return - case u16be: print_utf16(fi, ([^]u16be)(data)[:n]); return - case u32: print_utf32(fi, ([^]u32)(data)[:n]); return - case u32le: print_utf32(fi, ([^]u32le)(data)[:n]); return - case u32be: print_utf32(fi, ([^]u32be)(data)[:n]); return - case rune: print_utf32(fi, ([^]rune)(data)[:n]); return + case byte: fmt_string(fi, string (([^]byte)(data)[:n]), verb); return + case u16: fmt_string16(fi, string16(([^]u16) (data)[:n]), verb); return + case u16le: print_utf16(fi, ([^]u16le)(data)[:n]); return + case u16be: print_utf16(fi, ([^]u16be)(data)[:n]); return + case u32: print_utf32(fi, ([^]u32)(data)[:n]); return + case u32le: print_utf32(fi, ([^]u32le)(data)[:n]); return + case u32be: print_utf32(fi, ([^]u32be)(data)[:n]); return + case rune: print_utf32(fi, ([^]rune)(data)[:n]); return } } if verb == 'p' { diff --git a/core/io/io.odin b/core/io/io.odin index 5431519bf..c4eb6a073 100644 --- a/core/io/io.odin +++ b/core/io/io.odin @@ -319,7 +319,6 @@ write_string :: proc(s: Writer, str: string, n_written: ^int = nil) -> (n: int, write_string16 :: proc(s: Writer, str: string16, n_written: ^int = nil) -> (n: int, err: Error) { for i := 0; i < len(str); i += 1 { r := rune(utf16.REPLACEMENT_CHAR) - switch c := str[i]; { case c < utf16._surr1, utf16._surr3 <= c: r = rune(c) @@ -329,7 +328,8 @@ write_string16 :: proc(s: Writer, str: string16, n_written: ^int = nil) -> (n: i i += 1 } - w, err := write_rune(s, r, n_written) + w: int + w, err = write_rune(s, r, n_written) n += w if err != nil { return diff --git a/core/reflect/types.odin b/core/reflect/types.odin index 511c5c9bd..2351408cc 100644 --- a/core/reflect/types.odin +++ b/core/reflect/types.odin @@ -511,9 +511,11 @@ write_type_writer :: #force_no_inline proc(w: io.Writer, ti: ^Type_Info, n_writt io.write_i64(w, i64(8*ti.size), 10, &n) or_return case Type_Info_String: if info.is_cstring { - io.write_string(w, "cstring", &n) or_return - } else { - io.write_string(w, "string", &n) or_return + io.write_byte(w, 'c', &n) or_return + } + io.write_string(w, "string", &n) or_return + if info.is_utf16 { + io.write_string(w, "16", &n) or_return } case Type_Info_Boolean: switch ti.id { diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index d36cf4520..4abace637 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -19,6 +19,7 @@ gb_global BuiltinTypeIsProc *builtin_type_is_procs[BuiltinProc__type_simple_bool is_type_complex, is_type_quaternion, is_type_string, + is_type_string16, is_type_typeid, is_type_any, is_type_endian_platform, @@ -6139,6 +6140,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As case BuiltinProc_type_is_complex: case BuiltinProc_type_is_quaternion: case BuiltinProc_type_is_string: + case BuiltinProc_type_is_string16: case BuiltinProc_type_is_typeid: case BuiltinProc_type_is_any: case BuiltinProc_type_is_endian_platform: diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 57073e22f..8d2e4d637 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -2106,6 +2106,9 @@ gb_internal bool check_representable_as_constant(CheckerContext *c, ExactValue i } else if (is_type_boolean(type)) { return in_value.kind == ExactValue_Bool; } else if (is_type_string(type)) { + if (in_value.kind == ExactValue_String16) { + return is_type_string16(type) || is_type_cstring16(type); + } return in_value.kind == ExactValue_String; } else if (is_type_integer(type) || is_type_rune(type)) { if (in_value.kind == ExactValue_Bool) { @@ -2320,6 +2323,9 @@ gb_internal bool check_representable_as_constant(CheckerContext *c, ExactValue i if (in_value.kind == ExactValue_String) { return false; } + if (in_value.kind == ExactValue_String16) { + return false; + } if (out_value) *out_value = in_value; } else if (is_type_bit_set(type)) { if (in_value.kind == ExactValue_Integer) { @@ -4654,6 +4660,13 @@ gb_internal void convert_to_typed(CheckerContext *c, Operand *operand, Type *tar break; } } + } else if (operand->value.kind == ExactValue_String16) { + String16 s = operand->value.value_string16; + if (is_type_u16_array(t)) { + if (s.len == t->Array.count) { + break; + } + } } operand->mode = Addressing_Invalid; convert_untyped_error(c, operand, target_type); @@ -4983,6 +4996,12 @@ gb_internal ExactValue get_constant_field_single(CheckerContext *c, ExactValue v if (success_) *success_ = true; if (finish_) *finish_ = true; return exact_value_u64(val); + } else if (value.kind == ExactValue_String16) { + GB_ASSERT(0 <= index && index < value.value_string.len); + u16 val = value.value_string16[index]; + if (success_) *success_ = true; + if (finish_) *finish_ = true; + return exact_value_u64(val); } if (value.kind != ExactValue_Compound) { if (success_) *success_ = true; @@ -11124,15 +11143,21 @@ gb_internal ExprKind check_slice_expr(CheckerContext *c, Operand *o, Ast *node, o->expr = node; return kind; } - - String s = {}; - if (o->value.kind == ExactValue_String) { - s = o->value.value_string; - } - o->mode = Addressing_Constant; o->type = t; - o->value = exact_value_string(substring(s, cast(isize)indices[0], cast(isize)indices[1])); + + if (o->value.kind == ExactValue_String16) { + String16 s = o->value.value_string16; + + o->value = exact_value_string16(substring(s, cast(isize)indices[0], cast(isize)indices[1])); + } else { + String s = {}; + if (o->value.kind == ExactValue_String) { + s = o->value.value_string; + } + + o->value = exact_value_string(substring(s, cast(isize)indices[0], cast(isize)indices[1])); + } } return kind; } @@ -11221,6 +11246,7 @@ gb_internal ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast Type *t = t_invalid; switch (node->tav.value.kind) { case ExactValue_String: t = t_untyped_string; break; + case ExactValue_String16: t = t_string16; break; // TODO(bill): determine this correctly case ExactValue_Float: t = t_untyped_float; break; case ExactValue_Complex: t = t_untyped_complex; break; case ExactValue_Quaternion: t = t_untyped_quaternion; break; @@ -11657,6 +11683,8 @@ gb_internal bool is_exact_value_zero(ExactValue const &v) { return !v.value_bool; case ExactValue_String: return v.value_string.len == 0; + case ExactValue_String16: + return v.value_string16.len == 0; case ExactValue_Integer: return big_int_is_zero(&v.value_integer); case ExactValue_Float: diff --git a/src/checker_builtin_procs.hpp b/src/checker_builtin_procs.hpp index 8e135ab10..bff887d9e 100644 --- a/src/checker_builtin_procs.hpp +++ b/src/checker_builtin_procs.hpp @@ -250,6 +250,7 @@ BuiltinProc__type_simple_boolean_begin, BuiltinProc_type_is_complex, BuiltinProc_type_is_quaternion, BuiltinProc_type_is_string, + BuiltinProc_type_is_string16, BuiltinProc_type_is_typeid, BuiltinProc_type_is_any, @@ -607,6 +608,7 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = { {STR_LIT("type_is_complex"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("type_is_quaternion"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("type_is_string"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("type_is_string16"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("type_is_typeid"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("type_is_any"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 13a1d8cf3..f37415cc1 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -1264,7 +1264,13 @@ String lb_get_objc_type_encoding(Type *t, isize pointer_depth = 0) { case Basic_string: return build_context.metrics.int_size == 4 ? str_lit("{string=*i}") : str_lit("{string=*q}"); + case Basic_string16: + return build_context.metrics.int_size == 4 ? str_lit("{string16=*i}") : str_lit("{string16=*q}"); + case Basic_cstring: return str_lit("*"); + case Basic_cstring16: return str_lit("*"); + + case Basic_any: return str_lit("{any=^v^v}"); // rawptr + ^Type_Info case Basic_typeid: diff --git a/src/llvm_backend_const.cpp b/src/llvm_backend_const.cpp index c3112934e..8c05ed4a2 100644 --- a/src/llvm_backend_const.cpp +++ b/src/llvm_backend_const.cpp @@ -122,6 +122,25 @@ gb_internal lbValue lb_const_ptr_cast(lbModule *m, lbValue value, Type *t) { gb_internal LLVMValueRef llvm_const_string_internal(lbModule *m, Type *t, LLVMValueRef data, LLVMValueRef len) { + GB_ASSERT(!is_type_string16(t)); + if (build_context.metrics.ptr_size < build_context.metrics.int_size) { + LLVMValueRef values[3] = { + data, + LLVMConstNull(lb_type(m, t_i32)), + len, + }; + return llvm_const_named_struct_internal(lb_type(m, t), values, 3); + } else { + LLVMValueRef values[2] = { + data, + len, + }; + return llvm_const_named_struct_internal(lb_type(m, t), values, 2); + } +} + +gb_internal LLVMValueRef llvm_const_string16_internal(lbModule *m, Type *t, LLVMValueRef data, LLVMValueRef len) { + GB_ASSERT(is_type_string16(t)); if (build_context.metrics.ptr_size < build_context.metrics.int_size) { LLVMValueRef values[3] = { data, @@ -238,6 +257,10 @@ gb_internal lbValue lb_const_string(lbModule *m, String const &value) { return lb_const_value(m, t_string, exact_value_string(value)); } +gb_internal lbValue lb_const_string(lbModule *m, String16 const &value) { + return lb_const_value(m, t_string16, exact_value_string16(value)); +} + gb_internal lbValue lb_const_bool(lbModule *m, Type *type, bool value) { lbValue res = {}; @@ -569,7 +592,11 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb GB_ASSERT(is_type_slice(type)); res.value = lb_find_or_add_entity_string_byte_slice_with_type(m, value.value_string, original_type).value; return res; - } else { + } else if (value.kind == ExactValue_String16) { + GB_ASSERT(is_type_slice(type)); + GB_PANIC("TODO(bill): UTF-16 String"); + return res; + }else { ast_node(cl, CompoundLit, value.value_compound); isize count = cl->elems.count; @@ -751,15 +778,23 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb { bool custom_link_section = cc.link_section.len > 0; - LLVMValueRef ptr = lb_find_or_add_entity_string_ptr(m, value.value_string, custom_link_section); + LLVMValueRef ptr = nullptr; lbValue res = {}; res.type = default_type(original_type); + if (is_type_string16(res.type) || is_type_cstring16(res.type)) { + TEMPORARY_ALLOCATOR_GUARD(); + String16 s16 = string_to_string16(temporary_allocator(), value.value_string); + ptr = lb_find_or_add_entity_string16_ptr(m, s16, custom_link_section); + } else { + ptr = lb_find_or_add_entity_string_ptr(m, value.value_string, custom_link_section); + } + if (custom_link_section) { LLVMSetSection(ptr, alloc_cstring(permanent_allocator(), cc.link_section)); } - if (is_type_cstring(res.type)) { + if (is_type_cstring(res.type) || is_type_cstring16(res.type)) { res.value = ptr; } else { if (value.value_string.len == 0) { @@ -768,12 +803,46 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb LLVMValueRef str_len = LLVMConstInt(lb_type(m, t_int), value.value_string.len, true); GB_ASSERT(is_type_string(original_type)); - res.value = llvm_const_string_internal(m, original_type, ptr, str_len); + if (is_type_string16(res.type)) { + res.value = llvm_const_string16_internal(m, original_type, ptr, str_len); + } else { + res.value = llvm_const_string_internal(m, original_type, ptr, str_len); + } } return res; } + case ExactValue_String16: + { + GB_ASSERT(is_type_string16(res.type) || is_type_cstring16(res.type)); + + bool custom_link_section = cc.link_section.len > 0; + + LLVMValueRef ptr = lb_find_or_add_entity_string16_ptr(m, value.value_string16, custom_link_section); + lbValue res = {}; + res.type = default_type(original_type); + + if (custom_link_section) { + LLVMSetSection(ptr, alloc_cstring(permanent_allocator(), cc.link_section)); + } + + if (is_type_cstring16(res.type)) { + res.value = ptr; + } else { + if (value.value_string16.len == 0) { + ptr = LLVMConstNull(lb_type(m, t_u8_ptr)); + } + LLVMValueRef str_len = LLVMConstInt(lb_type(m, t_int), value.value_string16.len, true); + GB_ASSERT(is_type_string(original_type)); + + res.value = llvm_const_string16_internal(m, original_type, ptr, str_len); + } + + return res; + } + + case ExactValue_Integer: if (is_type_pointer(type) || is_type_multi_pointer(type) || is_type_proc(type)) { LLVMTypeRef t = lb_type(m, original_type); diff --git a/src/llvm_backend_debug.cpp b/src/llvm_backend_debug.cpp index 024c5564e..182920fc7 100644 --- a/src/llvm_backend_debug.cpp +++ b/src/llvm_backend_debug.cpp @@ -802,6 +802,20 @@ gb_internal LLVMMetadataRef lb_debug_type_internal(lbModule *m, Type *type) { LLVMMetadataRef char_type = lb_debug_type_basic_type(m, str_lit("char"), 8, LLVMDWARFTypeEncoding_Unsigned); return LLVMDIBuilderCreatePointerType(m->debug_builder, char_type, ptr_bits, ptr_bits, 0, "cstring", 7); } + + case Basic_string16: + { + LLVMMetadataRef elements[2] = {}; + elements[0] = lb_debug_struct_field(m, str_lit("data"), t_u16_ptr, 0); + elements[1] = lb_debug_struct_field(m, str_lit("len"), t_int, int_bits); + return lb_debug_basic_struct(m, str_lit("string16"), 2*int_bits, int_bits, elements, gb_count_of(elements)); + } + case Basic_cstring16: + { + LLVMMetadataRef char_type = lb_debug_type_basic_type(m, str_lit("wchar_t"), 16, LLVMDWARFTypeEncoding_Unsigned); + return LLVMDIBuilderCreatePointerType(m->debug_builder, char_type, ptr_bits, ptr_bits, 0, "cstring16", 7); + } + case Basic_any: { LLVMMetadataRef elements[2] = {}; diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index fbf0dea11..3463b6083 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -4354,12 +4354,13 @@ gb_internal lbAddr lb_build_addr_index_expr(lbProcedure *p, Ast *expr) { } - case Type_Basic: { // Basic_string + case Type_Basic: { // Basic_string/Basic_string16 lbValue str; lbValue elem; lbValue len; lbValue index; + str = lb_build_expr(p, ie->expr); if (deref) { str = lb_emit_load(p, str); diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp index d9771a75b..9ef1c23c0 100644 --- a/src/llvm_backend_general.cpp +++ b/src/llvm_backend_general.cpp @@ -2715,6 +2715,43 @@ gb_internal LLVMValueRef lb_find_or_add_entity_string_ptr(lbModule *m, String co } } +gb_internal LLVMValueRef lb_find_or_add_entity_string16_ptr(lbModule *m, String16 const &str, bool custom_link_section) { + // TODO(bill): caching for UTF-16 strings + + LLVMValueRef indices[2] = {llvm_zero(m), llvm_zero(m)}; + + LLVMValueRef data = nullptr; + { + LLVMTypeRef llvm_u16 = LLVMInt16TypeInContext(m->ctx); + + TEMPORARY_ALLOCATOR_GUARD(); + + LLVMValueRef *values = gb_alloc_array(temporary_allocator(), LLVMValueRef, str.len+1); + + for (isize i = 0; i < str.len; i++) { + values[i] = LLVMConstInt(llvm_u16, str.text[i], false); + } + values[str.len] = LLVMConstInt(llvm_u16, 0, false); + + data = LLVMConstArray(llvm_u16, values, cast(unsigned)(str.len+1)); + } + + + u32 id = m->global_array_index.fetch_add(1); + gbString name = gb_string_make(temporary_allocator(), "csbs$"); + name = gb_string_appendc(name, m->module_name); + name = gb_string_append_fmt(name, "$%x", id); + + LLVMTypeRef type = LLVMTypeOf(data); + LLVMValueRef global_data = LLVMAddGlobal(m->mod, type, name); + LLVMSetInitializer(global_data, data); + lb_make_global_private_const(global_data); + LLVMSetAlignment(global_data, 1); + + LLVMValueRef ptr = LLVMConstInBoundsGEP2(type, global_data, indices, 2); + return ptr; +} + gb_internal lbValue lb_find_or_add_entity_string(lbModule *m, String const &str, bool custom_link_section) { LLVMValueRef ptr = nullptr; if (str.len != 0) { diff --git a/src/llvm_backend_utility.cpp b/src/llvm_backend_utility.cpp index d4117b7ff..ea1bae4e9 100644 --- a/src/llvm_backend_utility.cpp +++ b/src/llvm_backend_utility.cpp @@ -6,6 +6,7 @@ gb_internal bool lb_is_type_aggregate(Type *t) { case Type_Basic: switch (t->Basic.kind) { case Basic_string: + case Basic_string16: case Basic_any: return true; @@ -981,7 +982,8 @@ gb_internal i32 lb_convert_struct_index(lbModule *m, Type *t, i32 index) { } else if (build_context.ptr_size != build_context.int_size) { switch (t->kind) { case Type_Basic: - if (t->Basic.kind != Basic_string) { + if (t->Basic.kind != Basic_string && + t->Basic.kind != Basic_string16) { break; } /*fallthrough*/ @@ -1160,6 +1162,11 @@ gb_internal lbValue lb_emit_struct_ep(lbProcedure *p, lbValue s, i32 index) { case 0: result_type = alloc_type_pointer(t->Slice.elem); break; case 1: result_type = t_int; break; } + } else if (is_type_string16(t)) { + switch (index) { + case 0: result_type = t_u16_ptr; break; + case 1: result_type = t_int; break; + } } else if (is_type_string(t)) { switch (index) { case 0: result_type = t_u8_ptr; break; @@ -1273,6 +1280,12 @@ gb_internal lbValue lb_emit_struct_ev(lbProcedure *p, lbValue s, i32 index) { switch (t->kind) { case Type_Basic: switch (t->Basic.kind) { + case Basic_string16: + switch (index) { + case 0: result_type = t_u16_ptr; break; + case 1: result_type = t_int; break; + } + break; case Basic_string: switch (index) { case 0: result_type = t_u8_ptr; break; @@ -1440,6 +1453,10 @@ gb_internal lbValue lb_emit_deep_field_gep(lbProcedure *p, lbValue e, Selection e = lb_emit_struct_ep(p, e, index); break; + case Basic_string16: + e = lb_emit_struct_ep(p, e, index); + break; + default: GB_PANIC("un-gep-able type %s", type_to_string(type)); break; diff --git a/src/string.cpp b/src/string.cpp index 8405938f4..8cc0e93f3 100644 --- a/src/string.cpp +++ b/src/string.cpp @@ -79,6 +79,13 @@ gb_internal String substring(String const &s, isize lo, isize hi) { return make_string(s.text+lo, hi-lo); } +gb_internal String16 substring(String16 const &s, isize lo, isize hi) { + isize max = s.len; + GB_ASSERT_MSG(lo <= hi && hi <= max, "%td..%td..%td", lo, hi, max); + + return make_string16(s.text+lo, hi-lo); +} + gb_internal char *alloc_cstring(gbAllocator a, String s) { char *c_str = gb_alloc_array(a, char, s.len+1); From bb4bc316a4bd86774953f1e8fcefffb5ed8bbf37 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 2 Aug 2025 12:20:35 +0100 Subject: [PATCH 005/105] `for in string16`; Support `string16` across core --- base/runtime/internal.odin | 62 +++++++++++++ core/c/libc/locale.odin | 16 ++-- core/debug/trace/trace_windows.odin | 2 +- core/dynlib/lib_windows.odin | 2 +- core/mem/virtual/virtual_windows.odin | 2 +- core/os/dir_windows.odin | 2 +- core/os/os2/file_windows.odin | 2 +- core/os/stat_windows.odin | 4 +- core/path/filepath/path_windows.odin | 4 +- core/sys/info/platform_windows.odin | 12 +-- core/sys/windows/comctl32.odin | 10 +-- core/sys/windows/ip_helper.odin | 6 +- core/sys/windows/types.odin | 4 +- core/sys/windows/util.odin | 50 +++++------ core/time/timezone/tz_windows.odin | 8 +- core/unicode/utf16/utf16.odin | 32 ++++++- src/check_builtin.cpp | 6 +- src/check_expr.cpp | 2 +- src/check_stmt.cpp | 26 +++++- src/llvm_backend_stmt.cpp | 121 +++++++++++++++++++++++++- src/llvm_backend_utility.cpp | 17 ++++ 21 files changed, 321 insertions(+), 69 deletions(-) diff --git a/base/runtime/internal.odin b/base/runtime/internal.odin index 660af58ab..4f9509b23 100644 --- a/base/runtime/internal.odin +++ b/base/runtime/internal.odin @@ -781,6 +781,68 @@ string_decode_last_rune :: proc "contextless" (s: string) -> (rune, int) { return r, size } + +string16_decode_rune :: #force_inline proc "contextless" (s: string16) -> (rune, int) { + REPLACEMENT_CHAR :: '\ufffd' + _surr1 :: 0xd800 + _surr2 :: 0xdc00 + _surr3 :: 0xe000 + _surr_self :: 0x10000 + + r := rune(REPLACEMENT_CHAR) + + if len(s) < 1 { + return r, 0 + } + + w := 1 + switch c := s[0]; { + case c < _surr1, _surr3 <= c: + r = rune(c) + case _surr1 <= c && c < _surr2 && 1 < len(s) && + _surr2 <= s[1] && s[1] < _surr3: + r1, r2 := rune(c), rune(s[1]) + if _surr1 <= r1 && r1 < _surr2 && _surr2 <= r2 && r2 < _surr3 { + r = (r1-_surr1)<<10 | (r2 - _surr2) + _surr_self + } + w += 1 + } + return r, w +} + +string16_decode_last_rune :: proc "contextless" (s: string16) -> (rune, int) { + REPLACEMENT_CHAR :: '\ufffd' + _surr1 :: 0xd800 + _surr2 :: 0xdc00 + _surr3 :: 0xe000 + _surr_self :: 0x10000 + + r := rune(REPLACEMENT_CHAR) + + if len(s) < 1 { + return r, 0 + } + + n := len(s)-1 + c := s[n] + w := 1 + if _surr2 <= c && c < _surr3 { + if n >= 1 { + r1 := rune(s[n-1]) + r2 := rune(c) + if _surr1 <= r1 && r1 < _surr2 { + r = (r1-_surr1)<<10 | (r2 - _surr2) + _surr_self + } + w = 2 + } + } else if c < _surr1 || _surr3 <= c { + r = rune(c) + } + return r, w +} + + + abs_complex32 :: #force_inline proc "contextless" (x: complex32) -> f16 { p, q := abs(real(x)), abs(imag(x)) if p < q { diff --git a/core/c/libc/locale.odin b/core/c/libc/locale.odin index 27317526c..3216e0f90 100644 --- a/core/c/libc/locale.odin +++ b/core/c/libc/locale.odin @@ -72,14 +72,14 @@ when ODIN_OS == .Windows { n_sep_by_space: c.char, p_sign_posn: c.char, n_sign_posn: c.char, - _W_decimal_point: [^]u16 `fmt:"s,0"`, - _W_thousands_sep: [^]u16 `fmt:"s,0"`, - _W_int_curr_symbol: [^]u16 `fmt:"s,0"`, - _W_currency_symbol: [^]u16 `fmt:"s,0"`, - _W_mon_decimal_point: [^]u16 `fmt:"s,0"`, - _W_mon_thousands_sep: [^]u16 `fmt:"s,0"`, - _W_positive_sign: [^]u16 `fmt:"s,0"`, - _W_negative_sign: [^]u16 `fmt:"s,0"`, + _W_decimal_point: cstring16, + _W_thousands_sep: cstring16, + _W_int_curr_symbol: cstring16, + _W_currency_symbol: cstring16, + _W_mon_decimal_point: cstring16, + _W_mon_thousands_sep: cstring16, + _W_positive_sign: cstring16, + _W_negative_sign: cstring16, } } else { lconv :: struct { diff --git a/core/debug/trace/trace_windows.odin b/core/debug/trace/trace_windows.odin index 96507714c..04e92f125 100644 --- a/core/debug/trace/trace_windows.odin +++ b/core/debug/trace/trace_windows.odin @@ -54,7 +54,7 @@ _resolve :: proc(ctx: ^Context, frame: Frame, allocator: runtime.Allocator) -> ( symbol.SizeOfStruct = size_of(symbol^) symbol.MaxNameLen = 255 if win32.SymFromAddrW(ctx.impl.hProcess, win32.DWORD64(frame), &{}, symbol) { - fl.procedure, _ = win32.wstring_to_utf8(&symbol.Name[0], -1, allocator) + fl.procedure, _ = win32.wstring_to_utf8(cstring16(&symbol.Name[0]), -1, allocator) } else { fl.procedure = fmt.aprintf("(procedure: 0x%x)", frame, allocator=allocator) } diff --git a/core/dynlib/lib_windows.odin b/core/dynlib/lib_windows.odin index 05cd2cb3c..95372dac6 100644 --- a/core/dynlib/lib_windows.odin +++ b/core/dynlib/lib_windows.odin @@ -13,7 +13,7 @@ _LIBRARY_FILE_EXTENSION :: "dll" _load_library :: proc(path: string, global_symbols: bool, allocator: runtime.Allocator) -> (Library, bool) { // NOTE(bill): 'global_symbols' is here only for consistency with POSIX which has RTLD_GLOBAL wide_path := win32.utf8_to_wstring(path, allocator) - defer free(wide_path, allocator) + defer free(rawptr(wide_path), allocator) handle := cast(Library)win32.LoadLibraryW(wide_path) return handle, handle != nil } diff --git a/core/mem/virtual/virtual_windows.odin b/core/mem/virtual/virtual_windows.odin index 0da8498d5..3fd4eeb68 100644 --- a/core/mem/virtual/virtual_windows.odin +++ b/core/mem/virtual/virtual_windows.odin @@ -72,7 +72,7 @@ foreign Kernel32 { flProtect: u32, dwMaximumSizeHigh: u32, dwMaximumSizeLow: u32, - lpName: [^]u16, + lpName: cstring16, ) -> rawptr --- MapViewOfFile :: proc( diff --git a/core/os/dir_windows.odin b/core/os/dir_windows.odin index ae3e6922c..40f4b9e9b 100644 --- a/core/os/dir_windows.odin +++ b/core/os/dir_windows.odin @@ -87,7 +87,7 @@ read_dir :: proc(fd: Handle, n: int, allocator := context.allocator) -> (fi: []F defer delete(path) find_data := &win32.WIN32_FIND_DATAW{} - find_handle := win32.FindFirstFileW(raw_data(wpath_search), find_data) + find_handle := win32.FindFirstFileW(cstring16(raw_data(wpath_search)), find_data) if find_handle == win32.INVALID_HANDLE_VALUE { err = get_last_error() return dfi[:], err diff --git a/core/os/os2/file_windows.odin b/core/os/os2/file_windows.odin index 40d012183..1134e765c 100644 --- a/core/os/os2/file_windows.odin +++ b/core/os/os2/file_windows.odin @@ -619,7 +619,7 @@ _symlink :: proc(old_name, new_name: string) -> Error { return .Unsupported } -_open_sym_link :: proc(p: [^]u16) -> (handle: win32.HANDLE, err: Error) { +_open_sym_link :: proc(p: cstring16) -> (handle: win32.HANDLE, err: Error) { attrs := u32(win32.FILE_FLAG_BACKUP_SEMANTICS) attrs |= win32.FILE_FLAG_OPEN_REPARSE_POINT handle = win32.CreateFileW(p, 0, 0, nil, win32.OPEN_EXISTING, attrs, nil) diff --git a/core/os/stat_windows.odin b/core/os/stat_windows.odin index ca4f87668..662c9f9e6 100644 --- a/core/os/stat_windows.odin +++ b/core/os/stat_windows.odin @@ -17,7 +17,7 @@ full_path_from_name :: proc(name: string, allocator := context.allocator) -> (pa buf := make([dynamic]u16, 100) defer delete(buf) for { - n := win32.GetFullPathNameW(raw_data(p), u32(len(buf)), raw_data(buf), nil) + n := win32.GetFullPathNameW(cstring16(raw_data(p)), u32(len(buf)), cstring16(raw_data(buf)), nil) if n == 0 { return "", get_last_error() } @@ -154,7 +154,7 @@ cleanpath_from_handle_u16 :: proc(fd: Handle, allocator: runtime.Allocator) -> ( return nil, get_last_error() } buf := make([]u16, max(n, win32.DWORD(260))+1, allocator) - buf_len := win32.GetFinalPathNameByHandleW(h, raw_data(buf), n, 0) + buf_len := win32.GetFinalPathNameByHandleW(h, cstring16(raw_data(buf)), n, 0) return buf[:buf_len], nil } @(private, require_results) diff --git a/core/path/filepath/path_windows.odin b/core/path/filepath/path_windows.odin index 0dcb28cf8..24c6e00a5 100644 --- a/core/path/filepath/path_windows.odin +++ b/core/path/filepath/path_windows.odin @@ -61,13 +61,13 @@ temp_full_path :: proc(name: string) -> (path: string, err: os.Error) { } p := win32.utf8_to_utf16(name, ta) - n := win32.GetFullPathNameW(raw_data(p), 0, nil, nil) + n := win32.GetFullPathNameW(cstring16(raw_data(p)), 0, nil, nil) if n == 0 { return "", os.get_last_error() } buf := make([]u16, n, ta) - n = win32.GetFullPathNameW(raw_data(p), u32(len(buf)), raw_data(buf), nil) + n = win32.GetFullPathNameW(cstring16(raw_data(p)), u32(len(buf)), cstring16(raw_data(buf)), nil) if n == 0 { delete(buf) return "", os.get_last_error() diff --git a/core/sys/info/platform_windows.odin b/core/sys/info/platform_windows.odin index 4c00ddadf..dd1441d30 100644 --- a/core/sys/info/platform_windows.odin +++ b/core/sys/info/platform_windows.odin @@ -324,8 +324,8 @@ read_reg_string :: proc(hkey: sys.HKEY, subkey, val: string) -> (res: string, ok status := sys.RegGetValueW( hkey, - &key_name_wide[0], - &val_name_wide[0], + cstring16(&key_name_wide[0]), + cstring16(&val_name_wide[0]), sys.RRF_RT_REG_SZ, nil, raw_data(result_wide[:]), @@ -359,8 +359,8 @@ read_reg_i32 :: proc(hkey: sys.HKEY, subkey, val: string) -> (res: i32, ok: bool result_size := sys.DWORD(size_of(i32)) status := sys.RegGetValueW( hkey, - &key_name_wide[0], - &val_name_wide[0], + cstring16(&key_name_wide[0]), + cstring16(&val_name_wide[0]), sys.RRF_RT_REG_DWORD, nil, &res, @@ -386,8 +386,8 @@ read_reg_i64 :: proc(hkey: sys.HKEY, subkey, val: string) -> (res: i64, ok: bool result_size := sys.DWORD(size_of(i64)) status := sys.RegGetValueW( hkey, - &key_name_wide[0], - &val_name_wide[0], + cstring16(&key_name_wide[0]), + cstring16(&val_name_wide[0]), sys.RRF_RT_REG_QWORD, nil, &res, diff --git a/core/sys/windows/comctl32.odin b/core/sys/windows/comctl32.odin index d954f952c..c7a166634 100644 --- a/core/sys/windows/comctl32.odin +++ b/core/sys/windows/comctl32.odin @@ -573,10 +573,10 @@ Button_GetTextMargin :: #force_inline proc "system" (hwnd: HWND, pmargin: ^RECT) return cast(BOOL)SendMessageW(hwnd, BCM_GETTEXTMARGIN, 0, cast(LPARAM)uintptr(pmargin)) } Button_SetNote :: #force_inline proc "system" (hwnd: HWND, psz: LPCWSTR) -> BOOL { - return cast(BOOL)SendMessageW(hwnd, BCM_SETNOTE, 0, cast(LPARAM)uintptr(psz)) + return cast(BOOL)SendMessageW(hwnd, BCM_SETNOTE, 0, cast(LPARAM)uintptr(rawptr(psz))) } Button_GetNote :: #force_inline proc "system" (hwnd: HWND, psz: LPCWSTR, pcc: ^c_int) -> BOOL { - return cast(BOOL)SendMessageW(hwnd, BCM_GETNOTE, uintptr(pcc), cast(LPARAM)uintptr(psz)) + return cast(BOOL)SendMessageW(hwnd, BCM_GETNOTE, uintptr(pcc), cast(LPARAM)uintptr(rawptr(psz))) } Button_GetNoteLength :: #force_inline proc "system" (hwnd: HWND) -> LRESULT { return SendMessageW(hwnd, BCM_GETNOTELENGTH, 0, 0) @@ -604,10 +604,10 @@ EDITBALLOONTIP :: struct { PEDITBALLOONTIP :: ^EDITBALLOONTIP Edit_SetCueBannerText :: #force_inline proc "system" (hwnd: HWND, lpcwText: LPCWSTR) -> BOOL { - return cast(BOOL)SendMessageW(hwnd, EM_SETCUEBANNER, 0, cast(LPARAM)uintptr(lpcwText)) + return cast(BOOL)SendMessageW(hwnd, EM_SETCUEBANNER, 0, cast(LPARAM)uintptr(rawptr(lpcwText))) } Edit_SetCueBannerTextFocused :: #force_inline proc "system" (hwnd: HWND, lpcwText: LPCWSTR, fDrawFocused: BOOL) -> BOOL { - return cast(BOOL)SendMessageW(hwnd, EM_SETCUEBANNER, cast(WPARAM)fDrawFocused, cast(LPARAM)uintptr(lpcwText)) + return cast(BOOL)SendMessageW(hwnd, EM_SETCUEBANNER, cast(WPARAM)fDrawFocused, cast(LPARAM)uintptr(rawptr(lpcwText))) } Edit_GetCueBannerText :: #force_inline proc "system" (hwnd: HWND, lpwText: LPWSTR, cchText: LONG) -> BOOL { return cast(BOOL)SendMessageW(hwnd, EM_GETCUEBANNER, uintptr(lpwText), cast(LPARAM)cchText) @@ -1197,7 +1197,7 @@ ListView_GetItemPosition :: #force_inline proc "system" (hwnd: HWND, i: c_int, p return cast(BOOL)SendMessageW(hwnd, LVM_GETITEMPOSITION, cast(WPARAM)i, cast(LPARAM)uintptr(ppt)) } ListView_GetStringWidth :: #force_inline proc "system" (hwndLV: HWND, psz: LPCWSTR) -> c_int { - return cast(c_int)SendMessageW(hwndLV, LVM_GETSTRINGWIDTHW, 0, cast(LPARAM)uintptr(psz)) + return cast(c_int)SendMessageW(hwndLV, LVM_GETSTRINGWIDTHW, 0, cast(LPARAM)uintptr(rawptr(psz))) } ListView_HitTest :: #force_inline proc "system" (hwndLV: HWND, pinfo: ^LV_HITTESTINFO) -> c_int { return cast(c_int)SendMessageW(hwndLV, LVM_HITTEST, 0, cast(LPARAM)uintptr(pinfo)) diff --git a/core/sys/windows/ip_helper.odin b/core/sys/windows/ip_helper.odin index 7a6e545ac..d2e75d531 100644 --- a/core/sys/windows/ip_helper.odin +++ b/core/sys/windows/ip_helper.odin @@ -38,9 +38,9 @@ IP_Adapter_Addresses :: struct { FirstAnycastAddress: ^IP_ADAPTER_ANYCAST_ADDRESS_XP, FirstMulticastAddress: ^IP_ADAPTER_MULTICAST_ADDRESS_XP, FirstDnsServerAddress: ^IP_ADAPTER_DNS_SERVER_ADDRESS_XP, - DnsSuffix: ^u16, - Description: ^u16, - FriendlyName: ^u16, + DnsSuffix: cstring16, + Description: cstring16, + FriendlyName: cstring16, PhysicalAddress: [8]u8, PhysicalAddressLength: u32, Anonymous2: struct #raw_union { diff --git a/core/sys/windows/types.odin b/core/sys/windows/types.odin index 92b1cb15c..be16d2fdd 100644 --- a/core/sys/windows/types.odin +++ b/core/sys/windows/types.odin @@ -107,8 +107,8 @@ PDWORD64 :: ^DWORD64 PDWORD_PTR :: ^DWORD_PTR ATOM :: distinct WORD -wstring :: [^]WCHAR -PWSTR :: [^]WCHAR +wstring :: cstring16 +PWSTR :: cstring16 PBYTE :: ^BYTE LPBYTE :: ^BYTE diff --git a/core/sys/windows/util.odin b/core/sys/windows/util.odin index 995e8e0e5..10dc907e7 100644 --- a/core/sys/windows/util.odin +++ b/core/sys/windows/util.odin @@ -122,14 +122,14 @@ utf8_to_utf16 :: proc{utf8_to_utf16_alloc, utf8_to_utf16_buf} utf8_to_wstring_alloc :: proc(s: string, allocator := context.temp_allocator) -> wstring { if res := utf8_to_utf16(s, allocator); len(res) > 0 { - return raw_data(res) + return wstring(raw_data(res)) } return nil } utf8_to_wstring_buf :: proc(buf: []u16, s: string) -> wstring { if res := utf8_to_utf16(buf, s); len(res) > 0 { - return raw_data(res) + return wstring(raw_data(res)) } return nil } @@ -215,7 +215,7 @@ utf16_to_utf8_alloc :: proc(s: []u16, allocator := context.temp_allocator) -> (r if len(s) == 0 { return "", nil } - return wstring_to_utf8(raw_data(s), len(s), allocator) + return wstring_to_utf8(wstring(raw_data(s)), len(s), allocator) } /* @@ -236,7 +236,7 @@ utf16_to_utf8_buf :: proc(buf: []u8, s: []u16) -> (res: string) { if len(s) == 0 { return } - return wstring_to_utf8(buf, raw_data(s), len(s)) + return wstring_to_utf8(buf, wstring(raw_data(s)), len(s)) } utf16_to_utf8 :: proc{utf16_to_utf8_alloc, utf16_to_utf8_buf} @@ -298,7 +298,7 @@ _add_user :: proc(servername: string, username: string, password: string) -> (ok servername_w = nil } else { server := utf8_to_utf16(servername, context.temp_allocator) - servername_w = &server[0] + servername_w = wstring(&server[0]) } if len(username) == 0 || len(username) > LM20_UNLEN { @@ -348,7 +348,7 @@ get_computer_name_and_account_sid :: proc(username: string) -> (computer_name: s res := LookupAccountNameW( nil, // Look on this computer first - &username_w[0], + wstring(&username_w[0]), &sid, &cbsid, nil, @@ -364,10 +364,10 @@ get_computer_name_and_account_sid :: proc(username: string) -> (computer_name: s res = LookupAccountNameW( nil, - &username_w[0], + wstring(&username_w[0]), &sid, &cbsid, - &cname_w[0], + wstring(&cname_w[0]), &computer_name_size, &pe_use, ) @@ -390,7 +390,7 @@ get_sid :: proc(username: string, sid: ^SID) -> (ok: bool) { res := LookupAccountNameW( nil, // Look on this computer first - &username_w[0], + wstring(&username_w[0]), sid, &cbsid, nil, @@ -406,10 +406,10 @@ get_sid :: proc(username: string, sid: ^SID) -> (ok: bool) { res = LookupAccountNameW( nil, - &username_w[0], + wstring(&username_w[0]), sid, &cbsid, - &cname_w[0], + wstring(&cname_w[0]), &computer_name_size, &pe_use, ) @@ -428,7 +428,7 @@ add_user_to_group :: proc(sid: ^SID, group: string) -> (ok: NET_API_STATUS) { group_name := utf8_to_utf16(group, context.temp_allocator) ok = NetLocalGroupAddMembers( nil, - &group_name[0], + wstring(&group_name[0]), 0, &group_member, 1, @@ -443,7 +443,7 @@ add_del_from_group :: proc(sid: ^SID, group: string) -> (ok: NET_API_STATUS) { group_name := utf8_to_utf16(group, context.temp_allocator) ok = NetLocalGroupDelMembers( nil, - &group_name[0], + cstring16(&group_name[0]), 0, &group_member, 1, @@ -465,19 +465,19 @@ add_user_profile :: proc(username: string) -> (ok: bool, profile_path: string) { if res == false { return false, "" } - defer LocalFree(sb) + defer LocalFree(rawptr(sb)) pszProfilePath := make([]u16, 257, context.temp_allocator) res2 := CreateProfile( sb, - &username_w[0], - &pszProfilePath[0], + cstring16(&username_w[0]), + cstring16(&pszProfilePath[0]), 257, ) if res2 != 0 { return false, "" } - profile_path = wstring_to_utf8(&pszProfilePath[0], 257) or_else "" + profile_path = wstring_to_utf8(wstring(&pszProfilePath[0]), 257) or_else "" return true, profile_path } @@ -495,7 +495,7 @@ delete_user_profile :: proc(username: string) -> (ok: bool) { if res == false { return false } - defer LocalFree(sb) + defer LocalFree(rawptr(sb)) res2 := DeleteProfileW( sb, @@ -548,13 +548,13 @@ delete_user :: proc(servername: string, username: string) -> (ok: bool) { servername_w = nil } else { server := utf8_to_utf16(servername, context.temp_allocator) - servername_w = &server[0] + servername_w = wstring(&server[0]) } username_w := utf8_to_utf16(username) res := NetUserDel( servername_w, - &username_w[0], + wstring(&username_w[0]), ) if res != .Success { return false @@ -586,9 +586,9 @@ run_as_user :: proc(username, password, application, commandline: string, pi: ^P user_token: HANDLE ok = bool(LogonUserW( - lpszUsername = &username_w[0], - lpszDomain = &domain_w[0], - lpszPassword = &password_w[0], + lpszUsername = wstring(&username_w[0]), + lpszDomain = wstring(&domain_w[0]), + lpszPassword = wstring(&password_w[0]), dwLogonType = .NEW_CREDENTIALS, dwLogonProvider = .WINNT50, phToken = &user_token, @@ -605,8 +605,8 @@ run_as_user :: proc(username, password, application, commandline: string, pi: ^P ok = bool(CreateProcessAsUserW( user_token, - &app_w[0], - &commandline_w[0], + wstring(&app_w[0]), + wstring(&commandline_w[0]), nil, // lpProcessAttributes, nil, // lpThreadAttributes, false, // bInheritHandles, diff --git a/core/time/timezone/tz_windows.odin b/core/time/timezone/tz_windows.odin index 8dc5f533c..fe00719a2 100644 --- a/core/time/timezone/tz_windows.odin +++ b/core/time/timezone/tz_windows.odin @@ -159,9 +159,9 @@ iana_to_windows_tz :: proc(iana_name: string, allocator := context.allocator) -> status: windows.UError iana_name_wstr := windows.utf8_to_wstring(iana_name, allocator) - defer free(iana_name_wstr, allocator) + defer free(rawptr(iana_name_wstr), allocator) - wintz_name_len := windows.ucal_getWindowsTimeZoneID(iana_name_wstr, -1, raw_data(wintz_name_buffer[:]), len(wintz_name_buffer), &status) + wintz_name_len := windows.ucal_getWindowsTimeZoneID(iana_name_wstr, -1, cstring16(raw_data(wintz_name_buffer[:])), len(wintz_name_buffer), &status) if status != .U_ZERO_ERROR { return } @@ -178,7 +178,7 @@ local_tz_name :: proc(allocator := context.allocator) -> (name: string, success: iana_name_buffer: [128]u16 status: windows.UError - zone_str_len := windows.ucal_getDefaultTimeZone(raw_data(iana_name_buffer[:]), len(iana_name_buffer), &status) + zone_str_len := windows.ucal_getDefaultTimeZone(cstring16(raw_data(iana_name_buffer[:])), len(iana_name_buffer), &status) if status != .U_ZERO_ERROR { return } @@ -291,7 +291,7 @@ _region_load :: proc(reg_str: string, allocator := context.allocator) -> (out_re defer delete(tz_key, allocator) tz_key_wstr := windows.utf8_to_wstring(tz_key, allocator) - defer free(tz_key_wstr, allocator) + defer free(rawptr(tz_key_wstr), allocator) key: windows.HKEY res := windows.RegOpenKeyExW(windows.HKEY_LOCAL_MACHINE, tz_key_wstr, 0, windows.KEY_READ, &key) diff --git a/core/unicode/utf16/utf16.odin b/core/unicode/utf16/utf16.odin index 9a8cfe438..d3f98584b 100644 --- a/core/unicode/utf16/utf16.odin +++ b/core/unicode/utf16/utf16.odin @@ -126,7 +126,37 @@ decode_rune_in_string :: proc(s: string16) -> (r: rune, width: int) { return } -rune_count :: proc(s: []u16) -> (n: int) { +string_to_runes :: proc "odin" (s: string16, allocator := context.allocator) -> (runes: []rune) { + n := rune_count(s) + + runes = make([]rune, n, allocator) + i := 0 + for r in s { + runes[i] = r + i += 1 + } + return +} + + +rune_count :: proc{ + rune_count_in_string, + rune_count_in_slice, +} +rune_count_in_string :: proc(s: string16) -> (n: int) { + for i := 0; i < len(s); i += 1 { + c := s[i] + if _surr1 <= c && c < _surr2 && i+1 < len(s) && + _surr2 <= s[i+1] && s[i+1] < _surr3 { + i += 1 + } + n += 1 + } + return +} + + +rune_count_in_slice :: proc(s: []u16) -> (n: int) { for i := 0; i < len(s); i += 1 { c := s[i] if _surr1 <= c && c < _surr2 && i+1 < len(s) && diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index 4abace637..66ea0cfbd 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -7179,7 +7179,11 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As return false; } operand->mode = Addressing_Value; - operand->type = alloc_type_multi_pointer(t_u16); + if (type_hint != nullptr && is_type_cstring16(type_hint)) { + operand->type = type_hint; + } else { + operand->type = alloc_type_multi_pointer(t_u16); + } operand->value = {}; break; } diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 8d2e4d637..34149f92b 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -3426,7 +3426,7 @@ gb_internal bool check_is_castable_to(CheckerContext *c, Operand *operand, Type if (are_types_identical(src, t_cstring16) && is_type_u16_multi_ptr(dst)) { return !is_constant; } - // cstring -> rawptr + // cstring16 -> rawptr if (are_types_identical(src, t_cstring16) && is_type_rawptr(dst)) { return !is_constant; } diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index bc9b6c5dd..ae88ff333 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -974,7 +974,14 @@ gb_internal void check_unroll_range_stmt(CheckerContext *ctx, Ast *node, u32 mod Type *t = base_type(operand.type); switch (t->kind) { case Type_Basic: - if (is_type_string(t) && t->Basic.kind != Basic_cstring) { + if (is_type_string16(t) && t->Basic.kind != Basic_cstring) { + val0 = t_rune; + val1 = t_int; + inline_for_depth = exact_value_i64(operand.value.value_string.len); + if (unroll_count > 0) { + error(node, "#unroll(%lld) does not support strings", cast(long long)unroll_count); + } + } else if (is_type_string(t) && t->Basic.kind != Basic_cstring) { val0 = t_rune; val1 = t_int; inline_for_depth = exact_value_i64(operand.value.value_string.len); @@ -1236,7 +1243,11 @@ gb_internal void check_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags add_to_seen_map(ctx, &seen, upper_op, x, lhs, rhs); - if (is_type_string(x.type)) { + if (is_type_string16(x.type)) { + // NOTE(bill): Force dependency for strings here + add_package_dependency(ctx, "runtime", "string16_le"); + add_package_dependency(ctx, "runtime", "string16_lt"); + } else if (is_type_string(x.type)) { // NOTE(bill): Force dependency for strings here add_package_dependency(ctx, "runtime", "string_le"); add_package_dependency(ctx, "runtime", "string_lt"); @@ -1770,7 +1781,16 @@ gb_internal void check_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) switch (t->kind) { case Type_Basic: - if (t->Basic.kind == Basic_string || t->Basic.kind == Basic_UntypedString) { + if (t->Basic.kind == Basic_string16) { + is_possibly_addressable = false; + array_add(&vals, t_rune); + array_add(&vals, t_int); + if (is_reverse) { + add_package_dependency(ctx, "runtime", "string16_decode_last_rune"); + } else { + add_package_dependency(ctx, "runtime", "string16_decode_rune"); + } + } else if (t->Basic.kind == Basic_string || t->Basic.kind == Basic_UntypedString) { is_possibly_addressable = false; array_add(&vals, t_rune); array_add(&vals, t_int); diff --git a/src/llvm_backend_stmt.cpp b/src/llvm_backend_stmt.cpp index 027837f3f..5481ca447 100644 --- a/src/llvm_backend_stmt.cpp +++ b/src/llvm_backend_stmt.cpp @@ -622,6 +622,121 @@ gb_internal void lb_build_range_string(lbProcedure *p, lbValue expr, Type *val_t if (done_) *done_ = done; } +gb_internal void lb_build_range_string16(lbProcedure *p, lbValue expr, Type *val_type, + lbValue *val_, lbValue *idx_, lbBlock **loop_, lbBlock **done_, + bool is_reverse) { + + lbModule *m = p->module; + lbValue count = lb_const_int(m, t_int, 0); + Type *expr_type = base_type(expr.type); + switch (expr_type->kind) { + case Type_Basic: + count = lb_string_len(p, expr); + break; + default: + GB_PANIC("Cannot do range_string of %s", type_to_string(expr_type)); + break; + } + + lbValue val = {}; + lbValue idx = {}; + lbBlock *loop = nullptr; + lbBlock *done = nullptr; + lbBlock *body = nullptr; + + loop = lb_create_block(p, "for.string16.loop"); + body = lb_create_block(p, "for.string16.body"); + done = lb_create_block(p, "for.string16.done"); + + lbAddr offset_ = lb_add_local_generated(p, t_int, false); + lbValue offset = {}; + lbValue cond = {}; + + if (!is_reverse) { + /* + for c, offset in str { + ... + } + + offset := 0 + for offset < len(str) { + c, _w := string16_decode_rune(str[offset:]) + ... + offset += _w + } + */ + lb_addr_store(p, offset_, lb_const_int(m, t_int, 0)); + + lb_emit_jump(p, loop); + lb_start_block(p, loop); + + + offset = lb_addr_load(p, offset_); + cond = lb_emit_comp(p, Token_Lt, offset, count); + } else { + // NOTE(bill): REVERSED LOGIC + /* + #reverse for c, offset in str { + ... + } + + offset := len(str) + for offset > 0 { + c, _w := string16_decode_last_rune(str[:offset]) + offset -= _w + ... + } + */ + lb_addr_store(p, offset_, count); + + lb_emit_jump(p, loop); + lb_start_block(p, loop); + + offset = lb_addr_load(p, offset_); + cond = lb_emit_comp(p, Token_Gt, offset, lb_const_int(m, t_int, 0)); + } + lb_emit_if(p, cond, body, done); + lb_start_block(p, body); + + + lbValue rune_and_len = {}; + if (!is_reverse) { + lbValue str_elem = lb_emit_ptr_offset(p, lb_string_elem(p, expr), offset); + lbValue str_len = lb_emit_arith(p, Token_Sub, count, offset, t_int); + auto args = array_make(permanent_allocator(), 1); + args[0] = lb_emit_string16(p, str_elem, str_len); + + rune_and_len = lb_emit_runtime_call(p, "string16_decode_rune", args); + lbValue len = lb_emit_struct_ev(p, rune_and_len, 1); + lb_addr_store(p, offset_, lb_emit_arith(p, Token_Add, offset, len, t_int)); + + idx = offset; + } else { + // NOTE(bill): REVERSED LOGIC + lbValue str_elem = lb_string_elem(p, expr); + lbValue str_len = offset; + auto args = array_make(permanent_allocator(), 1); + args[0] = lb_emit_string16(p, str_elem, str_len); + + rune_and_len = lb_emit_runtime_call(p, "string16_decode_last_rune", args); + lbValue len = lb_emit_struct_ev(p, rune_and_len, 1); + lb_addr_store(p, offset_, lb_emit_arith(p, Token_Sub, offset, len, t_int)); + + idx = lb_addr_load(p, offset_); + } + + + if (val_type != nullptr) { + val = lb_emit_struct_ev(p, rune_and_len, 0); + } + + if (val_) *val_ = val; + if (idx_) *idx_ = idx; + if (loop_) *loop_ = loop; + if (done_) *done_ = done; +} + + gb_internal Ast *lb_strip_and_prefix(Ast *ident) { if (ident != nullptr) { @@ -1138,7 +1253,11 @@ gb_internal void lb_build_range_stmt(lbProcedure *p, AstRangeStmt *rs, Scope *sc } Type *t = base_type(string.type); GB_ASSERT(!is_type_cstring(t)); - lb_build_range_string(p, string, val0_type, &val, &key, &loop, &done, rs->reverse); + if (is_type_string16(t)) { + lb_build_range_string16(p, string, val0_type, &val, &key, &loop, &done, rs->reverse); + } else { + lb_build_range_string(p, string, val0_type, &val, &key, &loop, &done, rs->reverse); + } break; } case Type_Tuple: diff --git a/src/llvm_backend_utility.cpp b/src/llvm_backend_utility.cpp index ea1bae4e9..dcb95a9a2 100644 --- a/src/llvm_backend_utility.cpp +++ b/src/llvm_backend_utility.cpp @@ -191,6 +191,23 @@ gb_internal lbValue lb_emit_clamp(lbProcedure *p, Type *t, lbValue x, lbValue mi return z; } +gb_internal lbValue lb_emit_string16(lbProcedure *p, lbValue str_elem, lbValue str_len) { + if (false && lb_is_const(str_elem) && lb_is_const(str_len)) { + LLVMValueRef values[2] = { + str_elem.value, + str_len.value, + }; + lbValue res = {}; + res.type = t_string16; + res.value = llvm_const_named_struct(p->module, t_string16, values, gb_count_of(values)); + return res; + } else { + lbAddr res = lb_add_local_generated(p, t_string16, false); + lb_emit_store(p, lb_emit_struct_ep(p, res.addr, 0), str_elem); + lb_emit_store(p, lb_emit_struct_ep(p, res.addr, 1), str_len); + return lb_addr_load(p, res); + } +} gb_internal lbValue lb_emit_string(lbProcedure *p, lbValue str_elem, lbValue str_len) { From 620bf162a048fdf29fdfcedc12abae79cffeedf4 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 2 Aug 2025 12:32:18 +0100 Subject: [PATCH 006/105] Cache const `string16` in LLVM --- src/check_builtin.cpp | 13 +++++-- src/common.cpp | 1 + src/llvm_backend.hpp | 3 +- src/llvm_backend_const.cpp | 2 +- src/llvm_backend_expr.cpp | 6 --- src/llvm_backend_general.cpp | 71 +++++++++++++++++++++++++++++++++++- 6 files changed, 83 insertions(+), 13 deletions(-) diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index 66ea0cfbd..da5eb8977 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -2329,10 +2329,15 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As if (operand->mode == Addressing_Constant) { mode = Addressing_Constant; - GB_ASSERT_MSG(!is_type_string16(op_type), "TODO(bill): constant utf-16 string len"); - - String str = operand->value.value_string; - value = exact_value_i64(str.len); + if (operand->value.kind == ExactValue_String) { + String str = operand->value.value_string; + value = exact_value_i64(str.len); + } else if (operand->value.kind == ExactValue_String16) { + String16 str = operand->value.value_string16; + value = exact_value_i64(str.len); + } else { + GB_PANIC("Unhandled value kind: %d", operand->value.kind); + } type = t_untyped_integer; } else { mode = Addressing_Value; diff --git a/src/common.cpp b/src/common.cpp index b3761fc36..53848cacf 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -350,6 +350,7 @@ gb_global bool global_module_path_set = false; #include "ptr_map.cpp" #include "ptr_set.cpp" #include "string_map.cpp" +#include "string16_map.cpp" #include "string_set.cpp" #include "priority_queue.cpp" #include "thread_pool.cpp" diff --git a/src/llvm_backend.hpp b/src/llvm_backend.hpp index fef6e754d..648e8a732 100644 --- a/src/llvm_backend.hpp +++ b/src/llvm_backend.hpp @@ -173,7 +173,8 @@ struct lbModule { PtrMap procedure_values; Array missing_procedures_to_check; - StringMap const_strings; + StringMap const_strings; + String16Map const_string16s; PtrMap function_type_map; diff --git a/src/llvm_backend_const.cpp b/src/llvm_backend_const.cpp index 8c05ed4a2..cba0000cd 100644 --- a/src/llvm_backend_const.cpp +++ b/src/llvm_backend_const.cpp @@ -594,7 +594,7 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb return res; } else if (value.kind == ExactValue_String16) { GB_ASSERT(is_type_slice(type)); - GB_PANIC("TODO(bill): UTF-16 String"); + res.value = lb_find_or_add_entity_string16_slice_with_type(m, value.value_string16, original_type).value; return res; }else { ast_node(cl, CompoundLit, value.value_compound); diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index 3463b6083..8ad6a5a1c 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -2526,12 +2526,6 @@ gb_internal lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) { if (is_type_untyped(src)) { - if (is_type_string(src) && is_type_string16(dst)) { - GB_PANIC("TODO(bill): UTF-16 string"); - lbAddr result = lb_add_local_generated(p, t, false); - lb_addr_store(p, result, value); - return lb_addr_load(p, result); - } if (is_type_string(src) && is_type_string(dst)) { lbAddr result = lb_add_local_generated(p, t, false); lb_addr_store(p, result, value); diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp index 9ef1c23c0..064d0ef39 100644 --- a/src/llvm_backend_general.cpp +++ b/src/llvm_backend_general.cpp @@ -85,6 +85,7 @@ gb_internal void lb_init_module(lbModule *m, Checker *c) { string_map_init(&m->members); string_map_init(&m->procedures); string_map_init(&m->const_strings); + string16_map_init(&m->const_string16s); map_init(&m->function_type_map); string_map_init(&m->gen_procs); if (USE_SEPARATE_MODULES) { @@ -2716,7 +2717,18 @@ gb_internal LLVMValueRef lb_find_or_add_entity_string_ptr(lbModule *m, String co } gb_internal LLVMValueRef lb_find_or_add_entity_string16_ptr(lbModule *m, String16 const &str, bool custom_link_section) { - // TODO(bill): caching for UTF-16 strings + String16HashKey key = {}; + LLVMValueRef *found = nullptr; + + if (!custom_link_section) { + key = string_hash_string(str); + found = string16_map_get(&m->const_string16s, key); + } + if (found != nullptr) { + return *found; + } + + LLVMValueRef indices[2] = {llvm_zero(m), llvm_zero(m)}; @@ -2749,6 +2761,9 @@ gb_internal LLVMValueRef lb_find_or_add_entity_string16_ptr(lbModule *m, String1 LLVMSetAlignment(global_data, 1); LLVMValueRef ptr = LLVMConstInBoundsGEP2(type, global_data, indices, 2); + if (!custom_link_section) { + string16_map_set(&m->const_string16s, key, ptr); + } return ptr; } @@ -2812,6 +2827,60 @@ gb_internal lbValue lb_find_or_add_entity_string_byte_slice_with_type(lbModule * return res; } +gb_internal lbValue lb_find_or_add_entity_string16_slice_with_type(lbModule *m, String16 const &str, Type *slice_type) { + GB_ASSERT(is_type_slice(slice_type)); + LLVMValueRef indices[2] = {llvm_zero(m), llvm_zero(m)}; + LLVMValueRef data = nullptr; + { + LLVMTypeRef llvm_u16 = LLVMInt16TypeInContext(m->ctx); + + TEMPORARY_ALLOCATOR_GUARD(); + + LLVMValueRef *values = gb_alloc_array(temporary_allocator(), LLVMValueRef, str.len+1); + + for (isize i = 0; i < str.len; i++) { + values[i] = LLVMConstInt(llvm_u16, str.text[i], false); + } + values[str.len] = LLVMConstInt(llvm_u16, 0, false); + + data = LLVMConstArray(llvm_u16, values, cast(unsigned)(str.len+1)); + } + + u32 id = m->global_array_index.fetch_add(1); + gbString name = gb_string_make(temporary_allocator(), "csba$"); + name = gb_string_appendc(name, m->module_name); + name = gb_string_append_fmt(name, "$%x", id); + + LLVMTypeRef type = LLVMTypeOf(data); + LLVMValueRef global_data = LLVMAddGlobal(m->mod, type, name); + LLVMSetInitializer(global_data, data); + lb_make_global_private_const(global_data); + LLVMSetAlignment(global_data, 1); + + i64 data_len = str.len; + LLVMValueRef ptr = nullptr; + if (data_len != 0) { + ptr = LLVMConstInBoundsGEP2(type, global_data, indices, 2); + } else { + ptr = LLVMConstNull(lb_type(m, t_u8_ptr)); + } + if (!is_type_u16_slice(slice_type)) { + Type *bt = base_type(slice_type); + Type *elem = bt->Slice.elem; + i64 sz = type_size_of(elem); + GB_ASSERT(sz > 0); + ptr = LLVMConstPointerCast(ptr, lb_type(m, alloc_type_pointer(elem))); + data_len /= sz; + } + + LLVMValueRef len = LLVMConstInt(lb_type(m, t_int), data_len, true); + LLVMValueRef values[2] = {ptr, len}; + + lbValue res = {}; + res.value = llvm_const_named_struct(m, slice_type, values, 2); + res.type = slice_type; + return res; +} gb_internal lbValue lb_find_ident(lbProcedure *p, lbModule *m, Entity *e, Ast *expr) { From 9b5700225d3d2e22003251ed8578fb2ccdee1ec2 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 2 Aug 2025 12:33:33 +0100 Subject: [PATCH 007/105] Add string16_map.cpp --- src/string16_map.cpp | 538 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 538 insertions(+) create mode 100644 src/string16_map.cpp diff --git a/src/string16_map.cpp b/src/string16_map.cpp new file mode 100644 index 000000000..c9e2eb817 --- /dev/null +++ b/src/string16_map.cpp @@ -0,0 +1,538 @@ +GB_STATIC_ASSERT(sizeof(MapIndex) == sizeof(u32)); + + +struct String16HashKey { + String16 string; + u32 hash; + + operator String16() const noexcept { + return this->string; + } + operator String16 const &() const noexcept { + return this->string; + } +}; +gb_internal gb_inline u32 string_hash(String16 const &s) { + u32 res = fnv32a(s.text, s.len*gb_size_of(u16)) & 0x7fffffff; + return res | (res == 0); +} + +gb_internal gb_inline String16HashKey string_hash_string(String16 const &s) { + String16HashKey hash_key = {}; + hash_key.hash = string_hash(s); + hash_key.string = s; + return hash_key; +} + + +#if 1 /* old string map */ + +template +struct String16MapEntry { + String16 key; + u32 hash; + MapIndex next; + T value; +}; + +template +struct String16Map { + MapIndex * hashes; + usize hashes_count; + String16MapEntry *entries; + u32 count; + u32 entries_capacity; +}; + + +template gb_internal void string16_map_init (String16Map *h, usize capacity = 16); +template gb_internal void string16_map_destroy (String16Map *h); + +template gb_internal T * string16_map_get (String16Map *h, String16HashKey const &key); +template gb_internal T & string16_map_must_get(String16Map *h, String16HashKey const &key); +template gb_internal void string16_map_set (String16Map *h, String16HashKey const &key, T const &value); + +// template gb_internal void string16_map_remove (String16Map *h, String16HashKey const &key); +template gb_internal void string16_map_clear (String16Map *h); +template gb_internal void string16_map_grow (String16Map *h); +template gb_internal void string16_map_reserve (String16Map *h, usize new_count); + +gb_internal gbAllocator string16_map_allocator(void) { + return heap_allocator(); +} + +template +gb_internal gb_inline void string16_map_init(String16Map *h, usize capacity) { + capacity = next_pow2_isize(capacity); + string16_map_reserve(h, capacity); +} + +template +gb_internal gb_inline void string16_map_destroy(String16Map *h) { + gb_free(string16_map_allocator(), h->hashes); + gb_free(string16_map_allocator(), h->entries); +} + + +template +gb_internal void string16_map__resize_hashes(String16Map *h, usize count) { + h->hashes_count = cast(u32)resize_array_raw(&h->hashes, string16_map_allocator(), h->hashes_count, count, MAP_CACHE_LINE_SIZE); +} + + +template +gb_internal void string16_map__reserve_entries(String16Map *h, usize capacity) { + h->entries_capacity = cast(u32)resize_array_raw(&h->entries, string16_map_allocator(), h->entries_capacity, capacity, MAP_CACHE_LINE_SIZE); +} + + +template +gb_internal MapIndex string16_map__add_entry(String16Map *h, u32 hash, String16 const &key) { + String16MapEntry e = {}; + e.key = key; + e.hash = hash; + e.next = MAP_SENTINEL; + if (h->count+1 >= h->entries_capacity) { + string16_map__reserve_entries(h, gb_max(h->entries_capacity*2, 4)); + } + h->entries[h->count++] = e; + return cast(MapIndex)(h->count-1); +} + +template +gb_internal MapFindResult string16_map__find(String16Map *h, u32 hash, String16 const &key) { + MapFindResult fr = {MAP_SENTINEL, MAP_SENTINEL, MAP_SENTINEL}; + if (h->hashes_count != 0) { + fr.hash_index = cast(MapIndex)(hash & (h->hashes_count-1)); + fr.entry_index = h->hashes[fr.hash_index]; + while (fr.entry_index != MAP_SENTINEL) { + auto *entry = &h->entries[fr.entry_index]; + if (entry->hash == hash && entry->key == key) { + return fr; + } + fr.entry_prev = fr.entry_index; + fr.entry_index = entry->next; + } + } + return fr; +} + +template +gb_internal MapFindResult string16_map__find_from_entry(String16Map *h, String16MapEntry *e) { + MapFindResult fr = {MAP_SENTINEL, MAP_SENTINEL, MAP_SENTINEL}; + if (h->hashes_count != 0) { + fr.hash_index = cast(MapIndex)(e->hash & (h->hashes_count-1)); + fr.entry_index = h->hashes[fr.hash_index]; + while (fr.entry_index != MAP_SENTINEL) { + auto *entry = &h->entries[fr.entry_index]; + if (entry == e) { + return fr; + } + fr.entry_prev = fr.entry_index; + fr.entry_index = entry->next; + } + } + return fr; +} + +template +gb_internal b32 string16_map__full(String16Map *h) { + return 0.75f * h->hashes_count <= h->count; +} + +template +gb_inline void string16_map_grow(String16Map *h) { + isize new_count = gb_max(h->hashes_count<<1, 16); + string16_map_reserve(h, new_count); +} + + +template +gb_internal void string16_map_reset_entries(String16Map *h) { + for (u32 i = 0; i < h->hashes_count; i++) { + h->hashes[i] = MAP_SENTINEL; + } + for (isize i = 0; i < h->count; i++) { + MapFindResult fr; + String16MapEntry *e = &h->entries[i]; + e->next = MAP_SENTINEL; + fr = string16_map__find_from_entry(h, e); + if (fr.entry_prev == MAP_SENTINEL) { + h->hashes[fr.hash_index] = cast(MapIndex)i; + } else { + h->entries[fr.entry_prev].next = cast(MapIndex)i; + } + } +} + +template +gb_internal void string16_map_reserve(String16Map *h, usize cap) { + if (h->count*2 < h->hashes_count) { + return; + } + string16_map__reserve_entries(h, cap); + string16_map__resize_hashes(h, cap*2); + string16_map_reset_entries(h); +} + +template +gb_internal T *string16_map_get(String16Map *h, u32 hash, String16 const &key) { + MapFindResult fr = {MAP_SENTINEL, MAP_SENTINEL, MAP_SENTINEL}; + if (h->hashes_count != 0) { + fr.hash_index = cast(MapIndex)(hash & (h->hashes_count-1)); + fr.entry_index = h->hashes[fr.hash_index]; + while (fr.entry_index != MAP_SENTINEL) { + auto *entry = &h->entries[fr.entry_index]; + if (entry->hash == hash && entry->key == key) { + return &entry->value; + } + fr.entry_prev = fr.entry_index; + fr.entry_index = entry->next; + } + } + return nullptr; +} + + +template +gb_internal gb_inline T *string16_map_get(String16Map *h, String16HashKey const &key) { + return string16_map_get(h, key.hash, key.string); +} +template +gb_internal T &string16_map_must_get(String16Map *h, u32 hash, String16 const &key) { + isize index = string16_map__find(h, hash, key).entry_index; + GB_ASSERT(index != MAP_SENTINEL); + return h->entries[index].value; +} + +template +gb_internal T &string16_map_must_get(String16Map *h, String16HashKey const &key) { + return string16_map_must_get(h, key.hash, key.string); +} + +template +gb_internal void string16_map_set(String16Map *h, u32 hash, String16 const &key, T const &value) { + MapIndex index; + MapFindResult fr; + if (h->hashes_count == 0) { + string16_map_grow(h); + } + fr = string16_map__find(h, hash, key); + if (fr.entry_index != MAP_SENTINEL) { + index = fr.entry_index; + } else { + index = string16_map__add_entry(h, hash, key); + if (fr.entry_prev != MAP_SENTINEL) { + h->entries[fr.entry_prev].next = index; + } else { + h->hashes[fr.hash_index] = index; + } + } + h->entries[index].value = value; + + if (string16_map__full(h)) { + string16_map_grow(h); + } +} + +template +gb_internal gb_inline void string16_map_set(String16Map *h, String16HashKey const &key, T const &value) { + string16_map_set(h, key.hash, key.string, value); +} + + +template +gb_internal gb_inline void string16_map_clear(String16Map *h) { + h->count = 0; + for (u32 i = 0; i < h->hashes_count; i++) { + h->hashes[i] = MAP_SENTINEL; + } +} + + + +template +gb_internal String16MapEntry *begin(String16Map &m) noexcept { + return m.entries; +} +template +gb_internal String16MapEntry const *begin(String16Map const &m) noexcept { + return m.entries; +} + + +template +gb_internal String16MapEntry *end(String16Map &m) noexcept { + return m.entries + m.count; +} + +template +gb_internal String16MapEntry const *end(String16Map const &m) noexcept { + return m.entries + m.count; +} + +#else /* new string map */ + +template +struct StringMapEntry { + String key; + u32 hash; + T value; +}; + +template +struct StringMap { + String16MapEntry *entries; + u32 count; + u32 capacity; +}; + + +template gb_internal void string16_map_init (String16Map *h, usize capacity = 16); +template gb_internal void string16_map_destroy (String16Map *h); + +template gb_internal T * string16_map_get (String16Map *h, String16 const &key); +template gb_internal T * string16_map_get (String16Map *h, String16HashKey const &key); + +template gb_internal T & string16_map_must_get(String16Map *h, String16 const &key); +template gb_internal T & string16_map_must_get(String16Map *h, String16HashKey const &key); + +template gb_internal void string16_map_set (String16Map *h, String16 const &key, T const &value); +template gb_internal void string16_map_set (String16Map *h, String16HashKey const &key, T const &value); + +// template gb_internal void string16_map_remove (String16Map *h, String16HashKey const &key); +template gb_internal void string16_map_clear (String16Map *h); +template gb_internal void string16_map_grow (String16Map *h); +template gb_internal void string16_map_reserve (String16Map *h, usize new_count); + +gb_internal gbAllocator string16_map_allocator(void) { + return heap_allocator(); +} + +template +gb_internal gb_inline void string16_map_init(String16Map *h, usize capacity) { + capacity = next_pow2_isize(capacity); + string16_map_reserve(h, capacity); +} + +template +gb_internal gb_inline void string16_map_destroy(String16Map *h) { + gb_free(string16_map_allocator(), h->entries); +} + + +template +gb_internal void string16_map__insert(String16Map *h, u32 hash, String16 const &key, T const &value) { + if (h->count+1 >= h->capacity) { + string16_map_grow(h); + } + GB_ASSERT(h->count+1 < h->capacity); + + u32 mask = h->capacity-1; + MapIndex index = hash & mask; + MapIndex original_index = index; + do { + auto *entry = h->entries+index; + if (entry->hash == 0) { + entry->key = key; + entry->hash = hash; + entry->value = value; + + h->count += 1; + return; + } + index = (index+1)&mask; + } while (index != original_index); + + GB_PANIC("Full map"); +} + +template +gb_internal b32 string16_map__full(String16Map *h) { + return 0.75f * h->count <= h->capacity; +} + +template +gb_inline void string16_map_grow(String16Map *h) { + isize new_capacity = gb_max(h->capacity<<1, 16); + string16_map_reserve(h, new_capacity); +} + + +template +gb_internal void string16_map_reserve(String16Map *h, usize cap) { + if (cap < h->capacity) { + return; + } + cap = next_pow2_isize(cap); + + String16Map new_h = {}; + new_h.count = 0; + new_h.capacity = cast(u32)cap; + new_h.entries = gb_alloc_array(string16_map_allocator(), String16MapEntry, new_h.capacity); + + if (h->count) { + for (u32 i = 0; i < h->capacity; i++) { + auto *entry = h->entries+i; + if (entry->hash) { + string16_map__insert(&new_h, entry->hash, entry->key, entry->value); + } + } + } + string16_map_destroy(h); + *h = new_h; +} + +template +gb_internal T *string16_map_get(String16Map *h, u32 hash, String16 const &key) { + if (h->count == 0) { + return nullptr; + } + u32 mask = (h->capacity-1); + u32 index = hash & mask; + u32 original_index = index; + do { + auto *entry = h->entries+index; + u32 curr_hash = entry->hash; + if (curr_hash == 0) { + // NOTE(bill): no found, but there isn't any key removal for this hash map + return nullptr; + } else if (curr_hash == hash && entry->key == key) { + return &entry->value; + } + index = (index+1) & mask; + } while (original_index != index); + return nullptr; +} + + +template +gb_internal gb_inline T *string16_map_get(String16Map *h, String16HashKey const &key) { + return string16_map_get(h, key.hash, key.string); +} + +template +gb_internal gb_inline T *string16_map_get(String16Map *h, String16 const &key) { + return string16_map_get(h, string_hash(key), key); +} + +template +gb_internal T &string16_map_must_get(String16Map *h, u32 hash, String16 const &key) { + T *found = string16_map_get(h, hash, key); + GB_ASSERT(found != nullptr); + return *found; +} + +template +gb_internal T &string16_map_must_get(String16Map *h, String16HashKey const &key) { + return string16_map_must_get(h, key.hash, key.string); +} + +template +gb_internal gb_inline T &string16_map_must_get(String16Map *h, String16 const &key) { + return string16_map_must_get(h, string_hash(key), key); +} + +template +gb_internal void string16_map_set(String16Map *h, u32 hash, String16 const &key, T const &value) { + if (h->count == 0) { + string16_map_grow(h); + } + auto *found = string16_map_get(h, hash, key); + if (found) { + *found = value; + return; + } + string16_map__insert(h, hash, key, value); +} + +template +gb_internal gb_inline void string16_map_set(String16Map *h, String16 const &key, T const &value) { + string16_map_set(h, string_hash_string(key), value); +} + +template +gb_internal gb_inline void string16_map_set(String16Map *h, String16HashKey const &key, T const &value) { + string16_map_set(h, key.hash, key.string, value); +} + + +template +gb_internal gb_inline void string16_map_clear(String16Map *h) { + h->count = 0; + gb_zero_array(h->entries, h->capacity); +} + + +template +struct StringMapIterator { + String16Map *map; + MapIndex index; + + StringMapIterator &operator++() noexcept { + for (;;) { + ++index; + if (map->capacity == index) { + return *this; + } + String16MapEntry *entry = map->entries+index; + if (entry->hash != 0) { + return *this; + } + } + } + + bool operator==(StringMapIterator const &other) const noexcept { + return this->map == other->map && this->index == other->index; + } + + operator String16MapEntry *() const { + return map->entries+index; + } +}; + + +template +gb_internal StringMapIterator end(String16Map &m) noexcept { + return StringMapIterator{&m, m.capacity}; +} + +template +gb_internal StringMapIterator const end(String16Map const &m) noexcept { + return StringMapIterator{&m, m.capacity}; +} + + + +template +gb_internal StringMapIterator begin(String16Map &m) noexcept { + if (m.count == 0) { + return end(m); + } + + MapIndex index = 0; + while (index < m.capacity) { + if (m.entries[index].hash) { + break; + } + index++; + } + return StringMapIterator{&m, index}; +} +template +gb_internal StringMapIterator const begin(String16Map const &m) noexcept { + if (m.count == 0) { + return end(m); + } + + MapIndex index = 0; + while (index < m.capacity) { + if (m.entries[index].hash) { + break; + } + index++; + } + return StringMapIterator{&m, index}; +} + +#endif \ No newline at end of file From c631a8eff59f8c4f76b1a39d1ca04b9fdf0cb85c Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 2 Aug 2025 12:47:03 +0100 Subject: [PATCH 008/105] os2 internals -> (c)string16 --- core/os/os2/dir_windows.odin | 14 ++---- core/os/os2/env_windows.odin | 2 +- core/os/os2/file_windows.odin | 70 ++++++++++++++++++++++-------- core/os/os2/path_windows.odin | 8 ++-- core/os/os2/process_windows.odin | 8 ++-- core/os/os2/stat_windows.odin | 14 +++--- core/os/os2/temp_file_windows.odin | 4 +- core/os/os2/user_windows.odin | 3 +- core/sys/windows/kernel32.odin | 2 +- core/sys/windows/types.odin | 2 +- 10 files changed, 77 insertions(+), 50 deletions(-) diff --git a/core/os/os2/dir_windows.odin b/core/os/os2/dir_windows.odin index 4cf1f8396..6c754a677 100644 --- a/core/os/os2/dir_windows.odin +++ b/core/os/os2/dir_windows.odin @@ -16,7 +16,7 @@ find_data_to_file_info :: proc(base_path: string, d: ^win32.WIN32_FIND_DATAW, al } temp_allocator := TEMP_ALLOCATOR_GUARD({ allocator }) - path := concatenate({base_path, `\`, win32_wstring_to_utf8(raw_data(d.cFileName[:]), temp_allocator) or_else ""}, allocator) or_return + path := concatenate({base_path, `\`, win32_wstring_to_utf8(cstring16(raw_data(d.cFileName[:])), temp_allocator) or_else ""}, allocator) or_return handle := win32.HANDLE(_open_internal(path, {.Read}, 0o666) or_else 0) defer win32.CloseHandle(handle) @@ -107,15 +107,7 @@ _read_directory_iterator_init :: proc(it: ^Read_Directory_Iterator, f: ^File) { return } - wpath: []u16 - { - i := 0 - for impl.wname[i] != 0 { - i += 1 - } - wpath = impl.wname[:i] - } - + wpath := string16(impl.wname) temp_allocator := TEMP_ALLOCATOR_GUARD({}) wpath_search := make([]u16, len(wpath)+3, temp_allocator) @@ -124,7 +116,7 @@ _read_directory_iterator_init :: proc(it: ^Read_Directory_Iterator, f: ^File) { wpath_search[len(wpath)+1] = '*' wpath_search[len(wpath)+2] = 0 - it.impl.find_handle = win32.FindFirstFileW(raw_data(wpath_search), &it.impl.find_data) + it.impl.find_handle = win32.FindFirstFileW(cstring16(raw_data(wpath_search)), &it.impl.find_data) if it.impl.find_handle == win32.INVALID_HANDLE_VALUE { read_directory_iterator_set_error(it, impl.name, _get_platform_error()) return diff --git a/core/os/os2/env_windows.odin b/core/os/os2/env_windows.odin index 55b2bb5ee..d389f8860 100644 --- a/core/os/os2/env_windows.odin +++ b/core/os/os2/env_windows.odin @@ -31,7 +31,7 @@ _lookup_env_alloc :: proc(key: string, allocator: runtime.Allocator) -> (value: return "", false } - value = win32_utf16_to_utf8(b[:n], allocator) or_else "" + value = win32_utf16_to_utf8(string16(b[:n]), allocator) or_else "" found = true return } diff --git a/core/os/os2/file_windows.odin b/core/os/os2/file_windows.odin index 1134e765c..d63702709 100644 --- a/core/os/os2/file_windows.odin +++ b/core/os/os2/file_windows.odin @@ -247,7 +247,7 @@ _destroy :: proc(f: ^File_Impl) -> Error { } a := f.allocator - err0 := free(f.wname, a) + err0 := free(rawptr(f.wname), a) err1 := delete(f.name, a) err2 := free(f, a) err3 := delete(f.r_buf, a) @@ -661,7 +661,7 @@ _normalize_link_path :: proc(p: []u16, allocator: runtime.Allocator) -> (str: st } - handle := _open_sym_link(raw_data(p)) or_return + handle := _open_sym_link(cstring16(raw_data(p))) or_return defer win32.CloseHandle(handle) n := win32.GetFinalPathNameByHandleW(handle, nil, 0, win32.VOLUME_NAME_DOS) @@ -672,7 +672,7 @@ _normalize_link_path :: proc(p: []u16, allocator: runtime.Allocator) -> (str: st temp_allocator := TEMP_ALLOCATOR_GUARD({ allocator }) buf := make([]u16, n+1, temp_allocator) - n = win32.GetFinalPathNameByHandleW(handle, raw_data(buf), u32(len(buf)), win32.VOLUME_NAME_DOS) + n = win32.GetFinalPathNameByHandleW(handle, cstring16(raw_data(buf)), u32(len(buf)), win32.VOLUME_NAME_DOS) if n == 0 { return "", _get_platform_error() } @@ -713,7 +713,7 @@ _read_link :: proc(name: string, allocator: runtime.Allocator) -> (s: string, er switch rdb.ReparseTag { case win32.IO_REPARSE_TAG_SYMLINK: rb := (^win32.SYMBOLIC_LINK_REPARSE_BUFFER)(&rdb.rest) - pb := win32.wstring(&rb.PathBuffer) + pb := ([^]u16)(&rb.PathBuffer) pb[rb.SubstituteNameOffset+rb.SubstituteNameLength] = 0 p := pb[rb.SubstituteNameOffset:][:rb.SubstituteNameLength] if rb.Flags & win32.SYMLINK_FLAG_RELATIVE != 0 { @@ -723,7 +723,7 @@ _read_link :: proc(name: string, allocator: runtime.Allocator) -> (s: string, er case win32.IO_REPARSE_TAG_MOUNT_POINT: rb := (^win32.MOUNT_POINT_REPARSE_BUFFER)(&rdb.rest) - pb := win32.wstring(&rb.PathBuffer) + pb := ([^]u16)(&rb.PathBuffer) pb[rb.SubstituteNameOffset+rb.SubstituteNameLength] = 0 p := pb[rb.SubstituteNameOffset:][:rb.SubstituteNameLength] return _normalize_link_path(p, allocator) @@ -874,8 +874,8 @@ _file_stream_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, @(private="package", require_results) -win32_utf8_to_wstring :: proc(s: string, allocator: runtime.Allocator) -> (ws: [^]u16, err: runtime.Allocator_Error) { - ws = raw_data(win32_utf8_to_utf16(s, allocator) or_return) +win32_utf8_to_wstring :: proc(s: string, allocator: runtime.Allocator) -> (ws: cstring16, err: runtime.Allocator_Error) { + ws = cstring16(raw_data(win32_utf8_to_utf16(s, allocator) or_return)) return } @@ -909,24 +909,26 @@ win32_utf8_to_utf16 :: proc(s: string, allocator: runtime.Allocator) -> (ws: []u } @(private="package", require_results) -win32_wstring_to_utf8 :: proc(s: [^]u16, allocator: runtime.Allocator) -> (res: string, err: runtime.Allocator_Error) { - if s == nil || s[0] == 0 { +win32_wstring_to_utf8 :: proc(s: cstring16, allocator: runtime.Allocator) -> (res: string, err: runtime.Allocator_Error) { + if s == nil || s == "" { return "", nil } - n := 0 - for s[n] != 0 { - n += 1 - } - return win32_utf16_to_utf8(s[:n], allocator) + return win32_utf16_to_utf8(string16(s), allocator) +} + +@(private="package") +win32_utf16_to_utf8 :: proc{ + win32_utf16_string16_to_utf8, + win32_utf16_u16_to_utf8 } @(private="package", require_results) -win32_utf16_to_utf8 :: proc(s: []u16, allocator: runtime.Allocator) -> (res: string, err: runtime.Allocator_Error) { +win32_utf16_string16_to_utf8 :: proc(s: string16, allocator: runtime.Allocator) -> (res: string, err: runtime.Allocator_Error) { if len(s) == 0 { return } - n := win32.WideCharToMultiByte(win32.CP_UTF8, win32.WC_ERR_INVALID_CHARS, raw_data(s), i32(len(s)), nil, 0, nil, nil) + n := win32.WideCharToMultiByte(win32.CP_UTF8, win32.WC_ERR_INVALID_CHARS, cstring16(raw_data(s)), i32(len(s)), nil, 0, nil, nil) if n == 0 { return } @@ -938,7 +940,41 @@ win32_utf16_to_utf8 :: proc(s: []u16, allocator: runtime.Allocator) -> (res: str // will not be null terminated. text := make([]byte, n, allocator) or_return - n1 := win32.WideCharToMultiByte(win32.CP_UTF8, win32.WC_ERR_INVALID_CHARS, raw_data(s), i32(len(s)), raw_data(text), n, nil, nil) + n1 := win32.WideCharToMultiByte(win32.CP_UTF8, win32.WC_ERR_INVALID_CHARS, cstring16(raw_data(s)), i32(len(s)), raw_data(text), n, nil, nil) + if n1 == 0 { + delete(text, allocator) + return + } + + for i in 0.. (res: string, err: runtime.Allocator_Error) { + if len(s) == 0 { + return + } + + n := win32.WideCharToMultiByte(win32.CP_UTF8, win32.WC_ERR_INVALID_CHARS, cstring16(raw_data(s)), i32(len(s)), nil, 0, nil, nil) + if n == 0 { + return + } + + // If N < 0 the call to WideCharToMultiByte assume the wide string is null terminated + // and will scan it to find the first null terminated character. The resulting string will + // also be null terminated. + // If N > 0 it assumes the wide string is not null terminated and the resulting string + // will not be null terminated. + text := make([]byte, n, allocator) or_return + + n1 := win32.WideCharToMultiByte(win32.CP_UTF8, win32.WC_ERR_INVALID_CHARS, cstring16(raw_data(s)), i32(len(s)), raw_data(text), n, nil, nil) if n1 == 0 { delete(text, allocator) return diff --git a/core/os/os2/path_windows.odin b/core/os/os2/path_windows.odin index c2e51040f..e0a00b07a 100644 --- a/core/os/os2/path_windows.odin +++ b/core/os/os2/path_windows.odin @@ -91,11 +91,11 @@ _remove_all :: proc(path: string) -> Error { nil, win32.FO_DELETE, dir, - &empty[0], + cstring16(&empty[0]), win32.FOF_NOCONFIRMATION | win32.FOF_NOERRORUI | win32.FOF_SILENT, false, nil, - &empty[0], + cstring16(&empty[0]), } res := win32.SHFileOperationW(&file_op) if res != 0 { @@ -303,13 +303,13 @@ _get_absolute_path :: proc(path: string, allocator: runtime.Allocator) -> (absol } temp_allocator := TEMP_ALLOCATOR_GUARD({ allocator }) rel_utf16 := win32.utf8_to_utf16(rel, temp_allocator) - n := win32.GetFullPathNameW(raw_data(rel_utf16), 0, nil, nil) + n := win32.GetFullPathNameW(cstring16(raw_data(rel_utf16)), 0, nil, nil) if n == 0 { return "", Platform_Error(win32.GetLastError()) } buf := make([]u16, n, temp_allocator) or_return - n = win32.GetFullPathNameW(raw_data(rel_utf16), u32(n), raw_data(buf), nil) + n = win32.GetFullPathNameW(cstring16(raw_data(rel_utf16)), u32(n), cstring16(raw_data(buf)), nil) if n == 0 { return "", Platform_Error(win32.GetLastError()) } diff --git a/core/os/os2/process_windows.odin b/core/os/os2/process_windows.odin index 199e5ad74..990da6616 100644 --- a/core/os/os2/process_windows.odin +++ b/core/os/os2/process_windows.odin @@ -175,7 +175,7 @@ _process_info_by_pid :: proc(pid: int, selection: Process_Info_Fields, allocator info.fields += {.Command_Line} } if .Command_Args in selection { - info.command_args = _parse_command_line(raw_data(cmdline_w), allocator) or_return + info.command_args = _parse_command_line(cstring16(raw_data(cmdline_w)), allocator) or_return info.fields += {.Command_Args} } } @@ -286,7 +286,7 @@ _process_info_by_handle :: proc(process: Process, selection: Process_Info_Fields info.fields += {.Command_Line} } if .Command_Args in selection { - info.command_args = _parse_command_line(raw_data(cmdline_w), allocator) or_return + info.command_args = _parse_command_line(cstring16(raw_data(cmdline_w)), allocator) or_return info.fields += {.Command_Args} } } @@ -610,7 +610,7 @@ _process_exe_by_pid :: proc(pid: int, allocator: runtime.Allocator) -> (exe_path err =_get_platform_error() return } - return win32_wstring_to_utf8(raw_data(entry.szExePath[:]), allocator) + return win32_wstring_to_utf8(cstring16(raw_data(entry.szExePath[:])), allocator) } _get_process_user :: proc(process_handle: win32.HANDLE, allocator: runtime.Allocator) -> (full_username: string, err: Error) { @@ -650,7 +650,7 @@ _get_process_user :: proc(process_handle: win32.HANDLE, allocator: runtime.Alloc return strings.concatenate({domain, "\\", username}, allocator) } -_parse_command_line :: proc(cmd_line_w: [^]u16, allocator: runtime.Allocator) -> (argv: []string, err: Error) { +_parse_command_line :: proc(cmd_line_w: cstring16, allocator: runtime.Allocator) -> (argv: []string, err: Error) { argc: i32 argv_w := win32.CommandLineToArgvW(cmd_line_w, &argc) if argv_w == nil { diff --git a/core/os/os2/stat_windows.odin b/core/os/os2/stat_windows.odin index 3cdc80405..3dee42be6 100644 --- a/core/os/os2/stat_windows.odin +++ b/core/os/os2/stat_windows.odin @@ -49,12 +49,12 @@ full_path_from_name :: proc(name: string, allocator: runtime.Allocator) -> (path p := win32_utf8_to_utf16(name, temp_allocator) or_return - n := win32.GetFullPathNameW(raw_data(p), 0, nil, nil) + n := win32.GetFullPathNameW(cstring16(raw_data(p)), 0, nil, nil) if n == 0 { return "", _get_platform_error() } buf := make([]u16, n+1, temp_allocator) - n = win32.GetFullPathNameW(raw_data(p), u32(len(buf)), raw_data(buf), nil) + n = win32.GetFullPathNameW(cstring16(raw_data(p)), u32(len(buf)), cstring16(raw_data(buf)), nil) if n == 0 { return "", _get_platform_error() } @@ -140,8 +140,8 @@ _cleanpath_from_handle :: proc(f: ^File, allocator: runtime.Allocator) -> (strin temp_allocator := TEMP_ALLOCATOR_GUARD({ allocator }) buf := make([]u16, max(n, 260)+1, temp_allocator) - n = win32.GetFinalPathNameByHandleW(h, raw_data(buf), u32(len(buf)), 0) - return _cleanpath_from_buf(buf[:n], allocator) + n = win32.GetFinalPathNameByHandleW(h, cstring16(raw_data(buf)), u32(len(buf)), 0) + return _cleanpath_from_buf(string16(buf[:n]), allocator) } _cleanpath_from_handle_u16 :: proc(f: ^File) -> ([]u16, Error) { @@ -158,12 +158,12 @@ _cleanpath_from_handle_u16 :: proc(f: ^File) -> ([]u16, Error) { temp_allocator := TEMP_ALLOCATOR_GUARD({}) buf := make([]u16, max(n, 260)+1, temp_allocator) - n = win32.GetFinalPathNameByHandleW(h, raw_data(buf), u32(len(buf)), 0) + n = win32.GetFinalPathNameByHandleW(h, cstring16(raw_data(buf)), u32(len(buf)), 0) return _cleanpath_strip_prefix(buf[:n]), nil } -_cleanpath_from_buf :: proc(buf: []u16, allocator: runtime.Allocator) -> (string, runtime.Allocator_Error) { - buf := buf +_cleanpath_from_buf :: proc(buf: string16, allocator: runtime.Allocator) -> (string, runtime.Allocator_Error) { + buf := transmute([]u16)buf buf = _cleanpath_strip_prefix(buf) return win32_utf16_to_utf8(buf, allocator) } diff --git a/core/os/os2/temp_file_windows.odin b/core/os/os2/temp_file_windows.odin index 9d75ef99d..91ea284a1 100644 --- a/core/os/os2/temp_file_windows.odin +++ b/core/os/os2/temp_file_windows.odin @@ -12,12 +12,12 @@ _temp_dir :: proc(allocator: runtime.Allocator) -> (string, runtime.Allocator_Er temp_allocator := TEMP_ALLOCATOR_GUARD({ allocator }) b := make([]u16, max(win32.MAX_PATH, n), temp_allocator) - n = win32.GetTempPathW(u32(len(b)), raw_data(b)) + n = win32.GetTempPathW(u32(len(b)), cstring16(raw_data(b))) if n == 3 && b[1] == ':' && b[2] == '\\' { } else if n > 0 && b[n-1] == '\\' { n -= 1 } - return win32_utf16_to_utf8(b[:n], allocator) + return win32_utf16_to_utf8(string16(b[:n]), allocator) } diff --git a/core/os/os2/user_windows.odin b/core/os/os2/user_windows.odin index d68f933ce..75d0ba6ac 100644 --- a/core/os/os2/user_windows.odin +++ b/core/os/os2/user_windows.odin @@ -74,6 +74,5 @@ _get_known_folder_path :: proc(rfid: win32.REFKNOWNFOLDERID, allocator: runtime. return "", .Invalid_Path } - dir, _ = win32.wstring_to_utf8(path_w, -1, allocator) - return + return win32_wstring_to_utf8(cstring16(path_w), allocator) } \ No newline at end of file diff --git a/core/sys/windows/kernel32.odin b/core/sys/windows/kernel32.odin index 76f2897ac..114e70b41 100644 --- a/core/sys/windows/kernel32.odin +++ b/core/sys/windows/kernel32.odin @@ -258,7 +258,7 @@ foreign kernel32 { ) -> BOOL --- CreateProcessW :: proc( lpApplicationName: LPCWSTR, - lpCommandLine: LPWSTR, + lpCommandLine: LPCWSTR, lpProcessAttributes: LPSECURITY_ATTRIBUTES, lpThreadAttributes: LPSECURITY_ATTRIBUTES, bInheritHandles: BOOL, diff --git a/core/sys/windows/types.odin b/core/sys/windows/types.odin index be16d2fdd..200b0d62b 100644 --- a/core/sys/windows/types.odin +++ b/core/sys/windows/types.odin @@ -1698,7 +1698,7 @@ NM_FONTCHANGED :: NM_OUTOFMEMORY-22 NM_CUSTOMTEXT :: NM_OUTOFMEMORY-23 // uses NMCUSTOMTEXT struct NM_TVSTATEIMAGECHANGING :: NM_OUTOFMEMORY-23 // uses NMTVSTATEIMAGECHANGING struct, defined after HTREEITEM -PCZZWSTR :: ^WCHAR +PCZZWSTR :: cstring16 SHFILEOPSTRUCTW :: struct { hwnd: HWND, From 7c281a9614d815fda4c3ac5fd53ce940662c3264 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 2 Aug 2025 12:51:08 +0100 Subject: [PATCH 009/105] Fix [^]u16 <-> cstring16 conversions --- src/llvm_backend_expr.cpp | 61 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index 8ad6a5a1c..f58e2d9ac 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -2330,6 +2330,21 @@ gb_internal lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) { return res; } + // [^]u16 <-> cstring16 + if (is_type_u16_multi_ptr(src) && is_type_cstring16(dst)) { + return lb_emit_transmute(p, value, t); + } + if (is_type_cstring16(src) && is_type_u16_multi_ptr(dst)) { + return lb_emit_transmute(p, value, t); + } + if (is_type_u16_ptr(src) && is_type_cstring16(dst)) { + return lb_emit_transmute(p, value, t); + } + if (is_type_cstring16(src) && is_type_u16_ptr(dst)) { + return lb_emit_transmute(p, value, t); + } + + // []u16 <-> string16 if (is_type_u16_slice(src) && is_type_string16(dst)) { return lb_emit_transmute(p, value, t); @@ -2753,7 +2768,53 @@ gb_internal lbValue lb_emit_comp(lbProcedure *p, TokenKind op_kind, lbValue left return lb_compare_records(p, op_kind, left, right, b); } + + if (is_type_string16(a) || is_type_cstring16(a)) { + if (is_type_cstring16(a) && is_type_cstring16(b)) { + left = lb_emit_conv(p, left, t_cstring16); + right = lb_emit_conv(p, right, t_cstring16); + char const *runtime_procedure = nullptr; + switch (op_kind) { + case Token_CmpEq: runtime_procedure = "cstring16_eq"; break; + case Token_NotEq: runtime_procedure = "cstring16_ne"; break; + case Token_Lt: runtime_procedure = "cstring16_lt"; break; + case Token_Gt: runtime_procedure = "cstring16_gt"; break; + case Token_LtEq: runtime_procedure = "cstring16_le"; break; + case Token_GtEq: runtime_procedure = "cstring16_ge"; break; + } + GB_ASSERT(runtime_procedure != nullptr); + + auto args = array_make(permanent_allocator(), 2); + args[0] = left; + args[1] = right; + return lb_emit_runtime_call(p, runtime_procedure, args); + } + + + if (is_type_cstring16(a) ^ is_type_cstring16(b)) { + left = lb_emit_conv(p, left, t_string); + right = lb_emit_conv(p, right, t_string); + } + + char const *runtime_procedure = nullptr; + switch (op_kind) { + case Token_CmpEq: runtime_procedure = "string16_eq"; break; + case Token_NotEq: runtime_procedure = "string16_ne"; break; + case Token_Lt: runtime_procedure = "string16_lt"; break; + case Token_Gt: runtime_procedure = "string16_gt"; break; + case Token_LtEq: runtime_procedure = "string16_le"; break; + case Token_GtEq: runtime_procedure = "string16_ge"; break; + } + GB_ASSERT(runtime_procedure != nullptr); + + auto args = array_make(permanent_allocator(), 2); + args[0] = left; + args[1] = right; + return lb_emit_runtime_call(p, runtime_procedure, args); + } + if (is_type_string(a)) { + if (is_type_cstring(a) && is_type_cstring(b)) { left = lb_emit_conv(p, left, t_cstring); right = lb_emit_conv(p, right, t_cstring); From 5aec40e3e059e4ddbf8a004d61ba8d4883e6d281 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 2 Aug 2025 12:55:05 +0100 Subject: [PATCH 010/105] Remove unneeded uses of `intrinsics.constant_utf16_cstring` --- core/os/os2/file_windows.odin | 2 +- tests/core/sys/windows/test_kernel32.odin | 2 +- tests/core/sys/windows/util.odin | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/os/os2/file_windows.odin b/core/os/os2/file_windows.odin index d63702709..304cf99ac 100644 --- a/core/os/os2/file_windows.odin +++ b/core/os/os2/file_windows.odin @@ -919,7 +919,7 @@ win32_wstring_to_utf8 :: proc(s: cstring16, allocator: runtime.Allocator) -> (re @(private="package") win32_utf16_to_utf8 :: proc{ win32_utf16_string16_to_utf8, - win32_utf16_u16_to_utf8 + win32_utf16_u16_to_utf8, } @(private="package", require_results) diff --git a/tests/core/sys/windows/test_kernel32.odin b/tests/core/sys/windows/test_kernel32.odin index f6a88c769..7df16113a 100644 --- a/tests/core/sys/windows/test_kernel32.odin +++ b/tests/core/sys/windows/test_kernel32.odin @@ -17,7 +17,7 @@ lcid_to_local :: proc(t: ^testing.T) { exp :: "en-US" testing.expectf(t, str == exp, "%v (should be: %v)", str, exp) - cc2 := win32.LocaleNameToLCID(L(exp), 0) + cc2 := win32.LocaleNameToLCID(exp, 0) testing.expectf(t, cc2 == 0x0409, "%#x (should be: %#x)", u32(cc2), 0x0409) //fmt.printfln("%0X", lcid) diff --git a/tests/core/sys/windows/util.odin b/tests/core/sys/windows/util.odin index 0201395f6..6e4bef9b7 100644 --- a/tests/core/sys/windows/util.odin +++ b/tests/core/sys/windows/util.odin @@ -12,11 +12,11 @@ UTF16_Vector :: struct { utf16_vectors := []UTF16_Vector{ { - intrinsics.constant_utf16_cstring("Hellope, World!"), + "Hellope, World!", "Hellope, World!", }, { - intrinsics.constant_utf16_cstring("Hellope\x00, World!"), + "Hellope\x00, World!", "Hellope", }, } From e049dde582ac6525b9ce470a4af89075408c8de9 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 2 Aug 2025 13:01:58 +0100 Subject: [PATCH 011/105] Fix tests for UTF-16 strings --- core/sys/windows/types.odin | 2 +- tests/core/sys/windows/test_kernel32.odin | 2 +- tests/core/sys/windows/test_ole32.odin | 4 ++-- tests/core/sys/windows/util.odin | 3 ++- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/core/sys/windows/types.odin b/core/sys/windows/types.odin index 200b0d62b..d5c9b1d20 100644 --- a/core/sys/windows/types.odin +++ b/core/sys/windows/types.odin @@ -145,7 +145,7 @@ LPSTR :: ^CHAR LPWSTR :: ^WCHAR OLECHAR :: WCHAR BSTR :: ^OLECHAR -LPOLESTR :: ^OLECHAR +LPOLESTR :: cstring16 LPCOLESTR :: LPCSTR LPFILETIME :: ^FILETIME LPWSABUF :: ^WSABUF diff --git a/tests/core/sys/windows/test_kernel32.odin b/tests/core/sys/windows/test_kernel32.odin index 7df16113a..15f3b5173 100644 --- a/tests/core/sys/windows/test_kernel32.odin +++ b/tests/core/sys/windows/test_kernel32.odin @@ -12,7 +12,7 @@ lcid_to_local :: proc(t: ^testing.T) { cc := win32.LCIDToLocaleName(lcid, &wname[0], len(wname) - 1, 0) testing.expectf(t, cc == 6, "%#x (should be: %#x)", u32(cc), 6) if cc == 0 {return} - str, err := win32.wstring_to_utf8(win32.wstring(&wname), int(cc)) + str, err := win32.wstring_to_utf8(win32.wstring(&wname[0]), int(cc)) testing.expectf(t, err == .None, "%v (should be: %x)", err, 0) exp :: "en-US" testing.expectf(t, str == exp, "%v (should be: %v)", str, exp) diff --git a/tests/core/sys/windows/test_ole32.odin b/tests/core/sys/windows/test_ole32.odin index 8be231e1f..a0a2590b8 100644 --- a/tests/core/sys/windows/test_ole32.odin +++ b/tests/core/sys/windows/test_ole32.odin @@ -9,7 +9,7 @@ import "core:testing" string_from_clsid :: proc(t: ^testing.T) { p: win32.LPOLESTR hr := win32.StringFromCLSID(win32.CLSID_FileOpenDialog, &p) - defer if p != nil {win32.CoTaskMemFree(p)} + defer if p != nil {win32.CoTaskMemFree(rawptr(p))} testing.expectf(t, win32.SUCCEEDED(hr), "%x (should be: %x)", u32(hr), 0) testing.expectf(t, p != nil, "%v is nil", p) @@ -33,7 +33,7 @@ clsid_from_string :: proc(t: ^testing.T) { string_from_iid :: proc(t: ^testing.T) { p: win32.LPOLESTR hr := win32.StringFromIID(win32.IID_IFileDialog, &p) - defer if p != nil {win32.CoTaskMemFree(p)} + defer if p != nil {win32.CoTaskMemFree(rawptr(p))} testing.expectf(t, win32.SUCCEEDED(hr), "%x (should be: %x)", u32(hr), 0) testing.expectf(t, p != nil, "%v is nil", p) diff --git a/tests/core/sys/windows/util.odin b/tests/core/sys/windows/util.odin index 6e4bef9b7..e2ab9cde0 100644 --- a/tests/core/sys/windows/util.odin +++ b/tests/core/sys/windows/util.odin @@ -27,7 +27,8 @@ utf16_to_utf8_buf_test :: proc(t: ^testing.T) { buf := make([]u8, len(test.ustr)) defer delete(buf) - res := win32.utf16_to_utf8_buf(buf[:], test.wstr[:len(test.ustr)]) + wstr := string16(test.wstr) + res := win32.utf16_to_utf8_buf(buf[:], transmute([]u16)wstr) testing.expect_value(t, res, test.ustr) } } \ No newline at end of file From dca9bf0b0c8a3ad2ac6854c901d99868d3a296d5 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 2 Aug 2025 13:11:34 +0100 Subject: [PATCH 012/105] Fix string16 literal length set in LLVM --- src/llvm_backend_const.cpp | 13 ++++++++++--- src/llvm_backend_general.cpp | 4 ++-- src/string.cpp | 2 -- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/llvm_backend_const.cpp b/src/llvm_backend_const.cpp index cba0000cd..e64be49f2 100644 --- a/src/llvm_backend_const.cpp +++ b/src/llvm_backend_const.cpp @@ -782,9 +782,12 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb lbValue res = {}; res.type = default_type(original_type); + isize len = value.value_string.len; + if (is_type_string16(res.type) || is_type_cstring16(res.type)) { TEMPORARY_ALLOCATOR_GUARD(); String16 s16 = string_to_string16(temporary_allocator(), value.value_string); + len = s16.len; ptr = lb_find_or_add_entity_string16_ptr(m, s16, custom_link_section); } else { ptr = lb_find_or_add_entity_string_ptr(m, value.value_string, custom_link_section); @@ -797,10 +800,14 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb if (is_type_cstring(res.type) || is_type_cstring16(res.type)) { res.value = ptr; } else { - if (value.value_string.len == 0) { - ptr = LLVMConstNull(lb_type(m, t_u8_ptr)); + if (len == 0) { + if (is_type_string16(res.type)) { + ptr = LLVMConstNull(lb_type(m, t_u16_ptr)); + } else { + ptr = LLVMConstNull(lb_type(m, t_u8_ptr)); + } } - LLVMValueRef str_len = LLVMConstInt(lb_type(m, t_int), value.value_string.len, true); + LLVMValueRef str_len = LLVMConstInt(lb_type(m, t_int), len, true); GB_ASSERT(is_type_string(original_type)); if (is_type_string16(res.type)) { diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp index 064d0ef39..d84b8302b 100644 --- a/src/llvm_backend_general.cpp +++ b/src/llvm_backend_general.cpp @@ -2758,7 +2758,7 @@ gb_internal LLVMValueRef lb_find_or_add_entity_string16_ptr(lbModule *m, String1 LLVMValueRef global_data = LLVMAddGlobal(m->mod, type, name); LLVMSetInitializer(global_data, data); lb_make_global_private_const(global_data); - LLVMSetAlignment(global_data, 1); + LLVMSetAlignment(global_data, 2); LLVMValueRef ptr = LLVMConstInBoundsGEP2(type, global_data, indices, 2); if (!custom_link_section) { @@ -2855,7 +2855,7 @@ gb_internal lbValue lb_find_or_add_entity_string16_slice_with_type(lbModule *m, LLVMValueRef global_data = LLVMAddGlobal(m->mod, type, name); LLVMSetInitializer(global_data, data); lb_make_global_private_const(global_data); - LLVMSetAlignment(global_data, 1); + LLVMSetAlignment(global_data, 2); i64 data_len = str.len; LLVMValueRef ptr = nullptr; diff --git a/src/string.cpp b/src/string.cpp index 8cc0e93f3..2087a5fee 100644 --- a/src/string.cpp +++ b/src/string.cpp @@ -658,7 +658,6 @@ gb_internal String normalize_path(gbAllocator a, String const &path, String cons -// TODO(bill): Make this non-windows specific gb_internal String16 string_to_string16(gbAllocator a, String s) { int len, len1; u16 *text; @@ -680,7 +679,6 @@ gb_internal String16 string_to_string16(gbAllocator a, String s) { return make_string16(nullptr, 0); } text[len] = 0; - return make_string16(text, len); } From 86bd9186f9913f4b98f73d9f344d5277acf67fc0 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 2 Aug 2025 13:17:31 +0100 Subject: [PATCH 013/105] Fix `string16 != ""` comparison --- src/llvm_backend_expr.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index f58e2d9ac..f9007d960 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -1559,16 +1559,24 @@ gb_internal lbValue lb_build_binary_expr(lbProcedure *p, Ast *expr) { return lb_emit_conv(p, cmp, type); } else if (lb_is_empty_string_constant(be->right) && !is_type_union(be->left->tav.type)) { // `x == ""` or `x != ""` + Type *str_type = t_string; + if (is_type_string16(be->left->tav.type)) { + str_type = t_string16; + } lbValue s = lb_build_expr(p, be->left); - s = lb_emit_conv(p, s, t_string); + s = lb_emit_conv(p, s, str_type); lbValue len = lb_string_len(p, s); lbValue cmp = lb_emit_comp(p, be->op.kind, len, lb_const_int(p->module, t_int, 0)); Type *type = default_type(tv.type); return lb_emit_conv(p, cmp, type); } else if (lb_is_empty_string_constant(be->left) && !is_type_union(be->right->tav.type)) { // `"" == x` or `"" != x` + Type *str_type = t_string; + if (is_type_string16(be->right->tav.type)) { + str_type = t_string16; + } lbValue s = lb_build_expr(p, be->right); - s = lb_emit_conv(p, s, t_string); + s = lb_emit_conv(p, s, str_type); lbValue len = lb_string_len(p, s); lbValue cmp = lb_emit_comp(p, be->op.kind, len, lb_const_int(p->module, t_int, 0)); Type *type = default_type(tv.type); @@ -2792,8 +2800,8 @@ gb_internal lbValue lb_emit_comp(lbProcedure *p, TokenKind op_kind, lbValue left if (is_type_cstring16(a) ^ is_type_cstring16(b)) { - left = lb_emit_conv(p, left, t_string); - right = lb_emit_conv(p, right, t_string); + left = lb_emit_conv(p, left, t_string16); + right = lb_emit_conv(p, right, t_string16); } char const *runtime_procedure = nullptr; From f8d24923fdd701c0a08b8ffb7200cebdc9820b76 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 2 Aug 2025 13:23:20 +0100 Subject: [PATCH 014/105] Fix `cstring != ""` --- src/llvm_backend_expr.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index f9007d960..5425572c7 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -1560,7 +1560,7 @@ gb_internal lbValue lb_build_binary_expr(lbProcedure *p, Ast *expr) { } else if (lb_is_empty_string_constant(be->right) && !is_type_union(be->left->tav.type)) { // `x == ""` or `x != ""` Type *str_type = t_string; - if (is_type_string16(be->left->tav.type)) { + if (is_type_string16(be->left->tav.type) || is_type_cstring16(be->left->tav.type)) { str_type = t_string16; } lbValue s = lb_build_expr(p, be->left); @@ -1572,7 +1572,7 @@ gb_internal lbValue lb_build_binary_expr(lbProcedure *p, Ast *expr) { } else if (lb_is_empty_string_constant(be->left) && !is_type_union(be->right->tav.type)) { // `"" == x` or `"" != x` Type *str_type = t_string; - if (is_type_string16(be->right->tav.type)) { + if (is_type_string16(be->right->tav.type) || is_type_cstring16(be->right->tav.type)) { str_type = t_string16; } lbValue s = lb_build_expr(p, be->right); From a9e9e88f0629afd7d34022c45197ac6941820f81 Mon Sep 17 00:00:00 2001 From: Wesley Kerfoot Date: Sun, 3 Aug 2025 11:30:09 -0400 Subject: [PATCH 015/105] add missing xlib functions for getting and setting text properties --- vendor/x11/xlib/xlib_procs.odin | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/vendor/x11/xlib/xlib_procs.odin b/vendor/x11/xlib/xlib_procs.odin index 2cd4e0f83..f5ac373ae 100644 --- a/vendor/x11/xlib/xlib_procs.odin +++ b/vendor/x11/xlib/xlib_procs.odin @@ -389,6 +389,18 @@ foreign xlib { requestor: Window, time: Time, ) --- + GetTextProperty :: proc( + display: ^Display, + window: Window, + text_prop_return: ^XTextProperty, + property: Atom, + ) -> Status --- + SetTextProperty :: proc( + display: ^Display, + window: Window, + text_prop: ^XTextProperty, + property: Atom, + ) --- // Creating and freeing pixmaps CreatePixmap :: proc( display: ^Display, From 70818030f65be53b3b5bd966a088f726b2db9789 Mon Sep 17 00:00:00 2001 From: A1029384756 Date: Mon, 4 Aug 2025 00:27:03 -0400 Subject: [PATCH 016/105] [nightly] added linux arm build [nightly] docker container for linux arm [nightly] removed setup-alpine for arm [nightly] docker container for all linux + linux arm dep for upload [nightly] x86 remove arm reference [nightly] final fixes --- .github/workflows/nightly.yml | 69 ++++++++++++++++++++++++++++------- 1 file changed, 55 insertions(+), 14 deletions(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index eb67eb209..6826239e8 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -47,20 +47,15 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: jirutka/setup-alpine@v1 - with: - branch: edge - - name: (Linux) Download LLVM + - name: (Linux) Download LLVM and Build Odin run: | - apk add --no-cache \ - musl-dev llvm20-dev clang20 git mold lz4 \ - libxml2-static llvm20-static zlib-static zstd-static \ - make - shell: alpine.sh --root {0} - - name: build odin - # NOTE: this build does slow compile times because of musl - run: ci/build_linux_static.sh - shell: alpine.sh {0} + docker run --rm -v "$PWD:/src" -w /src alpine sh -c ' + apk add --no-cache \ + musl-dev llvm20-dev clang20 git mold lz4 \ + libxml2-static llvm20-static zlib-static zstd-static \ + make && + ./ci/build_linux_static.sh + ' - name: Odin run run: ./odin run examples/demo - name: Copy artifacts @@ -85,6 +80,45 @@ jobs: with: name: linux_artifacts path: dist.tar.gz + build_linux_arm: + name: Linux ARM Build + if: github.repository == 'odin-lang/Odin' + runs-on: ubuntu-24.04-arm + steps: + - uses: actions/checkout@v4 + - name: (Linux ARM) Download LLVM and Build Odin + run: | + docker run --rm -v "$PWD:/src" -w /src arm64v8/alpine sh -c ' + apk add --no-cache \ + musl-dev llvm20-dev clang20 git mold lz4 \ + libxml2-static llvm20-static zlib-static zstd-static \ + make && + ./ci/build_linux_static.sh + ' + - name: Odin run + run: ./odin run examples/demo + - name: Copy artifacts + run: | + FILE="odin-linux-arm64-nightly+$(date -I)" + mkdir $FILE + cp odin $FILE + cp LICENSE $FILE + cp -r shared $FILE + cp -r base $FILE + cp -r core $FILE + cp -r vendor $FILE + cp -r examples $FILE + # Creating a tarball so executable permissions are retained, see https://github.com/actions/upload-artifact/issues/38 + tar -czvf dist.tar.gz $FILE + - name: Odin run + run: | + FILE="odin-linux-arm64-nightly+$(date -I)" + $FILE/odin run examples/demo + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: linux_arm_artifacts + path: dist.tar.gz build_macos: name: MacOS Build if: github.repository == 'odin-lang/Odin' @@ -163,7 +197,7 @@ jobs: path: dist.tar.gz upload_b2: runs-on: [ubuntu-latest] - needs: [build_windows, build_macos, build_macos_arm, build_linux] + needs: [build_windows, build_macos, build_macos_arm, build_linux, build_linux_arm] steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 @@ -192,6 +226,12 @@ jobs: name: linux_artifacts path: linux_artifacts + - name: Download Ubuntu ARM artifacts + uses: actions/download-artifact@v4.1.7 + with: + name: linux_arm_artifacts + path: linux_arm_artifacts + - name: Download macOS artifacts uses: actions/download-artifact@v4.1.7 with: @@ -219,6 +259,7 @@ jobs: file linux_artifacts/dist.tar.gz python3 ci/nightly.py artifact windows-amd64 windows_artifacts/ python3 ci/nightly.py artifact linux-amd64 linux_artifacts/dist.tar.gz + python3 ci/nightly.py artifact linux-arm64 linux_arm_artifacts/dist.tar.gz python3 ci/nightly.py artifact macos-amd64 macos_artifacts/dist.tar.gz python3 ci/nightly.py artifact macos-arm64 macos_arm_artifacts/dist.tar.gz python3 ci/nightly.py prune From af3184adc96cef59fff986ea6400caa6dbdb56ae Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 5 Aug 2025 15:12:54 +0100 Subject: [PATCH 017/105] Change `is_utf16` field to `encoding` and use an enum --- base/runtime/core.odin | 7 ++++++- base/runtime/print.odin | 5 +++-- core/encoding/cbor/tags.odin | 2 +- core/encoding/cbor/unmarshal.odin | 2 +- core/encoding/json/unmarshal.odin | 2 +- core/flags/internal_rtti.odin | 2 +- core/reflect/types.odin | 5 +++-- src/checker.cpp | 3 +++ src/llvm_backend_type.cpp | 16 ++++++++++++---- src/types.cpp | 2 ++ 10 files changed, 33 insertions(+), 13 deletions(-) diff --git a/base/runtime/core.odin b/base/runtime/core.odin index fe40427ff..478a3d307 100644 --- a/base/runtime/core.odin +++ b/base/runtime/core.odin @@ -61,6 +61,11 @@ Type_Info_Struct_Soa_Kind :: enum u8 { Dynamic = 3, } +Type_Info_String_Encoding_Kind :: enum u8 { + UTF_8 = 0, + UTF_16 = 1, +} + // Variant Types Type_Info_Named :: struct { name: string, @@ -73,7 +78,7 @@ Type_Info_Rune :: struct {} Type_Info_Float :: struct {endianness: Platform_Endianness} Type_Info_Complex :: struct {} Type_Info_Quaternion :: struct {} -Type_Info_String :: struct {is_cstring: bool, is_utf16: bool} +Type_Info_String :: struct {is_cstring: bool, encoding: Type_Info_String_Encoding_Kind} Type_Info_Boolean :: struct {} Type_Info_Any :: struct {} Type_Info_Type_Id :: struct {} diff --git a/base/runtime/print.odin b/base/runtime/print.odin index 85ed49445..2cfb6661b 100644 --- a/base/runtime/print.odin +++ b/base/runtime/print.odin @@ -297,8 +297,9 @@ print_type :: #force_no_inline proc "contextless" (ti: ^Type_Info) { print_byte('c') } print_string("string") - if info.is_utf16 { - print_string("16") + switch info.encoding { + case .UTF_8: /**/ + case .UTF_16: print_string("16") } case Type_Info_Boolean: switch ti.id { diff --git a/core/encoding/cbor/tags.odin b/core/encoding/cbor/tags.odin index e0e69cbf5..ae1664dfc 100644 --- a/core/encoding/cbor/tags.odin +++ b/core/encoding/cbor/tags.odin @@ -298,7 +298,7 @@ tag_base64_unmarshal :: proc(_: ^Tag_Implementation, d: Decoder, _: Tag_Number, #partial switch t in ti.variant { case reflect.Type_Info_String: - assert(!t.is_utf16) + assert(t.encoding == .UTF_8) if t.is_cstring { length := base64.decoded_len(bytes) builder := strings.builder_make(0, length+1) diff --git a/core/encoding/cbor/unmarshal.odin b/core/encoding/cbor/unmarshal.odin index 2840429f5..043b2ec60 100644 --- a/core/encoding/cbor/unmarshal.odin +++ b/core/encoding/cbor/unmarshal.odin @@ -335,7 +335,7 @@ _unmarshal_value :: proc(d: Decoder, v: any, hdr: Header, allocator := context.a _unmarshal_bytes :: proc(d: Decoder, v: any, ti: ^reflect.Type_Info, hdr: Header, add: Add, allocator := context.allocator, loc := #caller_location) -> (err: Unmarshal_Error) { #partial switch t in ti.variant { case reflect.Type_Info_String: - assert(!t.is_utf16) + assert(t.encoding == .UTF_8) bytes := err_conv(_decode_bytes(d, add, allocator=allocator, loc=loc)) or_return diff --git a/core/encoding/json/unmarshal.odin b/core/encoding/json/unmarshal.odin index 51e7e3b81..0b65adaac 100644 --- a/core/encoding/json/unmarshal.odin +++ b/core/encoding/json/unmarshal.odin @@ -571,7 +571,7 @@ unmarshal_object :: proc(p: ^Parser, v: any, end_token: Token_Kind) -> (err: Unm #partial switch tk in t.key.variant { case runtime.Type_Info_String: - assert(!tk.is_utf16) + assert(tk.encoding == .UTF_8) key_ptr = rawptr(&key) key_cstr: cstring diff --git a/core/flags/internal_rtti.odin b/core/flags/internal_rtti.odin index 58224cc87..a1b050597 100644 --- a/core/flags/internal_rtti.odin +++ b/core/flags/internal_rtti.odin @@ -127,7 +127,7 @@ parse_and_set_pointer_by_base_type :: proc(ptr: rawptr, str: string, type_info: } case runtime.Type_Info_String: - assert(!specific_type_info.is_utf16) + assert(specific_type_info.encoding == .UTF_8) if specific_type_info.is_cstring { cstr_ptr := (^cstring)(ptr) diff --git a/core/reflect/types.odin b/core/reflect/types.odin index 2351408cc..98b7b368f 100644 --- a/core/reflect/types.odin +++ b/core/reflect/types.odin @@ -514,8 +514,9 @@ write_type_writer :: #force_no_inline proc(w: io.Writer, ti: ^Type_Info, n_writt io.write_byte(w, 'c', &n) or_return } io.write_string(w, "string", &n) or_return - if info.is_utf16 { - io.write_string(w, "16", &n) or_return + switch info.encoding { + case .UTF_8: /**/ + case .UTF_16: io.write_string(w, "16", &n) or_return } case Type_Info_Boolean: switch ti.id { diff --git a/src/checker.cpp b/src/checker.cpp index e9fa792f3..e72061f56 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -3101,6 +3101,9 @@ gb_internal void init_core_type_info(Checker *c) { GB_ASSERT(tis->fields.count == 5); + Entity *type_info_string_encoding_kind = find_core_entity(c, str_lit("Type_Info_String_Encoding_Kind")); + t_type_info_string_encoding_kind = type_info_string_encoding_kind->type; + Entity *type_info_variant = tis->fields[4]; Type *tiv_type = type_info_variant->type; GB_ASSERT(is_type_union(tiv_type)); diff --git a/src/llvm_backend_type.cpp b/src/llvm_backend_type.cpp index a91d77fe5..d1e7c0559 100644 --- a/src/llvm_backend_type.cpp +++ b/src/llvm_backend_type.cpp @@ -525,7 +525,15 @@ gb_internal void lb_setup_type_info_data_giant_array(lbModule *m, i64 global_typ break; case Basic_string: - tag_type = t_type_info_string; + { + tag_type = t_type_info_string; + LLVMValueRef vals[2] = { + lb_const_bool(m, t_bool, false).value, + lb_const_int(m, t_type_info_string_encoding_kind, 0).value, + }; + + variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals)); + } break; case Basic_cstring: @@ -533,7 +541,7 @@ gb_internal void lb_setup_type_info_data_giant_array(lbModule *m, i64 global_typ tag_type = t_type_info_string; LLVMValueRef vals[2] = { lb_const_bool(m, t_bool, true).value, - lb_const_bool(m, t_bool, false).value, + lb_const_int(m, t_type_info_string_encoding_kind, 0).value, }; variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals)); @@ -545,7 +553,7 @@ gb_internal void lb_setup_type_info_data_giant_array(lbModule *m, i64 global_typ tag_type = t_type_info_string; LLVMValueRef vals[2] = { lb_const_bool(m, t_bool, false).value, - lb_const_bool(m, t_bool, true).value, + lb_const_int(m, t_type_info_string_encoding_kind, 1).value, }; variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals)); @@ -558,7 +566,7 @@ gb_internal void lb_setup_type_info_data_giant_array(lbModule *m, i64 global_typ tag_type = t_type_info_string; LLVMValueRef vals[2] = { lb_const_bool(m, t_bool, true).value, - lb_const_bool(m, t_bool, true).value, + lb_const_int(m, t_type_info_string_encoding_kind, 1).value, }; variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals)); diff --git a/src/types.cpp b/src/types.cpp index 51d170f2b..c465714db 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -661,6 +661,8 @@ gb_global Type *t_type_info_enum_value = nullptr; gb_global Type *t_type_info_ptr = nullptr; gb_global Type *t_type_info_enum_value_ptr = nullptr; +gb_global Type *t_type_info_string_encoding_kind = nullptr; + gb_global Type *t_type_info_named = nullptr; gb_global Type *t_type_info_integer = nullptr; gb_global Type *t_type_info_rune = nullptr; From ec7509430369eb5d57a081507792dc03b1c05bab Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Tue, 5 Aug 2025 21:31:06 +0200 Subject: [PATCH 018/105] remove windows binaries from non-windows releases --- .github/workflows/nightly.yml | 4 ++++ ci/remove_windows_binaries.sh | 8 ++++++++ 2 files changed, 12 insertions(+) create mode 100755 ci/remove_windows_binaries.sh diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 6826239e8..2c9dc30ae 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -69,6 +69,7 @@ jobs: cp -r core $FILE cp -r vendor $FILE cp -r examples $FILE + ./ci/remove_windows_binaries.sh $FILE # Creating a tarball so executable permissions are retained, see https://github.com/actions/upload-artifact/issues/38 tar -czvf dist.tar.gz $FILE - name: Odin run @@ -108,6 +109,7 @@ jobs: cp -r core $FILE cp -r vendor $FILE cp -r examples $FILE + ./ci/remove_windows_binaries.sh $FILE # Creating a tarball so executable permissions are retained, see https://github.com/actions/upload-artifact/issues/38 tar -czvf dist.tar.gz $FILE - name: Odin run @@ -145,6 +147,7 @@ jobs: cp -r core $FILE cp -r vendor $FILE cp -r examples $FILE + ./ci/remove_windows_binaries.sh $FILE dylibbundler -b -x $FILE/odin -d $FILE/libs -od -p @executable_path/libs # Creating a tarball so executable permissions are retained, see https://github.com/actions/upload-artifact/issues/38 tar -czvf dist.tar.gz $FILE @@ -183,6 +186,7 @@ jobs: cp -r core $FILE cp -r vendor $FILE cp -r examples $FILE + ./ci/remove_windows_binaries.sh $FILE dylibbundler -b -x $FILE/odin -d $FILE/libs -od -p @executable_path/libs # Creating a tarball so executable permissions are retained, see https://github.com/actions/upload-artifact/issues/38 tar -czvf dist.tar.gz $FILE diff --git a/ci/remove_windows_binaries.sh b/ci/remove_windows_binaries.sh new file mode 100755 index 000000000..0722fc455 --- /dev/null +++ b/ci/remove_windows_binaries.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env sh + +find "$1" -type f \(\ + -iname "*.exe" \ + -o -iname "*.dll" \ + -o -iname "*.lib" \ + -o -iname "*.pdb" \ + \) -delete From 9d8e15b3af6e41b3b3d4359eb0d2324cfa34608f Mon Sep 17 00:00:00 2001 From: Harold Brenes Date: Wed, 6 Aug 2025 15:13:12 -0400 Subject: [PATCH 019/105] Implementes the block ABI.2010.3.16 natively via the `objc_block` intrinsic and the `Objc_Block` builtin type. See: https://clang.llvm.org/docs/Block-ABI-Apple.html --- base/intrinsics/intrinsics.odin | 1 + base/runtime/core_builtin.odin | 5 + base/runtime/procs_darwin.odin | 12 +- src/check_builtin.cpp | 224 ++++++++++++++++++ src/checker.cpp | 4 + src/checker_builtin_procs.hpp | 2 + src/llvm_backend.hpp | 6 +- src/llvm_backend_proc.cpp | 1 + src/llvm_backend_utility.cpp | 391 ++++++++++++++++++++++++++++++++ 9 files changed, 644 insertions(+), 2 deletions(-) diff --git a/base/intrinsics/intrinsics.odin b/base/intrinsics/intrinsics.odin index d45d24f48..4f644728e 100644 --- a/base/intrinsics/intrinsics.odin +++ b/base/intrinsics/intrinsics.odin @@ -381,6 +381,7 @@ objc_register_selector :: proc($name: string) -> objc_SEL --- objc_find_class :: proc($name: string) -> objc_Class --- objc_register_class :: proc($name: string) -> objc_Class --- objc_ivar_get :: proc(self: ^$T) -> ^$U --- +objc_block :: proc(invoke: $T, ..any) -> ^Objc_Block(T) where type_is_proc(T) --- valgrind_client_request :: proc(default: uintptr, request: uintptr, a0, a1, a2, a3, a4: uintptr) -> uintptr --- diff --git a/base/runtime/core_builtin.odin b/base/runtime/core_builtin.odin index 09118998c..3a51d71fb 100644 --- a/base/runtime/core_builtin.odin +++ b/base/runtime/core_builtin.odin @@ -5,6 +5,11 @@ import "base:intrinsics" @builtin Maybe :: union($T: typeid) {T} +/* +Represents an Objective-C block with a given procedure signature T +*/ +@builtin +Objc_Block :: struct($T: typeid) where intrinsics.type_is_proc(T) { using _: intrinsics.objc_object } /* Recovers the containing/parent struct from a pointer to one of its fields. diff --git a/base/runtime/procs_darwin.odin b/base/runtime/procs_darwin.odin index 20f09400d..d176f0f63 100644 --- a/base/runtime/procs_darwin.odin +++ b/base/runtime/procs_darwin.odin @@ -1,9 +1,12 @@ #+private package runtime -@(priority_index=-1e6) +@(priority_index=-1e5) foreign import ObjC "system:objc" +@(priority_index=-1e6) +foreign import libSystem "system:System" + import "base:intrinsics" objc_id :: ^intrinsics.objc_object @@ -34,3 +37,10 @@ foreign ObjC { object_getClass :: proc "c" (obj: objc_id) -> objc_Class --- } +foreign libSystem { + _NSConcreteGlobalBlock: intrinsics.objc_class + _NSConcreteStackBlock: intrinsics.objc_class + + _Block_object_assign :: proc "c" (rawptr, rawptr, i32) --- + _Block_object_dispose :: proc "c" (rawptr, i32) --- +} diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index 57413f519..9e2ad86c0 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -457,6 +457,229 @@ gb_internal bool check_builtin_objc_procedure(CheckerContext *c, Operand *operan return true; } break; + + case BuiltinProc_objc_block: + { + // NOTE(harold): The last argument specified in the call is the handler proc, + // any other arguments before it are capture by-copy arguments. + auto param_operands = slice_make(permanent_allocator(), ce->args.count); + + isize capture_arg_count = ce->args.count - 1; + + // NOTE(harold): The first parameter is already checked at check_builtin_procedure(). + // Checking again would invalidate the Entity -> Value map for direct parameters if it's the handler proc. + param_operands[0] = *operand; + + for (isize i = 0; i < ce->args.count-1; i++) { + Operand x = {}; + check_expr(c, &x, ce->args[i]); + + switch (x.mode) { + case Addressing_Value: + case Addressing_Context: + case Addressing_Variable: + case Addressing_Constant: + param_operands[i] = x; + break; + + default: + gbString e = expr_to_string(x.expr); + gbString t = type_to_string(x.type); + error(x.expr, "'%.*s' capture arguments must be values, but got %s of type %s", LIT(builtin_name), e, t); + gb_string_free(t); + gb_string_free(e); + return false; + } + } + + // Validate handler proc + Operand handler = {}; + + if (capture_arg_count == 0) { + // It's already been checked and assigned + handler = param_operands[0]; + } else { + check_expr_or_type(c, &handler, ce->args[capture_arg_count]); + param_operands[capture_arg_count] = handler; + } + + if (!is_operand_value(handler) || handler.type->kind != Type_Proc) { + gbString e = expr_to_string(handler.expr); + gbString t = type_to_string(handler.type); + error(handler.expr, "'%.*s' expected a procedure, but got '%s' of type %s", LIT(builtin_name), e, t); + gb_string_free(t); + gb_string_free(e); + return false; + } + + Ast *handler_node = unparen_expr(handler.expr); + + // Only direct reference to procs are allowed + switch (handler_node->kind) { + case Ast_ProcLit: break; // ok + case Ast_Ident: { + auto& ident = handler_node->Ident; + + if (ident.entity == nullptr) { + error(handler.expr, "'%.*s' failed to resolve entity from expression", LIT(builtin_name)); + return false; + } + + if (ident.entity->kind != Entity_Procedure) { + gbString e = expr_to_string(handler_node); + + ERROR_BLOCK(); + error(handler.expr, "'%.*s' expected a direct reference to a procedure", LIT(builtin_name)); + if(ident.entity->kind == Entity_Variable) { + error_line("\tSuggestion: Variables referencing a procedure are not allowed, they are not a direct procedure reference."); + } else { + error_line("\tSuggestion: Ensure '%s' is not a runtime-evaluated expression.", e); // NOTE(harold): Is this case possible to hit? + } + error_line("\n\t Refer to a procedure directly by its name or declare it anonymously: %.*s(proc(){})", LIT(builtin_name)); + + gb_string_free(e); + return false; + } + } break; + + default: { + gbString e = expr_to_string(handler_node); + ERROR_BLOCK(); + error(handler.expr, "'%.*s' expected a direct reference to a procedure", LIT(builtin_name)); + if( handler_node->kind == Ast_CallExpr) { + error_line("\tSuggestion: Do not use a procedure returned from another procedure."); + } else { + error_line("\tSuggestion: Ensure '%s' is not a runtime-evaluated expression.", e); + } + error_line("\n\t Refer to a procedure directly by its name or declare it anonymously: %.*s(proc(){})", LIT(builtin_name)); + + gb_string_free(e); + } return false; + } // End switch + + auto& handler_type_proc = handler.type->Proc; + + if (capture_arg_count > handler_type_proc.param_count) { + error(handler.expr, "'%.*s' captured arguments exceeded the handler's parameter count", LIT(builtin_name)); + return false; + } + + // If the handler proc is odin calling convention, but there must be a context defined in this scope. + if (handler_type_proc.calling_convention == ProcCC_Odin) { + if ((c->scope->flags & ScopeFlag_ContextDefined) == 0) { + ERROR_BLOCK(); + error(handler.expr, "The handler procedure for '%.*s' requires a context, but no context is defined in the current scope", LIT(builtin_name)); + error_line("\tSuggestion: 'context = runtime.default_context()', or use the \"c\" calling convention for the handler procedure"); + return false; + } + } + + // At most a single return value is supported + if (handler_type_proc.result_count > 1) { + error(handler_type_proc.node->ProcType.results, "Handler procedures for '%.*s' cannot have multiple return values", LIT(builtin_name)); + return false; + } + + // Ensure that captured args are assignable to the handler's corresponding capture params + if (handler_type_proc.param_count > 0) { + auto& handler_param_types = handler.type->Proc.params->Tuple.variables; + Slice handler_capture_param_types = slice(handler_param_types, handler_param_types.count - capture_arg_count, handler_param_types.count); + + for (isize i = 0; i < capture_arg_count; i++) { + Operand op = param_operands[i]; + if (!check_is_assignable_to(c, &op, handler_capture_param_types[i]->type)) { + gbString e = expr_to_string(op.expr); + gbString src = type_to_string(op.type); + gbString dst = type_to_string(handler_capture_param_types[i]->type); + error(op.expr, "'%.*s' captured value '%s' of type '%s' is not assignable to type '%s'", LIT(builtin_name), e, src, dst); + gb_string_free(e); + gb_string_free(src); + gb_string_free(dst); + return false; + } + } + } + + ProcCallingConvention cc = handler_type_proc.calling_convention; + switch (cc) { + case ProcCC_Odin: + case ProcCC_Contextless: + case ProcCC_CDecl: + break; // ok + default: + ERROR_BLOCK(); + + error(handler.expr, "'%.*s' Invalid calling convention for block procedure.", LIT(builtin_name)); + error_line("\tSuggestion: Do not specify a calling convention ot else use \"c\" or \"cotextless\""); + return false; + } + + if (handler_type_proc.is_polymorphic) { + error(handler.expr, "'%.*s' Unspecialized polymorphic procedures are not allowed.", LIT(builtin_name)); + return false; + } + + // Create the specialized Objc_Block type that this intrinsic will return + Token ident = {}; + ident.kind = Token_Ident; + ident.string = str_lit("Objc_Block"); + ident.pos = ast_token(call).pos; + + Token l_paren = {}; + l_paren.kind = Token_OpenParen; + l_paren.string = str_lit("("); + l_paren.pos = ident.pos; + + Token r_paren = {}; + r_paren.kind = Token_CloseParen; + l_paren.string = str_lit(")"); + r_paren.pos = ident.pos; + + // Remove the capture args from the resulting Objc_Block type signature + Ast* handler_proc_type_copy = clone_ast(handler_type_proc.node); + handler_proc_type_copy->ProcType.params->FieldList.list.count -= capture_arg_count; + + // Make sure the Objc_Block's specialized proc is always "c" calling conv, + // even if we have a context, as the invoker is always "c". + // This allows us to have compatibility with the target block types with either calling convention used. + handler_proc_type_copy->ProcType.calling_convention = ProcCC_CDecl; + + Array poly_args = {}; + array_init(&poly_args, permanent_allocator(), 1, 1); + poly_args[0] = handler_proc_type_copy; + + + Type *t_Objc_Block = find_core_type(c->checker, str_lit("Objc_Block")); + Operand poly_op = {}; + poly_op.type = t_Objc_Block; + poly_op.mode = Addressing_Type; + + Ast *poly_call = ast_call_expr(nullptr, ast_ident(nullptr, ident), poly_args, l_paren, r_paren, {}); + + auto err = check_polymorphic_record_type(c, &poly_op, poly_call); + + if (err != 0) { + operand->mode = Addressing_Invalid; + operand->type = t_invalid; + error(handler.expr, "'%.*s' failed to determine resulting Objc_Block handler procedure", LIT(builtin_name)); + return false; + } + + GB_ASSERT(poly_op.type != t_Objc_Block); + GB_ASSERT(poly_op.mode == Addressing_Type); + + bool is_global_block = capture_arg_count == 0 && handler_type_proc.calling_convention != ProcCC_Odin; + if (is_global_block) { + try_to_add_package_dependency(c, "runtime", "_NSConcreteGlobalBlock"); + } else { + try_to_add_package_dependency(c, "runtime", "_NSConcreteStackBlock"); + } + + *operand = poly_op; + operand->type = alloc_type_pointer(operand->type); + operand->mode = Addressing_Value; + return true; + } break; } } @@ -2291,6 +2514,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As case BuiltinProc_objc_register_selector: case BuiltinProc_objc_register_class: case BuiltinProc_objc_ivar_get: + case BuiltinProc_objc_block: return check_builtin_objc_procedure(c, operand, call, id, type_hint); case BuiltinProc___entry_point: diff --git a/src/checker.cpp b/src/checker.cpp index e72061f56..a13290750 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -1460,6 +1460,10 @@ gb_internal void destroy_checker_info(CheckerInfo *i) { mpsc_destroy(&i->foreign_decls_to_check); map_destroy(&i->objc_msgSend_types); + string_set_destroy(&i->obcj_class_name_set); + mpsc_destroy(&i->objc_class_implementations); + map_destroy(&i->objc_method_implementations); + string_map_destroy(&i->load_file_cache); string_map_destroy(&i->load_directory_cache); map_destroy(&i->load_directory_map); diff --git a/src/checker_builtin_procs.hpp b/src/checker_builtin_procs.hpp index b8b105fd2..da5418c1c 100644 --- a/src/checker_builtin_procs.hpp +++ b/src/checker_builtin_procs.hpp @@ -351,6 +351,7 @@ BuiltinProc__type_end, BuiltinProc_objc_register_selector, BuiltinProc_objc_register_class, BuiltinProc_objc_ivar_get, + BuiltinProc_objc_block, BuiltinProc_constant_utf16_cstring, @@ -711,6 +712,7 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = { {STR_LIT("objc_register_selector"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics, false, true}, {STR_LIT("objc_register_class"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics, false, true}, {STR_LIT("objc_ivar_get"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics, false, true}, + {STR_LIT("objc_block"), 1, true, Expr_Expr, BuiltinProcPkg_intrinsics, false, true}, {STR_LIT("constant_utf16_cstring"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, diff --git a/src/llvm_backend.hpp b/src/llvm_backend.hpp index 648e8a732..cc3dcaa4a 100644 --- a/src/llvm_backend.hpp +++ b/src/llvm_backend.hpp @@ -198,6 +198,7 @@ struct lbModule { StringMap objc_classes; StringMap objc_selectors; StringMap objc_ivars; + isize objc_next_block_id; // Used to name objective-c blocks, per module PtrMap map_cell_info_map; // address of runtime.Map_Info PtrMap map_info_map; // address of runtime.Map_Cell_Info @@ -483,7 +484,10 @@ gb_internal void lb_emit_if(lbProcedure *p, lbValue cond, lbBlock *true_block, l gb_internal void lb_start_block(lbProcedure *p, lbBlock *b); gb_internal lbValue lb_build_call_expr(lbProcedure *p, Ast *expr); - +gb_internal lbProcedure *lb_create_dummy_procedure(lbModule *m, String link_name, Type *type); +gb_internal void lb_begin_procedure_body(lbProcedure *p); +gb_internal void lb_end_procedure_body(lbProcedure *p); +gb_internal lbValue lb_emit_call(lbProcedure *p, lbValue value, Array const &args, ProcInlining inlining); gb_internal lbAddr lb_find_or_generate_context_ptr(lbProcedure *p); gb_internal lbContextData *lb_push_context_onto_stack(lbProcedure *p, lbAddr ctx); diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index 8f306b771..c95bb0c29 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -3746,6 +3746,7 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu case BuiltinProc_objc_register_selector: return lb_handle_objc_register_selector(p, expr); case BuiltinProc_objc_register_class: return lb_handle_objc_register_class(p, expr); case BuiltinProc_objc_ivar_get: return lb_handle_objc_ivar_get(p, expr); + case BuiltinProc_objc_block: return lb_handle_objc_block(p, expr); case BuiltinProc_constant_utf16_cstring: diff --git a/src/llvm_backend_utility.cpp b/src/llvm_backend_utility.cpp index dcb95a9a2..f7807364a 100644 --- a/src/llvm_backend_utility.cpp +++ b/src/llvm_backend_utility.cpp @@ -2263,6 +2263,397 @@ gb_internal lbValue lb_handle_objc_ivar_get(lbProcedure *p, Ast *expr) { return lb_handle_objc_ivar_for_objc_object_pointer(p, self); } +gb_internal void lb_create_objc_block_helper_procs( + lbModule *m, LLVMTypeRef block_lit_type, isize capture_field_offset, + Slice capture_values, Slice objc_object_indices, + lbProcedure *&out_copy_helper, lbProcedure *&out_dispose_helper +) { + gbString copy_helper_name = gb_string_append_fmt(gb_string_make(temporary_allocator(), ""), "__$objc_block_copy_helper_%lld", m->objc_next_block_id); + gbString dispose_helper_name = gb_string_append_fmt(gb_string_make(temporary_allocator(), ""), "__$objc_block_dispose_helper_%lld", m->objc_next_block_id); + + // copy: Block_Literal *dst, Block_Literal *src, i32 field_apropos + // dispose: Block_Literal *src, i32 field_apropos + Type *types[3] = { t_rawptr, t_rawptr, t_i32 }; + + Type *copy_tuple = alloc_type_tuple_from_field_types(types, 3, false, true); + Type *dispose_tuple = alloc_type_tuple_from_field_types(&types[1], 2, false, true); + + Type *copy_proc_type = alloc_type_proc(nullptr, copy_tuple, 3, nullptr, 0, false, ProcCC_CDecl); + Type *dispose_proc_type = alloc_type_proc(nullptr, dispose_tuple, 2, nullptr, 0, false, ProcCC_CDecl); + + lbProcedure *copy_proc = lb_create_dummy_procedure(m, make_string((u8*)copy_helper_name, gb_string_length(copy_helper_name)), copy_proc_type); + lbProcedure *dispose_proc = lb_create_dummy_procedure(m, make_string((u8*)dispose_helper_name, gb_string_length(dispose_helper_name)), dispose_proc_type); + LLVMSetLinkage(copy_proc->value, LLVMPrivateLinkage); + LLVMSetLinkage(dispose_proc->value, LLVMPrivateLinkage); + + + const int BLOCK_FIELD_IS_OBJECT = 3; // id, NSObject, __attribute__((NSObject)), block, ... + const int BLOCK_FIELD_IS_BLOCK = 7; // a block variable + + Type *block_base_type = find_core_type(m->info->checker, str_lit("Objc_Block")); + + auto is_object_objc_block = [](Type *type, Type *block_base_type) -> bool { + + Type *base = base_type(type_deref(type)); + GB_ASSERT(base->kind == Type_Struct); + + while (is_type_polymorphic_record_specialized(base)) { + if (base->Struct.polymorphic_parent) { + base = base->Struct.polymorphic_parent; + + if (base == block_base_type) { + return true; + } + base = base_type(base); + GB_ASSERT(base->kind == Type_Struct); + } + } + + return false; + }; + + lb_begin_procedure_body(copy_proc); + lb_begin_procedure_body(dispose_proc); + { + for (isize object_index : objc_object_indices) { + const auto field_offset = unsigned(capture_field_offset+object_index); + + Type *field_type = capture_values[object_index].type; + LLVMTypeRef field_raw_type = lb_type(m, field_type); + + GB_ASSERT(is_type_objc_object(field_type)); + bool is_block_obj = is_object_objc_block(field_type, block_base_type); + + auto copy_args = array_make(temporary_allocator(), 3, 3); + auto dispose_args = array_make(temporary_allocator(), 2, 2); + + // Copy helper + { + LLVMValueRef dst_field = LLVMBuildStructGEP2(copy_proc->builder, block_lit_type, copy_proc->raw_input_parameters[0], field_offset, ""); + LLVMValueRef src_field = LLVMBuildStructGEP2(copy_proc->builder, block_lit_type, copy_proc->raw_input_parameters[1], field_offset, ""); + + lbValue dst_value = {}, src_value = {}; + dst_value.type = alloc_type_pointer(field_type); + dst_value.value = dst_field; + + src_value.type = field_type; + src_value.value = LLVMBuildLoad2(copy_proc->builder, field_raw_type, src_field, ""); + + copy_args[0] = dst_value; + copy_args[1] = src_value; + copy_args[2] = lb_const_int(m, t_i32, u64(is_block_obj ? BLOCK_FIELD_IS_BLOCK : BLOCK_FIELD_IS_OBJECT)); + + lb_emit_runtime_call(copy_proc, "_Block_object_assign", copy_args); + } + + // Dispose helper + { + LLVMValueRef src_field = LLVMBuildStructGEP2(dispose_proc->builder, block_lit_type, dispose_proc->raw_input_parameters[0], field_offset, ""); + lbValue src_value = {}; + src_value.type = field_type; + src_value.value = LLVMBuildLoad2(dispose_proc->builder, field_raw_type, src_field, ""); + + dispose_args[0] = src_value; + dispose_args[1] = lb_const_int(m, t_i32, u64(is_block_obj ? BLOCK_FIELD_IS_BLOCK : BLOCK_FIELD_IS_OBJECT)); + + lb_emit_runtime_call(dispose_proc, "_Block_object_dispose", dispose_args); + } + } + } + lb_end_procedure_body(copy_proc); + lb_end_procedure_body(dispose_proc); + + + out_copy_helper = copy_proc; + out_dispose_helper = dispose_proc; +} + +gb_internal lbValue lb_handle_objc_block(lbProcedure *p, Ast *expr) { + /// #See: https://clang.llvm.org/docs/Block-ABI-Apple.html + /// https://www.newosxbook.com/src.php?tree=xnu&file=/libkern/libkern/Block_private.h + /// https://github.com/llvm/llvm-project/blob/21f1f9558df3830ffa637def364e3c0cb0dbb3c0/compiler-rt/lib/BlocksRuntime/Block_private.h + /// https://github.com/apple-oss-distributions/libclosure/blob/3668b0837f47be3cc1c404fb5e360f4ff178ca13/runtime.cpp + + ast_node(ce, CallExpr, expr); + GB_ASSERT(ce->args.count > 0); + + lbModule *m = p->module; + + m->objc_next_block_id += 1; + + const isize capture_arg_count = ce->args.count - 1; + + Type *block_result_type = type_of_expr(expr); + GB_ASSERT(block_result_type != nullptr && block_result_type->kind == Type_Pointer); + + LLVMTypeRef lb_type_rawptr = lb_type(m, t_rawptr); + LLVMTypeRef lb_type_i32 = lb_type(m, t_i32); + LLVMTypeRef lb_type_int = lb_type(m, t_int); + + // Build user proc + // Type * user_proc_type = type_of_expr(ce->args[capture_arg_count]); + lbValue user_proc_value = lb_build_expr(p, ce->args[capture_arg_count]); + auto& user_proc = user_proc_value.type->Proc; + GB_ASSERT(user_proc_value.type->kind == Type_Proc); + + const bool is_global = capture_arg_count == 0 && user_proc.calling_convention != ProcCC_Odin; + const isize block_forward_args = user_proc.param_count - capture_arg_count; + const isize capture_fields_offset = user_proc.calling_convention != ProcCC_Odin ? 5 : 6; + + Ast *proc_lit = unparen_expr(ce->args[capture_arg_count]); + if (proc_lit->kind == Ast_Ident) { + proc_lit = proc_lit->Ident.entity->decl_info->proc_lit; + } + GB_ASSERT(proc_lit->kind == Ast_ProcLit); + + lbProcedure *copy_helper = {}, *dispose_helper = {}; + + // Build captured arguments & collect the ones that are Objective-C objects + auto captured_values = array_make(temporary_allocator(), capture_arg_count, capture_arg_count); + auto objc_captures = array_make(temporary_allocator()); + + for (isize i = 0; i < capture_arg_count; i++) { + captured_values[i] = lb_build_expr(p, ce->args[i]); + + if (is_type_pointer(captured_values[i].type) && is_type_objc_object(captured_values[i].type)) { + array_add(&objc_captures, i); + } + } + + const bool has_objc_fields = objc_captures.count > 0; + + + // Create proc with the block signature + // (takes a block literal pointer as the first parameter, followed by any expected ones from the user's proc) + gbString block_invoker_name = gb_string_append_fmt(gb_string_make(permanent_allocator(), ""), "__$objc_block_invoker_%lld", m->objc_next_block_id); + + // Add + 1 because the first parameter received is the block literal pointer itself + auto invoker_args = array_make(temporary_allocator(), block_forward_args + 1, block_forward_args + 1); + invoker_args[0] = t_rawptr; + + GB_ASSERT(block_forward_args <= user_proc.param_count); + if (user_proc.param_count > 0) { + Slice user_proc_param_types = user_proc.params->Tuple.variables; + for (isize i = 0; i < block_forward_args; i++) { + invoker_args[i+1] = user_proc_param_types[i]->type; + } + } + + GB_ASSERT(user_proc.result_count <= 1); + + Type *invoker_args_tuple = alloc_type_tuple_from_field_types(invoker_args.data, invoker_args.count, false, true); + Type *invoker_results_tuple = nullptr; + if (user_proc.result_count > 0) { + invoker_results_tuple = alloc_type_tuple_from_field_types(&user_proc.results->Tuple.variables[0]->type, 1, false, true); + } + + Type *invoker_proc_type = alloc_type_proc(nullptr, invoker_args_tuple, invoker_args_tuple->Tuple.variables.count, + invoker_results_tuple, user_proc.result_count, false, ProcCC_CDecl); + + lbProcedure *invoker_proc = lb_create_dummy_procedure(m, make_string((u8*)block_invoker_name, + gb_string_length(block_invoker_name)), invoker_proc_type); + LLVMSetLinkage(invoker_proc->value, LLVMPrivateLinkage); + + // Create the block descriptor and block literal + gbString block_lit_type_name = gb_string_make(temporary_allocator(), "__$ObjC_Block_Literal_"); + block_lit_type_name = gb_string_append_fmt(block_lit_type_name, "%lld", m->objc_next_block_id); + + gbString block_desc_type_name = gb_string_make(temporary_allocator(), "__$ObjC_Block_Descriptor_"); + block_desc_type_name = gb_string_append_fmt(block_desc_type_name, "%lld", m->objc_next_block_id); + + LLVMTypeRef block_lit_type = {}; + LLVMTypeRef block_desc_type = {}; + LLVMValueRef block_desc_initializer = {}; + + { + block_desc_type = LLVMStructCreateNamed(m->ctx, block_desc_type_name); + + LLVMTypeRef fields_types[4] = { + lb_type_int, // Reserved + lb_type_int, // Block size + lb_type_rawptr, // Copy helper func pointer + lb_type_rawptr, // Dispose helper func pointer + }; + + LLVMStructSetBody(block_desc_type, fields_types, has_objc_fields ? 4 : 2, false); + } + + { + block_lit_type = LLVMStructCreateNamed(m->ctx, block_lit_type_name); + + auto fields = array_make(temporary_allocator()); + + array_add(&fields, lb_type_rawptr); // isa + array_add(&fields, lb_type_i32); // flags + array_add(&fields, lb_type_i32); // reserved + array_add(&fields, lb_type_rawptr); // invoke + array_add(&fields, block_desc_type); // descriptor + + if (user_proc.calling_convention == ProcCC_Odin) { + array_add(&fields, lb_type(m, t_context)); // context + } + + // From here on, fields for the captured vars are added + for (lbValue cap_arg : captured_values) { + array_add(&fields, lb_type(m, cap_arg.type)); + } + + LLVMStructSetBody(block_lit_type, fields.data, (unsigned)fields.count, false); + } + + // Generate copy and dispose helper functions for captured params that are Objective-C objects (or a Block) + if (has_objc_fields) { + lb_create_objc_block_helper_procs(m, block_lit_type, capture_fields_offset, + slice(captured_values, 0, captured_values.count), + slice(objc_captures, 0, objc_captures.count), + copy_helper, dispose_helper); + } + + { + LLVMValueRef fields_values[4] = { + lb_const_int(m, t_int, 0).value, // Reserved + lb_const_int(m, t_int, u64(lb_sizeof(block_lit_type))).value, // Block size + has_objc_fields ? copy_helper->value : nullptr, // Copy helper + has_objc_fields ? dispose_helper->value : nullptr, // Dispose helper + }; + + block_desc_initializer = LLVMConstNamedStruct(block_desc_type, fields_values, has_objc_fields ? 4 : 2); + } + + // Create global block descriptor + gbString desc_global_name = gb_string_make(temporary_allocator(), "__$objc_block_desc_"); + desc_global_name = gb_string_append_fmt(desc_global_name, "%lld", m->objc_next_block_id); + + LLVMValueRef p_descriptor = LLVMAddGlobal(m->mod, block_desc_type, desc_global_name); + LLVMSetInitializer(p_descriptor, block_desc_initializer); + + + /// Invoker body + lb_begin_procedure_body(invoker_proc); + { + auto call_args = array_make(temporary_allocator(), user_proc.param_count, user_proc.param_count); + + for (isize i = 1; i < invoker_proc->raw_input_parameters.count; i++) { + lbValue arg = {}; + arg.type = invoker_args[i]; + arg.value = invoker_proc->raw_input_parameters[i], + call_args[i-1] = arg; + } + + LLVMValueRef block_literal = invoker_proc->raw_input_parameters[0]; + + // Push context, if needed + if (user_proc.calling_convention == ProcCC_Odin) { + LLVMValueRef p_context = LLVMBuildStructGEP2(invoker_proc->builder, block_lit_type, block_literal, 5, "context"); + lbValue ctx_val = {}; + ctx_val.type = t_context_ptr; + ctx_val.value = p_context; + + lb_push_context_onto_stack(invoker_proc, lb_addr(ctx_val)); + } + + // Copy capture parameters from the block literal + for (isize i = 0; i < capture_arg_count; i++) { + LLVMValueRef cap_value = LLVMBuildStructGEP2(invoker_proc->builder, block_lit_type, block_literal, unsigned(capture_fields_offset + i), ""); + + lbValue cap_arg = {}; + cap_arg.value = cap_value; + cap_arg.type = alloc_type_pointer(captured_values[i].type); + + lbValue arg = lb_emit_load(invoker_proc, cap_arg); + call_args[block_forward_args+i] = arg; + } + + lbValue result = lb_emit_call(invoker_proc, user_proc_value, call_args, proc_lit->ProcLit.inlining); + + GB_ASSERT(user_proc.result_count <= 1); + if (user_proc.result_count > 0) { + GB_ASSERT(result.value != nullptr); + LLVMBuildRet(p->builder, result.value); + } + } + lb_end_procedure_body(invoker_proc); + + + /// Create local block literal + const int BLOCK_HAS_COPY_DISPOSE = (1 << 25); + const int BLOCK_IS_GLOBAL = (1 << 28); + + int raw_flags = is_global ? BLOCK_IS_GLOBAL : 0; + if (has_objc_fields) { + raw_flags |= BLOCK_HAS_COPY_DISPOSE; + } + + gbString block_var_name = gb_string_make(temporary_allocator(), "__$objc_block_literal_"); + block_var_name = gb_string_append_fmt(block_var_name, "%lld", m->objc_next_block_id); + + lbValue result = {}; + result.type = block_result_type; + + lbValue isa_val = lb_find_runtime_value(m, is_global ? str_lit("_NSConcreteGlobalBlock") : str_lit("_NSConcreteStackBlock")); + lbValue flags_val = lb_const_int(m, t_i32, (u64)raw_flags); + lbValue reserved_val = lb_const_int(m, t_i32, 0); + + if (is_global) { + LLVMValueRef p_block_lit = LLVMAddGlobal(m->mod, block_lit_type, block_var_name); + result.value = p_block_lit; + + LLVMValueRef fields_values[5] = { + isa_val.value, // isa + flags_val.value, // flags + reserved_val.value, // reserved + invoker_proc->value, // invoke + p_descriptor // descriptor + }; + + LLVMValueRef g_block_lit_initializer = LLVMConstNamedStruct(block_lit_type, fields_values, gb_count_of(fields_values)); + LLVMSetInitializer(p_block_lit, g_block_lit_initializer); + + } else { + LLVMValueRef p_block_lit = llvm_alloca(p, block_lit_type, lb_alignof(block_lit_type), block_var_name); + result.value = p_block_lit; + + // Initialize it + LLVMValueRef f_isa = LLVMBuildStructGEP2(p->builder, block_lit_type, p_block_lit, 0, "isa"); + LLVMValueRef f_flags = LLVMBuildStructGEP2(p->builder, block_lit_type, p_block_lit, 1, "flags"); + LLVMValueRef f_reserved = LLVMBuildStructGEP2(p->builder, block_lit_type, p_block_lit, 2, "reserved"); + LLVMValueRef f_invoke = LLVMBuildStructGEP2(p->builder, block_lit_type, p_block_lit, 3, "invoke"); + LLVMValueRef f_descriptor = LLVMBuildStructGEP2(p->builder, block_lit_type, p_block_lit, 4, "descriptor"); + + LLVMBuildStore(p->builder, isa_val.value, f_isa); + LLVMBuildStore(p->builder, flags_val.value, f_flags); + LLVMBuildStore(p->builder, reserved_val.value, f_reserved); + LLVMBuildStore(p->builder, invoker_proc->value, f_invoke); + LLVMBuildStore(p->builder, p_descriptor, f_descriptor); + + // Store current context, if there is one + if (user_proc.calling_convention == ProcCC_Odin) { + LLVMValueRef f_context = LLVMBuildStructGEP2(p->builder, block_lit_type, p_block_lit, 5, "context"); + lbAddr p_current_context = lb_find_or_generate_context_ptr(p); + + LLVMValueRef context_size = LLVMConstInt(LLVMInt64TypeInContext(m->ctx), (u64)lb_sizeof(lb_type(m, t_context)), false); + LLVMBuildMemCpy(p->builder, f_context, lb_try_get_alignment(f_context, 1), + p_current_context.addr.value, lb_try_get_alignment(p_current_context.addr.value, 1), context_size); + } + + // Store captured args into the block + for (isize i = 0; i < captured_values.count; i++) { + lbValue capture_arg = captured_values[i]; + + unsigned field_index = unsigned(capture_fields_offset + i); + LLVMValueRef f_capture = LLVMBuildStructGEP2(p->builder, block_lit_type, p_block_lit, field_index, "capture_arg"); + + lbValue f_capture_val = {}; + f_capture_val.type = alloc_type_pointer(capture_arg.type); + f_capture_val.value = f_capture; + + lb_emit_store(p, f_capture_val, capture_arg); + } + } + + return result; +} + gb_internal lbValue lb_handle_objc_find_selector(lbProcedure *p, Ast *expr) { ast_node(ce, CallExpr, expr); From a492fa7bc2f83d08a1a639cd2b8087e4752a51a5 Mon Sep 17 00:00:00 2001 From: Tohei Ichikawa Date: Wed, 6 Aug 2025 23:56:36 -0400 Subject: [PATCH 020/105] Fix Metal mesh shading bindings --- vendor/darwin/Metal/MetalClasses.odin | 363 ++++++++++++++++++++------ vendor/darwin/Metal/MetalEnums.odin | 6 + 2 files changed, 284 insertions(+), 85 deletions(-) diff --git a/vendor/darwin/Metal/MetalClasses.odin b/vendor/darwin/Metal/MetalClasses.odin index 2792cb119..ef57be0b4 100644 --- a/vendor/darwin/Metal/MetalClasses.odin +++ b/vendor/darwin/Metal/MetalClasses.odin @@ -2767,6 +2767,10 @@ RenderPipelineDescriptor_fragmentBuffers :: #force_inline proc "c" (self: ^Rende RenderPipelineDescriptor_fragmentFunction :: #force_inline proc "c" (self: ^RenderPipelineDescriptor) -> ^Function { return msgSend(^Function, self, "fragmentFunction") } +@(objc_type=RenderPipelineDescriptor, objc_name="fragmentLinkedFunctions") +RenderPipelineDescriptor_fragmentLinkedFunctions :: #force_inline proc "c" (self: ^RenderPipelineDescriptor) -> ^LinkedFunctions { + return msgSend(^LinkedFunctions, self, "fragmentLinkedFunctions") +} @(objc_type=RenderPipelineDescriptor, objc_name="inputPrimitiveTopology") RenderPipelineDescriptor_inputPrimitiveTopology :: #force_inline proc "c" (self: ^RenderPipelineDescriptor) -> PrimitiveTopologyClass { return msgSend(PrimitiveTopologyClass, self, "inputPrimitiveTopology") @@ -2831,6 +2835,10 @@ RenderPipelineDescriptor_setDepthAttachmentPixelFormat :: #force_inline proc "c" RenderPipelineDescriptor_setFragmentFunction :: #force_inline proc "c" (self: ^RenderPipelineDescriptor, fragmentFunction: ^Function) { msgSend(nil, self, "setFragmentFunction:", fragmentFunction) } +@(objc_type=RenderPipelineDescriptor, objc_name="setFragmentLinkedFunctions") +RenderPipelineDescriptor_setFragmentLinkedFunctions :: #force_inline proc "c" (self: ^RenderPipelineDescriptor, fragmentLinkedFunctions: ^LinkedFunctions) { + msgSend(nil, self, "setFragmentLinkedFunctions:", fragmentLinkedFunctions) +} @(objc_type=RenderPipelineDescriptor, objc_name="setInputPrimitiveTopology") RenderPipelineDescriptor_setInputPrimitiveTopology :: #force_inline proc "c" (self: ^RenderPipelineDescriptor, inputPrimitiveTopology: PrimitiveTopologyClass) { msgSend(nil, self, "setInputPrimitiveTopology:", inputPrimitiveTopology) @@ -2940,86 +2948,6 @@ RenderPipelineDescriptor_vertexFunction :: #force_inline proc "c" (self: ^Render return msgSend(^Function, self, "vertexFunction") } -@(objc_type=RenderPipelineDescriptor, objc_name="objectFunction") -RenderPipelineDescriptor_objectFunction :: #force_inline proc "c" (self: ^RenderPipelineDescriptor) -> ^Function { - return msgSend(^Function, self, "objectFunction") -} -@(objc_type=RenderPipelineDescriptor, objc_name="setObjectFunction") -RenderPipelineDescriptor_setObjectFunction :: #force_inline proc "c" (self: ^RenderPipelineDescriptor, objectFunction: ^Function) { - msgSend(nil, self, "setObjectFunction:", objectFunction) -} -@(objc_type=RenderPipelineDescriptor, objc_name="meshFunction") -RenderPipelineDescriptor_meshFunction :: #force_inline proc "c" (self: ^RenderPipelineDescriptor) -> ^Function { - return msgSend(^Function, self, "meshFunction") -} -@(objc_type=RenderPipelineDescriptor, objc_name="setMeshFunction") -RenderPipelineDescriptor_setMeshFunction :: #force_inline proc "c" (self: ^RenderPipelineDescriptor, meshFunction: ^Function) { - msgSend(nil, self, "setMeshFunction:", meshFunction) -} - -@(objc_type=RenderPipelineDescriptor, objc_name="maxTotalThreadsPerObjectThreadgroup") -RenderPipelineDescriptor_maxTotalThreadsPerObjectThreadgroup :: #force_inline proc "c" (self: ^RenderPipelineDescriptor) -> NS.UInteger { - return msgSend(NS.UInteger, self, "maxTotalThreadsPerObjectThreadgroup") -} -@(objc_type=RenderPipelineDescriptor, objc_name="setMaxTotalThreadsPerObjectThreadgroup") -RenderPipelineDescriptor_setMaxTotalThreadsPerObjectThreadgroup :: #force_inline proc "c" (self: ^RenderPipelineDescriptor, maxTotalThreadsPerObjectThreadgroup: NS.UInteger) { - msgSend(nil, self, "setMaxTotalThreadsPerObjectThreadgroup:", maxTotalThreadsPerObjectThreadgroup) -} -@(objc_type=RenderPipelineDescriptor, objc_name="maxTotalThreadsPerMeshThreadgroup") -RenderPipelineDescriptor_maxTotalThreadsPerMeshThreadgroup :: #force_inline proc "c" (self: ^RenderPipelineDescriptor) -> NS.UInteger { - return msgSend(NS.UInteger, self, "maxTotalThreadsPerMeshThreadgroup") -} -@(objc_type=RenderPipelineDescriptor, objc_name="setMaxTotalThreadsPerMeshThreadgroup") -RenderPipelineDescriptor_setMaxTotalThreadsPerMeshThreadgroup :: #force_inline proc "c" (self: ^RenderPipelineDescriptor, maxTotalThreadsPerMeshThreadgroup: NS.UInteger) { - msgSend(nil, self, "setMaxTotalThreadsPerMeshThreadgroup:", maxTotalThreadsPerMeshThreadgroup) -} -@(objc_type=RenderPipelineDescriptor, objc_name="objectThreadgroupSizeIsMultipleOfThreadExecutionWidth") -RenderPipelineDescriptor_objectThreadgroupSizeIsMultipleOfThreadExecutionWidth :: #force_inline proc "c" (self: ^RenderPipelineDescriptor) -> NS.UInteger { - return msgSend(NS.UInteger, self, "objectThreadgroupSizeIsMultipleOfThreadExecutionWidth") -} -@(objc_type=RenderPipelineDescriptor, objc_name="setObjectThreadgroupSizeIsMultipleOfThreadExecutionWidth") -RenderPipelineDescriptor_setObjectThreadgroupSizeIsMultipleOfThreadExecutionWidth :: #force_inline proc "c" (self: ^RenderPipelineDescriptor, objectThreadgroupSizeIsMultipleOfThreadExecutionWidth: NS.UInteger) { - msgSend(nil, self, "setObjectThreadgroupSizeIsMultipleOfThreadExecutionWidth:", objectThreadgroupSizeIsMultipleOfThreadExecutionWidth) -} - -@(objc_type=RenderPipelineDescriptor, objc_name="meshThreadgroupSizeIsMultipleOfThreadExecutionWidth") -RenderPipelineDescriptor_meshThreadgroupSizeIsMultipleOfThreadExecutionWidth :: #force_inline proc "c" (self: ^RenderPipelineDescriptor) -> BOOL { - return msgSend(BOOL, self, "meshThreadgroupSizeIsMultipleOfThreadExecutionWidth") -} -@(objc_type=RenderPipelineDescriptor, objc_name="setMeshThreadgroupSizeIsMultipleOfThreadExecutionWidth") -RenderPipelineDescriptor_setMeshThreadgroupSizeIsMultipleOfThreadExecutionWidth :: #force_inline proc "c" (self: ^RenderPipelineDescriptor, meshThreadgroupSizeIsMultipleOfThreadExecutionWidth: BOOL) { - msgSend(nil, self, "setMeshThreadgroupSizeIsMultipleOfThreadExecutionWidth:", meshThreadgroupSizeIsMultipleOfThreadExecutionWidth) -} - - -@(objc_type=RenderPipelineDescriptor, objc_name="payloadMemoryLength") -RenderPipelineDescriptor_payloadMemoryLength :: #force_inline proc "c" (self: ^RenderPipelineDescriptor) -> NS.UInteger { - return msgSend(NS.UInteger, self, "payloadMemoryLength") -} -@(objc_type=RenderPipelineDescriptor, objc_name="setPayloadMemoryLength") -RenderPipelineDescriptor_setPayloadMemoryLength :: #force_inline proc "c" (self: ^RenderPipelineDescriptor, payloadMemoryLength: NS.UInteger) { - msgSend(nil, self, "setPayloadMemoryLength:", payloadMemoryLength) -} -@(objc_type=RenderPipelineDescriptor, objc_name="maxTotalThreadgroupsPerMeshGrid") -RenderPipelineDescriptor_maxTotalThreadgroupsPerMeshGrid :: #force_inline proc "c" (self: ^RenderPipelineDescriptor) -> NS.UInteger { - return msgSend(NS.UInteger, self, "maxTotalThreadgroupsPerMeshGrid") -} -@(objc_type=RenderPipelineDescriptor, objc_name="setMaxTotalThreadgroupsPerMeshGrid") -RenderPipelineDescriptor_setMaxTotalThreadgroupsPerMeshGrid :: #force_inline proc "c" (self: ^RenderPipelineDescriptor, maxTotalThreadgroupsPerMeshGrid: NS.UInteger) { - msgSend(nil, self, "setMaxTotalThreadgroupsPerMeshGrid:", maxTotalThreadgroupsPerMeshGrid) -} - -@(objc_type=RenderPipelineDescriptor, objc_name="objectBuffers") -RenderPipelineDescriptor_objectBuffers :: #force_inline proc "c" (self: ^RenderPipelineDescriptor) -> ^PipelineBufferDescriptorArray { - return msgSend(^PipelineBufferDescriptorArray, self, "objectBuffers") -} -@(objc_type=RenderPipelineDescriptor, objc_name="meshBuffers") -RenderPipelineDescriptor_meshBuffers :: #force_inline proc "c" (self: ^RenderPipelineDescriptor) -> ^PipelineBufferDescriptorArray { - return msgSend(^PipelineBufferDescriptorArray, self, "meshBuffers") -} - - - @(objc_type=RenderPipelineDescriptor, objc_name="alphaToCoverageEnabled") RenderPipelineDescriptor_alphaToCoverageEnabled :: #force_inline proc "c" (self: ^RenderPipelineDescriptor) -> BOOL { return msgSend(BOOL, self, "alphaToCoverageEnabled") @@ -3034,6 +2962,272 @@ RenderPipelineDescriptor_rasterizationEnabled :: #force_inline proc "c" (self: ^ return msgSend(BOOL, self, "rasterizationEnabled") } +@(objc_type=RenderPipelineDescriptor, objc_name="shaderValidation") +RenderPipelineDescriptor_shaderValidation :: #force_inline proc "c" (self: ^RenderPipelineDescriptor) -> ShaderValidation { + return msgSend(ShaderValidation, self, "shaderValidation") +} +@(objc_type=RenderPipelineDescriptor, objc_name="setShaderValidation") +RenderPipelineDescriptor_setShaderValidation :: #force_inline proc "c" (self: ^RenderPipelineDescriptor, shaderValidation: ShaderValidation) { + msgSend(nil, self, "setShaderValidation:", shaderValidation) +} + + +//////////////////////////////////////////////////////////////////////////////// + + +@(objc_class="MTLMeshRenderPipelineDescriptor") +MeshRenderPipelineDescriptor :: struct{ using _: NS.Copying(MeshRenderPipelineDescriptor) } + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="alloc", objc_is_class_method=true) +MeshRenderPipelineDescriptor_alloc :: #force_inline proc "c" () -> ^MeshRenderPipelineDescriptor { + return msgSend(^MeshRenderPipelineDescriptor, MeshRenderPipelineDescriptor, "alloc") +} + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="init") +MeshRenderPipelineDescriptor_init :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> ^MeshRenderPipelineDescriptor { + return msgSend(^MeshRenderPipelineDescriptor, self, "init") +} + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="binaryArchives") +MeshRenderPipelineDescriptor_binaryArchives :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> ^NS.Array { + return msgSend(^NS.Array, self, "binaryArchives") +} +@(objc_type=MeshRenderPipelineDescriptor, objc_name="setBinaryArchives") +MeshRenderPipelineDescriptor_setBinaryArchives :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, binaryArchives: ^NS.Array) { + msgSend(nil, self, "setBinaryArchives:", binaryArchives) +} + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="colorAttachments") +MeshRenderPipelineDescriptor_colorAttachments :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> ^RenderPipelineColorAttachmentDescriptorArray { + return msgSend(^RenderPipelineColorAttachmentDescriptorArray, self, "colorAttachments") +} + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="depthAttachmentPixelFormat") +MeshRenderPipelineDescriptor_depthAttachmentPixelFormat :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> PixelFormat { + return msgSend(PixelFormat, self, "depthAttachmentPixelFormat") +} +@(objc_type=MeshRenderPipelineDescriptor, objc_name="setDepthAttachmentPixelFormat") +MeshRenderPipelineDescriptor_setDepthAttachmentPixelFormat :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, depthAttachmentPixelFormat: PixelFormat) { + msgSend(nil, self, "setDepthAttachmentPixelFormat:", depthAttachmentPixelFormat) +} + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="fragmentBuffers") +MeshRenderPipelineDescriptor_fragmentBuffers :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> ^PipelineBufferDescriptorArray { + return msgSend(^PipelineBufferDescriptorArray, self, "fragmentBuffers") +} + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="fragmentFunction") +MeshRenderPipelineDescriptor_fragmentFunction :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> ^Function { + return msgSend(^Function, self, "fragmentFunction") +} +@(objc_type=MeshRenderPipelineDescriptor, objc_name="setFragmentFunction") +MeshRenderPipelineDescriptor_setFragmentFunction :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, fragmentFunction: ^Function) { + msgSend(nil, self, "setFragmentFunction:", fragmentFunction) +} + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="fragmentLinkedFunctions") +MeshRenderPipelineDescriptor_fragmentLinkedFunctions :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> ^LinkedFunctions { + return msgSend(^LinkedFunctions, self, "fragmentLinkedFunctions") +} +@(objc_type=MeshRenderPipelineDescriptor, objc_name="setFragmentLinkedFunctions") +MeshRenderPipelineDescriptor_setFragmentLinkedFunctions :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, fragmentLinkedFunctions: ^LinkedFunctions) { + msgSend(nil, self, "setFragmentLinkedFunctions:", fragmentLinkedFunctions) +} + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="alphaToCoverageEnabled") +MeshRenderPipelineDescriptor_alphaToCoverageEnabled :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> BOOL { + return msgSend(BOOL, self, "alphaToCoverageEnabled") +} +@(objc_type=MeshRenderPipelineDescriptor, objc_name="isAlphaToCoverageEnabled") +MeshRenderPipelineDescriptor_isAlphaToCoverageEnabled :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> BOOL { + return msgSend(BOOL, self, "isAlphaToCoverageEnabled") +} +@(objc_type=MeshRenderPipelineDescriptor, objc_name="setAlphaToCoverageEnabled") +MeshRenderPipelineDescriptor_setAlphaToCoverageEnabled :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, alphaToCoverageEnabled: BOOL) { + msgSend(nil, self, "setAlphaToCoverageEnabled:", alphaToCoverageEnabled) +} + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="alphaToOneEnabled") +MeshRenderPipelineDescriptor_alphaToOneEnabled :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> BOOL { + return msgSend(BOOL, self, "alphaToOneEnabled") +} +@(objc_type=MeshRenderPipelineDescriptor, objc_name="isAlphaToOneEnabled") +MeshRenderPipelineDescriptor_isAlphaToOneEnabled :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> BOOL { + return msgSend(BOOL, self, "isAlphaToOneEnabled") +} +@(objc_type=MeshRenderPipelineDescriptor, objc_name="setAlphaToOneEnabled") +MeshRenderPipelineDescriptor_setAlphaToOneEnabled :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, alphaToOneEnabled: BOOL) { + msgSend(nil, self, "setAlphaToOneEnabled:", alphaToOneEnabled) +} + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="rasterizationEnabled") +MeshRenderPipelineDescriptor_rasterizationEnabled :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> BOOL { + return msgSend(BOOL, self, "rasterizationEnabled") +} +@(objc_type=MeshRenderPipelineDescriptor, objc_name="isRasterizationEnabled") +MeshRenderPipelineDescriptor_isRasterizationEnabled :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> BOOL { + return msgSend(BOOL, self, "isRasterizationEnabled") +} +@(objc_type=MeshRenderPipelineDescriptor, objc_name="setRasterizationEnabled") +MeshRenderPipelineDescriptor_setRasterizationEnabled :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, rasterizationEnabled: BOOL) { + msgSend(nil, self, "setRasterizationEnabled:", rasterizationEnabled) +} + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="label") +MeshRenderPipelineDescriptor_label :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> ^NS.String { + return msgSend(^NS.String, self, "label") +} + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="maxTotalThreadgroupsPerMeshGrid") +MeshRenderPipelineDescriptor_maxTotalThreadgroupsPerMeshGrid :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> NS.UInteger { + return msgSend(NS.UInteger, self, "maxTotalThreadgroupsPerMeshGrid") +} +@(objc_type=MeshRenderPipelineDescriptor, objc_name="setMaxTotalThreadgroupsPerMeshGrid") +MeshRenderPipelineDescriptor_setMaxTotalThreadgroupsPerMeshGrid :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, maxTotalThreadgroupsPerMeshGrid: NS.UInteger) { + msgSend(nil, self, "setMaxTotalThreadgroupsPerMeshGrid:", maxTotalThreadgroupsPerMeshGrid) +} + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="maxTotalThreadsPerMeshThreadgroup") +MeshRenderPipelineDescriptor_maxTotalThreadsPerMeshThreadgroup :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> NS.UInteger { + return msgSend(NS.UInteger, self, "maxTotalThreadsPerMeshThreadgroup") +} +@(objc_type=MeshRenderPipelineDescriptor, objc_name="setMaxTotalThreadsPerMeshThreadgroup") +MeshRenderPipelineDescriptor_setMaxTotalThreadsPerMeshThreadgroup :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, maxTotalThreadsPerMeshThreadgroup: NS.UInteger) { + msgSend(nil, self, "setMaxTotalThreadsPerMeshThreadgroup:", maxTotalThreadsPerMeshThreadgroup) +} + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="maxTotalThreadsPerObjectThreadgroup") +MeshRenderPipelineDescriptor_maxTotalThreadsPerObjectThreadgroup :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> NS.UInteger { + return msgSend(NS.UInteger, self, "maxTotalThreadsPerObjectThreadgroup") +} +@(objc_type=MeshRenderPipelineDescriptor, objc_name="setMaxTotalThreadsPerObjectThreadgroup") +MeshRenderPipelineDescriptor_setMaxTotalThreadsPerObjectThreadgroup :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, maxTotalThreadsPerObjectThreadgroup: NS.UInteger) { + msgSend(nil, self, "setMaxTotalThreadsPerObjectThreadgroup:", maxTotalThreadsPerObjectThreadgroup) +} + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="maxVertexAmplificationCount") +MeshRenderPipelineDescriptor_maxVertexAmplificationCount :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> NS.UInteger { + return msgSend(NS.UInteger, self, "maxVertexAmplificationCount") +} +@(objc_type=MeshRenderPipelineDescriptor, objc_name="setMaxVertexAmplificationCount") +MeshRenderPipelineDescriptor_setMaxVertexAmplificationCount :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, maxVertexAmplificationCount: NS.UInteger) { + msgSend(nil, self, "setMaxVertexAmplificationCount:", maxVertexAmplificationCount) +} + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="meshBuffers") +MeshRenderPipelineDescriptor_meshBuffers :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> ^PipelineBufferDescriptorArray { + return msgSend(^PipelineBufferDescriptorArray, self, "meshBuffers") +} + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="meshFunction") +MeshRenderPipelineDescriptor_meshFunction :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> ^Function { + return msgSend(^Function, self, "meshFunction") +} +@(objc_type=MeshRenderPipelineDescriptor, objc_name="setMeshFunction") +MeshRenderPipelineDescriptor_setMeshFunction :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, meshFunction: ^Function) { + msgSend(nil, self, "setMeshFunction:", meshFunction) +} + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="meshLinkedFunctions") +MeshRenderPipelineDescriptor_meshLinkedFunctions :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> ^LinkedFunctions { + return msgSend(^LinkedFunctions, self, "meshLinkedFunctions") +} +@(objc_type=MeshRenderPipelineDescriptor, objc_name="setMeshLinkedFunctions") +MeshRenderPipelineDescriptor_setMeshLinkedFunctions :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, meshLinkedFunctions: ^LinkedFunctions) { + msgSend(nil, self, "setMeshLinkedFunctions:", meshLinkedFunctions) +} + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="meshThreadgroupSizeIsMultipleOfThreadExecutionWidth") +MeshRenderPipelineDescriptor_meshThreadgroupSizeIsMultipleOfThreadExecutionWidth :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> BOOL { + return msgSend(BOOL, self, "meshThreadgroupSizeIsMultipleOfThreadExecutionWidth") +} +@(objc_type=MeshRenderPipelineDescriptor, objc_name="setMeshThreadgroupSizeIsMultipleOfThreadExecutionWidth") +MeshRenderPipelineDescriptor_setMeshThreadgroupSizeIsMultipleOfThreadExecutionWidth :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, meshThreadgroupSizeIsMultipleOfThreadExecutionWidth: BOOL) { + msgSend(nil, self, "setMeshThreadgroupSizeIsMultipleOfThreadExecutionWidth:", meshThreadgroupSizeIsMultipleOfThreadExecutionWidth) +} + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="objectBuffers") +MeshRenderPipelineDescriptor_objectBuffers :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> ^PipelineBufferDescriptorArray { + return msgSend(^PipelineBufferDescriptorArray, self, "objectBuffers") +} + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="objectFunction") +MeshRenderPipelineDescriptor_objectFunction :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> ^Function { + return msgSend(^Function, self, "objectFunction") +} +@(objc_type=MeshRenderPipelineDescriptor, objc_name="setObjectFunction") +MeshRenderPipelineDescriptor_setObjectFunction :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, objectFunction: ^Function) { + msgSend(nil, self, "setObjectFunction:", objectFunction) +} + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="objectLinkedFunctions") +MeshRenderPipelineDescriptor_objectLinkedFunctions :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> ^LinkedFunctions { + return msgSend(^LinkedFunctions, self, "objectLinkedFunctions") +} +@(objc_type=MeshRenderPipelineDescriptor, objc_name="setObjectLinkedFunctions") +MeshRenderPipelineDescriptor_setObjectLinkedFunctions :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, objectLinkedFunctions: ^LinkedFunctions) { + msgSend(nil, self, "setObjectLinkedFunctions:", objectLinkedFunctions) +} + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="objectThreadgroupSizeIsMultipleOfThreadExecutionWidth") +MeshRenderPipelineDescriptor_objectThreadgroupSizeIsMultipleOfThreadExecutionWidth :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> BOOL { + return msgSend(BOOL, self, "objectThreadgroupSizeIsMultipleOfThreadExecutionWidth") +} +@(objc_type=MeshRenderPipelineDescriptor, objc_name="setObjectThreadgroupSizeIsMultipleOfThreadExecutionWidth") +MeshRenderPipelineDescriptor_setObjectThreadgroupSizeIsMultipleOfThreadExecutionWidth :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, objectThreadgroupSizeIsMultipleOfThreadExecutionWidth: BOOL) { + msgSend(nil, self, "setObjectThreadgroupSizeIsMultipleOfThreadExecutionWidth:", objectThreadgroupSizeIsMultipleOfThreadExecutionWidth) +} + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="payloadMemoryLength") +MeshRenderPipelineDescriptor_payloadMemoryLength :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> NS.UInteger { + return msgSend(NS.UInteger, self, "payloadMemoryLength") +} +@(objc_type=MeshRenderPipelineDescriptor, objc_name="setPayloadMemoryLength") +MeshRenderPipelineDescriptor_setPayloadMemoryLength :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, payloadMemoryLength: NS.UInteger) { + msgSend(nil, self, "setPayloadMemoryLength:", payloadMemoryLength) +} + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="rasterSampleCount") +MeshRenderPipelineDescriptor_rasterSampleCount :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> NS.UInteger { + return msgSend(NS.UInteger, self, "rasterSampleCount") +} +@(objc_type=MeshRenderPipelineDescriptor, objc_name="setRasterSampleCount") +MeshRenderPipelineDescriptor_setRasterSampleCount :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, rasterSampleCount: NS.UInteger) { + msgSend(nil, self, "setRasterSampleCount:", rasterSampleCount) +} + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="shaderValidation") +MeshRenderPipelineDescriptor_shaderValidation :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> ShaderValidation { + return msgSend(ShaderValidation, self, "shaderValidation") +} +@(objc_type=MeshRenderPipelineDescriptor, objc_name="setShaderValidation") +MeshRenderPipelineDescriptor_setShaderValidation :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, shaderValidation: ShaderValidation) { + msgSend(nil, self, "setShaderValidation:", shaderValidation) +} + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="stencilAttachmentPixelFormat") +MeshRenderPipelineDescriptor_stencilAttachmentPixelFormat :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> PixelFormat { + return msgSend(PixelFormat, self, "stencilAttachmentPixelFormat") +} +@(objc_type=MeshRenderPipelineDescriptor, objc_name="setStencilAttachmentPixelFormat") +MeshRenderPipelineDescriptor_setStencilAttachmentPixelFormat :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, stencilAttachmentPixelFormat: PixelFormat) { + msgSend(nil, self, "setStencilAttachmentPixelFormat:", stencilAttachmentPixelFormat) +} + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="supportIndirectCommandBuffers") +MeshRenderPipelineDescriptor_supportIndirectCommandBuffers :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) -> BOOL { + return msgSend(BOOL, self, "supportIndirectCommandBuffers") +} +@(objc_type=MeshRenderPipelineDescriptor, objc_name="setSupportIndirectCommandBuffers") +MeshRenderPipelineDescriptor_setSupportIndirectCommandBuffers :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor, supportIndirectCommandBuffers: BOOL) { + msgSend(nil, self, "setSupportIndirectCommandBuffers:", supportIndirectCommandBuffers) +} + +@(objc_type=MeshRenderPipelineDescriptor, objc_name="reset") +MeshRenderPipelineDescriptor_reset :: #force_inline proc "c" (self: ^MeshRenderPipelineDescriptor) { + msgSend(nil, self, "reset") +} + //////////////////////////////////////////////////////////////////////////////// @@ -5702,14 +5896,13 @@ Device_supportsVertexAmplificationCount :: #force_inline proc "c" (self: ^Device @(objc_type=Device, objc_name="newRenderPipelineStateWithMeshDescriptor") -Device_newRenderPipelineStateWithMeshDescriptor :: #force_inline proc "contextless" (self: ^Device, options: PipelineOption, reflection: ^AutoreleasedRenderPipelineReflection) -> (state: ^RenderPipelineState, error: ^NS.Error) { - state = msgSend(^RenderPipelineState, self, "newRenderPipelineStateWithMeshDescriptor:options:reflection:error:", options, reflection, &error) +Device_newRenderPipelineStateWithMeshDescriptor :: #force_inline proc "c" (self: ^Device, descriptor: ^MeshRenderPipelineDescriptor, options: PipelineOption, reflection: ^AutoreleasedRenderPipelineReflection) -> (state: ^RenderPipelineState, error: ^NS.Error) { + state = msgSend(^RenderPipelineState, self, "newRenderPipelineStateWithMeshDescriptor:options:reflection:error:", descriptor, options, reflection, &error) return } @(objc_type=Device, objc_name="newRenderPipelineStateWithMeshDescriptorAndCompletionHandler") -Device_newRenderPipelineStateWithMeshDescriptorAndCompletionHandler :: #force_inline proc "c" (self: ^Device, options: PipelineOption, completionHandler: ^NewRenderPipelineStateWithReflectionCompletionHandler) -> (state: ^RenderPipelineState) { - state = msgSend(^RenderPipelineState, self, "newRenderPipelineStateWithMeshDescriptor:options:completionHandler:", options, completionHandler) - return +Device_newRenderPipelineStateWithMeshDescriptorAndCompletionHandler :: #force_inline proc "c" (self: ^Device, descriptor: ^MeshRenderPipelineDescriptor, options: PipelineOption, completionHandler: NewRenderPipelineStateWithReflectionCompletionHandler) { + msgSend(nil, self, "newRenderPipelineStateWithMeshDescriptor:options:completionHandler:", descriptor, options, completionHandler) } @(objc_type=Device, objc_name="newIOHandle") diff --git a/vendor/darwin/Metal/MetalEnums.odin b/vendor/darwin/Metal/MetalEnums.odin index 5cef5f18d..7d4e86d65 100644 --- a/vendor/darwin/Metal/MetalEnums.odin +++ b/vendor/darwin/Metal/MetalEnums.odin @@ -1050,3 +1050,9 @@ VertexStepFunction :: enum NS.UInteger { PerPatch = 3, PerPatchControlPoint = 4, } + +ShaderValidation :: enum NS.UInteger { + Default = 0, + Enabled = 1, + Disabled = 2, +} From 5a998d44d4007e9edf43b8310794471b857d4e4a Mon Sep 17 00:00:00 2001 From: Tohei Ichikawa Date: Thu, 7 Aug 2025 00:25:36 -0400 Subject: [PATCH 021/105] Add bindings for vertexLinkedFunctions --- vendor/darwin/Metal/MetalClasses.odin | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/vendor/darwin/Metal/MetalClasses.odin b/vendor/darwin/Metal/MetalClasses.odin index ef57be0b4..a4c7b43f2 100644 --- a/vendor/darwin/Metal/MetalClasses.odin +++ b/vendor/darwin/Metal/MetalClasses.odin @@ -2767,6 +2767,10 @@ RenderPipelineDescriptor_fragmentBuffers :: #force_inline proc "c" (self: ^Rende RenderPipelineDescriptor_fragmentFunction :: #force_inline proc "c" (self: ^RenderPipelineDescriptor) -> ^Function { return msgSend(^Function, self, "fragmentFunction") } +@(objc_type=RenderPipelineDescriptor, objc_name="vertexLinkedFunctions") +RenderPipelineDescriptor_vertexLinkedFunctions :: #force_inline proc "c" (self: ^RenderPipelineDescriptor) -> ^LinkedFunctions { + return msgSend(^LinkedFunctions, self, "vertexLinkedFunctions") +} @(objc_type=RenderPipelineDescriptor, objc_name="fragmentLinkedFunctions") RenderPipelineDescriptor_fragmentLinkedFunctions :: #force_inline proc "c" (self: ^RenderPipelineDescriptor) -> ^LinkedFunctions { return msgSend(^LinkedFunctions, self, "fragmentLinkedFunctions") @@ -2835,6 +2839,10 @@ RenderPipelineDescriptor_setDepthAttachmentPixelFormat :: #force_inline proc "c" RenderPipelineDescriptor_setFragmentFunction :: #force_inline proc "c" (self: ^RenderPipelineDescriptor, fragmentFunction: ^Function) { msgSend(nil, self, "setFragmentFunction:", fragmentFunction) } +@(objc_type=RenderPipelineDescriptor, objc_name="setVertexLinkedFunctions") +RenderPipelineDescriptor_setVertexLinkedFunctions :: #force_inline proc "c" (self: ^RenderPipelineDescriptor, vertexLinkedFunctions: ^LinkedFunctions) { + msgSend(nil, self, "setVertexLinkedFunctions:", vertexLinkedFunctions) +} @(objc_type=RenderPipelineDescriptor, objc_name="setFragmentLinkedFunctions") RenderPipelineDescriptor_setFragmentLinkedFunctions :: #force_inline proc "c" (self: ^RenderPipelineDescriptor, fragmentLinkedFunctions: ^LinkedFunctions) { msgSend(nil, self, "setFragmentLinkedFunctions:", fragmentLinkedFunctions) From 34b4b84b644c726869b863278f22f223d65e45af Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 7 Aug 2025 12:34:41 +0100 Subject: [PATCH 022/105] Add `intrinsics.type_canonical_name` --- base/intrinsics/intrinsics.odin | 3 +++ src/check_builtin.cpp | 16 ++++++++++++++++ src/checker_builtin_procs.hpp | 3 +++ 3 files changed, 22 insertions(+) diff --git a/base/intrinsics/intrinsics.odin b/base/intrinsics/intrinsics.odin index d45d24f48..c008321f0 100644 --- a/base/intrinsics/intrinsics.odin +++ b/base/intrinsics/intrinsics.odin @@ -233,6 +233,9 @@ type_integer_to_signed :: proc($T: typeid) -> type where type_is_integer(T), t type_has_shared_fields :: proc($U, $V: typeid) -> bool where type_is_struct(U), type_is_struct(V) --- +// Returns the canonicalized name of the type, of which is used to produce the pseudo-unique 'typeid' +type_canonical_name :: proc($T: typeid) -> string --- + constant_utf16_cstring :: proc($literal: string) -> [^]u16 --- constant_log2 :: proc($v: $T) -> T where type_is_integer(T) --- diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index 57413f519..18c75c455 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -7134,6 +7134,22 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As break; } + case BuiltinProc_type_canonical_name: + { + Operand op = {}; + Type *type = check_type(c, ce->args[0]); + Type *bt = base_type(type); + if (bt == nullptr || bt == t_invalid) { + error(ce->args[0], "Expected a type for '%.*s'", LIT(builtin_name)); + return false; + } + + operand->mode = Addressing_Constant; + operand->type = t_untyped_string; + operand->value = type_to_canonical_string(permanent_allocator(), type); + break; + } + case BuiltinProc_procedure_of: { Ast *call_expr = unparen_expr(ce->args[0]); diff --git a/src/checker_builtin_procs.hpp b/src/checker_builtin_procs.hpp index b8b105fd2..29b12ba1c 100644 --- a/src/checker_builtin_procs.hpp +++ b/src/checker_builtin_procs.hpp @@ -339,6 +339,8 @@ BuiltinProc__type_simple_boolean_end, BuiltinProc_type_has_shared_fields, + BuiltinProc_type_canonical_name, + BuiltinProc__type_end, BuiltinProc_procedure_of, @@ -697,6 +699,7 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = { {STR_LIT("type_map_cell_info"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT("type_has_shared_fields"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics}, + {STR_LIT("type_canonical_name"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics}, {STR_LIT(""), 0, false, Expr_Stmt, BuiltinProcPkg_intrinsics}, From 3de300d2f936a3702b73dabce9e877756892646f Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 7 Aug 2025 12:38:15 +0100 Subject: [PATCH 023/105] Fix typo --- src/check_builtin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index 18c75c455..0daf101b7 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -7146,7 +7146,7 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As operand->mode = Addressing_Constant; operand->type = t_untyped_string; - operand->value = type_to_canonical_string(permanent_allocator(), type); + operand->value = exact_value_string(type_to_canonical_string(permanent_allocator(), type)); break; } From 1470c300c7b729ea58df5cd6ac2cfd2006389660 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 7 Aug 2025 12:45:59 +0100 Subject: [PATCH 024/105] Add support for `[dynamic]T` in `.raddbg` --- src/llvm_backend.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index f37415cc1..fd3701108 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -3374,8 +3374,9 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { LLVMModuleRef mod = m->mod; LLVMContextRef ctx = m->ctx; - lb_add_raddbg_string(m, "type_view: {type: \"[]?\", expr: \"array(data, len)\"}"); - lb_add_raddbg_string(m, "type_view: {type: \"string\", expr: \"array(data, len)\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"[]?\", expr: \"array(data, len)\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"string\", expr: \"array(data, len)\"}"); + lb_add_raddbg_string(m, "type_view: {type: \"[dynamic]?\", expr: \"rows($, array(data, len), len, cap, allocator)\"}"); // column major matrices lb_add_raddbg_string(m, "type_view: {type: \"matrix[1, ?]?\", expr: \"columns($.data, $[0])\"}"); From 3a1171e25f604e5978a3da303ae9caed44a44ac3 Mon Sep 17 00:00:00 2001 From: connnnal <216976529+connnnal@users.noreply.github.com> Date: Thu, 7 Aug 2025 13:15:12 +0100 Subject: [PATCH 025/105] Alias [^]u16 to Windows LPCWSTR --- vendor/directx/d3d11/d3d11.odin | 2 +- vendor/directx/d3d12/d3d12.odin | 38 +++++++++++++++++---------------- 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/vendor/directx/d3d11/d3d11.odin b/vendor/directx/d3d11/d3d11.odin index bb91e87ce..c15f19934 100644 --- a/vendor/directx/d3d11/d3d11.odin +++ b/vendor/directx/d3d11/d3d11.odin @@ -19,7 +19,7 @@ BOOL :: dxgi.BOOL UINT :: dxgi.UINT INT :: dxgi.INT -LPCWSTR :: [^]u16 +LPCWSTR :: windows.LPCWSTR RECT :: dxgi.RECT SIZE :: dxgi.SIZE diff --git a/vendor/directx/d3d12/d3d12.odin b/vendor/directx/d3d12/d3d12.odin index 9cb1eec48..2bfd4de4f 100644 --- a/vendor/directx/d3d12/d3d12.odin +++ b/vendor/directx/d3d12/d3d12.odin @@ -22,6 +22,8 @@ BOOL :: dxgi.BOOL RECT :: dxgi.RECT +LPCWSTR :: win32.LPCWSTR + IModuleInstance :: d3d_compiler.ID3D11ModuleInstance IBlob :: d3d_compiler.ID3DBlob IModule :: d3d_compiler.ID3D11Module @@ -680,7 +682,7 @@ IObject_VTable :: struct { GetPrivateData: proc "system" (this: ^IObject, guid: ^GUID, pDataSize: ^u32, pData: rawptr) -> HRESULT, SetPrivateData: proc "system" (this: ^IObject, guid: ^GUID, DataSize: u32, pData: rawptr) -> HRESULT, SetPrivateDataInterface: proc "system" (this: ^IObject, guid: ^GUID, pData: ^IUnknown) -> HRESULT, - SetName: proc "system" (this: ^IObject, Name: [^]u16) -> HRESULT, + SetName: proc "system" (this: ^IObject, Name: LPCWSTR) -> HRESULT, } @@ -2714,9 +2716,9 @@ IDevice_VTable :: struct { CreateHeap: proc "system" (this: ^IDevice, pDesc: ^HEAP_DESC, riid: ^IID, ppvHeap: ^rawptr) -> HRESULT, CreatePlacedResource: proc "system" (this: ^IDevice, pHeap: ^IHeap, HeapOffset: u64, pDesc: ^RESOURCE_DESC, InitialState: RESOURCE_STATES, pOptimizedClearValue: ^CLEAR_VALUE, riid: ^IID, ppvResource: ^rawptr) -> HRESULT, CreateReservedResource: proc "system" (this: ^IDevice, pDesc: ^RESOURCE_DESC, InitialState: RESOURCE_STATES, pOptimizedClearValue: ^CLEAR_VALUE, riid: ^IID, ppvResource: ^rawptr) -> HRESULT, - CreateSharedHandle: proc "system" (this: ^IDevice, pObject: ^IDeviceChild, pAttributes: ^win32.SECURITY_ATTRIBUTES, Access: u32, Name: [^]u16, pHandle: ^HANDLE) -> HRESULT, + CreateSharedHandle: proc "system" (this: ^IDevice, pObject: ^IDeviceChild, pAttributes: ^win32.SECURITY_ATTRIBUTES, Access: u32, Name: LPCWSTR, pHandle: ^HANDLE) -> HRESULT, OpenSharedHandle: proc "system" (this: ^IDevice, NTHandle: HANDLE, riid: ^IID, ppvObj: ^rawptr) -> HRESULT, - OpenSharedHandleByName: proc "system" (this: ^IDevice, Name: [^]u16, Access: u32, pNTHandle: ^HANDLE) -> HRESULT, + OpenSharedHandleByName: proc "system" (this: ^IDevice, Name: LPCWSTR, Access: u32, pNTHandle: ^HANDLE) -> HRESULT, MakeResident: proc "system" (this: ^IDevice, NumObjects: u32, ppObjects: [^]^IPageable) -> HRESULT, Evict: proc "system" (this: ^IDevice, NumObjects: u32, ppObjects: [^]^IPageable) -> HRESULT, CreateFence: proc "system" (this: ^IDevice, InitialValue: u64, Flags: FENCE_FLAGS, riid: ^IID, ppFence: ^rawptr) -> HRESULT, @@ -2738,9 +2740,9 @@ IPipelineLibrary :: struct #raw_union { } IPipelineLibrary_VTable :: struct { using id3d12devicechild_vtable: IDeviceChild_VTable, - StorePipeline: proc "system" (this: ^IPipelineLibrary, pName: [^]u16, pPipeline: ^IPipelineState) -> HRESULT, - LoadGraphicsPipeline: proc "system" (this: ^IPipelineLibrary, pName: [^]u16, pDesc: ^GRAPHICS_PIPELINE_STATE_DESC, riid: ^IID, ppPipelineState: ^rawptr) -> HRESULT, - LoadComputePipeline: proc "system" (this: ^IPipelineLibrary, pName: [^]u16, pDesc: ^COMPUTE_PIPELINE_STATE_DESC, riid: ^IID, ppPipelineState: ^rawptr) -> HRESULT, + StorePipeline: proc "system" (this: ^IPipelineLibrary, pName: LPCWSTR, pPipeline: ^IPipelineState) -> HRESULT, + LoadGraphicsPipeline: proc "system" (this: ^IPipelineLibrary, pName: LPCWSTR, pDesc: ^GRAPHICS_PIPELINE_STATE_DESC, riid: ^IID, ppPipelineState: ^rawptr) -> HRESULT, + LoadComputePipeline: proc "system" (this: ^IPipelineLibrary, pName: LPCWSTR, pDesc: ^COMPUTE_PIPELINE_STATE_DESC, riid: ^IID, ppPipelineState: ^rawptr) -> HRESULT, GetSerializedSize: proc "system" (this: ^IPipelineLibrary) -> SIZE_T, Serialize: proc "system" (this: ^IPipelineLibrary, pData: rawptr, DataSizeInBytes: SIZE_T) -> HRESULT, } @@ -2754,7 +2756,7 @@ IPipelineLibrary1 :: struct #raw_union { } IPipelineLibrary1_VTable :: struct { using id3d12pipelinelibrary_vtable: IPipelineLibrary_VTable, - LoadPipeline: proc "system" (this: ^IPipelineLibrary1, pName: [^]u16, pDesc: ^PIPELINE_STATE_STREAM_DESC, riid: ^IID, ppPipelineState: ^rawptr) -> HRESULT, + LoadPipeline: proc "system" (this: ^IPipelineLibrary1, pName: LPCWSTR, pDesc: ^PIPELINE_STATE_STREAM_DESC, riid: ^IID, ppPipelineState: ^rawptr) -> HRESULT, } MULTIPLE_FENCE_WAIT_FLAGS :: distinct bit_set[MULTIPLE_FENCE_WAIT_FLAG; u32] @@ -2961,7 +2963,7 @@ META_COMMAND_PARAMETER_STAGE :: enum i32 { } META_COMMAND_PARAMETER_DESC :: struct { - Name: [^]u16, + Name: LPCWSTR, Type: META_COMMAND_PARAMETER_TYPE, Flags: META_COMMAND_PARAMETER_FLAGS, RequiredResourceState: RESOURCE_STATES, @@ -2991,7 +2993,7 @@ GRAPHICS_STATES :: enum i32 { META_COMMAND_DESC :: struct { Id: GUID, - Name: [^]u16, + Name: LPCWSTR, InitializationDirtyState: GRAPHICS_STATES, ExecutionDirtyState: GRAPHICS_STATES, } @@ -3012,8 +3014,8 @@ IStateObjectProperties :: struct #raw_union { } IStateObjectProperties_VTable :: struct { using iunknown_vtable: IUnknown_VTable, - GetShaderIdentifier: proc "system" (this: ^IStateObjectProperties, pExportName: [^]u16) -> rawptr, - GetShaderStackSize: proc "system" (this: ^IStateObjectProperties, pExportName: [^]u16) -> u64, + GetShaderIdentifier: proc "system" (this: ^IStateObjectProperties, pExportName: LPCWSTR) -> rawptr, + GetShaderStackSize: proc "system" (this: ^IStateObjectProperties, pExportName: LPCWSTR) -> u64, GetPipelineStackSize: proc "system" (this: ^IStateObjectProperties) -> u64, SetPipelineStackSize: proc "system" (this: ^IStateObjectProperties, PipelineStackSizeInBytes: u64), } @@ -3067,8 +3069,8 @@ EXPORT_FLAG :: enum u32 { } EXPORT_DESC :: struct { - Name: [^]u16, - ExportToRename: [^]u16, + Name: LPCWSTR, + ExportToRename: LPCWSTR, Flags: EXPORT_FLAGS, } @@ -3414,9 +3416,9 @@ AUTO_BREADCRUMB_OP :: enum i32 { AUTO_BREADCRUMB_NODE :: struct { pCommandListDebugNameA: cstring, - pCommandListDebugNameW: [^]u16, + pCommandListDebugNameW: LPCWSTR, pCommandQueueDebugNameA: cstring, - pCommandQueueDebugNameW: [^]u16, + pCommandQueueDebugNameW: LPCWSTR, pCommandList: ^IGraphicsCommandList, pCommandQueue: ^ICommandQueue, BreadcrumbCount: u32, @@ -3427,14 +3429,14 @@ AUTO_BREADCRUMB_NODE :: struct { DRED_BREADCRUMB_CONTEXT :: struct { BreadcrumbIndex: u32, - pContextString: [^]u16, + pContextString: LPCWSTR, } AUTO_BREADCRUMB_NODE1 :: struct { pCommandListDebugNameA: cstring, - pCommandListDebugNameW: [^]u16, + pCommandListDebugNameW: LPCWSTR, pCommandQueueDebugNameA: cstring, - pCommandQueueDebugNameW: [^]u16, + pCommandQueueDebugNameW: LPCWSTR, pCommandList: ^IGraphicsCommandList, pCommandQueue: ^ICommandQueue, BreadcrumbCount: u32, From 46b7abee9fdd339bac31fe7bc79551f2b3881f46 Mon Sep 17 00:00:00 2001 From: Sunagatov Denis Date: Fri, 8 Aug 2025 03:18:57 +1100 Subject: [PATCH 026/105] Fix ICE on missing procedure in base:runtime When a required built-in procedure is missing from the base:runtime package, an assert should be triggered. However this does not happen and instead the compiler crashes silently. The cause is the null-dereference after scope_lookup_current returns nullptr. This adds an assertion that the runtime procedure is found, before proceeding to check it's type and performing further lookups. --- src/llvm_backend_general.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp index 5d6a55973..67e799918 100644 --- a/src/llvm_backend_general.cpp +++ b/src/llvm_backend_general.cpp @@ -2792,6 +2792,7 @@ gb_internal lbValue lb_find_ident(lbProcedure *p, lbModule *m, Entity *e, Ast *e gb_internal lbValue lb_find_procedure_value_from_entity(lbModule *m, Entity *e) { lbGenerator *gen = m->gen; + GB_ASSERT(e != nullptr); GB_ASSERT(is_type_proc(e->type)); e = strip_entity_wrapping(e); GB_ASSERT(e != nullptr); From b6944b8acb55c090d68d77014017282f0f4df9fb Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 7 Aug 2025 17:53:54 +0100 Subject: [PATCH 027/105] Fix instantiation of package for parapoly records --- src/check_type.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/check_type.cpp b/src/check_type.cpp index 79705b928..a427a1927 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -286,9 +286,20 @@ gb_internal GenTypesData *ensure_polymorphic_record_entity_has_gen_types(Checker gb_internal void add_polymorphic_record_entity(CheckerContext *ctx, Ast *node, Type *named_type, Type *original_type) { GB_ASSERT(is_type_named(named_type)); + GB_ASSERT(original_type->kind == Type_Named); gbAllocator a = heap_allocator(); Scope *s = ctx->scope->parent; + AstPackage *pkg = nullptr; + if (original_type->Named.type_name && original_type->Named.type_name->pkg) { + pkg = original_type->Named.type_name->pkg; + } + + if (pkg == nullptr) { + // NOTE(bill): if the `pkg` cannot be determined, default to the current context's pkg instead + pkg = ctx->pkg; + } + Entity *e = nullptr; { Token token = ast_token(node); @@ -300,12 +311,11 @@ gb_internal void add_polymorphic_record_entity(CheckerContext *ctx, Ast *node, T e = alloc_entity_type_name(s, token, named_type); e->state = EntityState_Resolved; e->file = ctx->file; - e->pkg = ctx->pkg; + e->pkg = pkg; add_entity_use(ctx, node, e); } named_type->Named.type_name = e; - GB_ASSERT(original_type->kind == Type_Named); e->TypeName.objc_class_name = original_type->Named.type_name->TypeName.objc_class_name; // TODO(bill): Is this even correct? Or should the metadata be copied? e->TypeName.objc_metadata = original_type->Named.type_name->TypeName.objc_metadata; From c22da490b9416b242235a1748d3aa2d4c9fde539 Mon Sep 17 00:00:00 2001 From: Sunagatov Denis Date: Fri, 8 Aug 2025 04:56:59 +1100 Subject: [PATCH 028/105] Print the name of missing runtime procedure This continues the fix made at 46b7abee9fdd339bac31fe7bc79551f2b3881f46, by asserting on missing entity early and printing it's name if its not found. --- src/llvm_backend_proc.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index c95bb0c29..04dcc6662 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -985,6 +985,7 @@ gb_internal lbValue lb_emit_call_internal(lbProcedure *p, lbValue value, lbValue gb_internal lbValue lb_lookup_runtime_procedure(lbModule *m, String const &name) { AstPackage *pkg = m->info->runtime_package; Entity *e = scope_lookup_current(pkg->scope, name); + GB_ASSERT_MSG(e != nullptr, "Runtime procedure not found: %s", name); return lb_find_procedure_value_from_entity(m, e); } From e6635e2508339634921198d4adf9aa9dee418403 Mon Sep 17 00:00:00 2001 From: Sunagatov Denis Date: Fri, 8 Aug 2025 05:45:39 +1100 Subject: [PATCH 029/105] Update runtime doc file This updates and reformats the doc file for the runtime package. The list of things that need to be implemented for a compiler runtime to work has been updated in accordance with recent changes to runtime (notably `cstring16` and `string16` types and `#load_directory`). Some copy-paste errors around string-comparison procedures have been fixed. The file has been renamed to `doc.odin` as per convention, the comment has been moved to the top of the package declaration and the comment is now markdown-formatted. Also wrote down a little map to maybe slightly help with understanding navigation within package runtime's files and added a few more explanations as to why that list of declarations exists and how to use it. The list of declarations has been detailed to some degree, explaining under what conditions the declarations are required. --- base/runtime/doc.odin | 244 +++++++++++++++++++++++++++++++++++++++++ base/runtime/docs.odin | 180 ------------------------------ 2 files changed, 244 insertions(+), 180 deletions(-) create mode 100644 base/runtime/doc.odin delete mode 100644 base/runtime/docs.odin diff --git a/base/runtime/doc.odin b/base/runtime/doc.odin new file mode 100644 index 000000000..7369e36b5 --- /dev/null +++ b/base/runtime/doc.odin @@ -0,0 +1,244 @@ + +/* +Declarations which are required by the compiler + +## Descriptions of files + +There are a lot of files in this package and below is described roughly what +kind of functionality is placed in different files: + +| File pattern | Description +|----------------------|------------------------------------------------------| +| `core.odin` | Contains the declarations that compiler will require to be present. Contains context-related declarations, `Type_Info` declarations and some other types used to implement the runtime and other packages. | +| `core_builtin*.odin` | Contain `@(builtin)` declarations that can be used without importing the package. Most of them aren't required by the compiler | +| `default_*.odin` | Contain default implementations for context allocators | +| `entry_*.odin` | Contain OS-specific entry points | +| `os_specific_*.odin` | Contain OS-specific utility procedures | +| `*internal*.odin` | Contain implementations for internal procedures that can be called by the compiler | + +## Implementing custom runtime + +For embedded and kernel development it might be required to re-implement parts +of the `base:runtime` package. This can include changing the default printing +procedures that handle console output when the program panics, custom +entry-points, tailored for a specific platform or execution environment, or +simply switching up implementations of some procedures. + +In case this is required, the following is suggested: + +1. Define `$ODIN_ROOT` environment variable to point to a directory within your + project that contains the following directories: `base/`, `core/` and `vendor/`. +2. Inside the `$ODIN_ROOT/base` subdirectory, implement the *necessary + declarations*. + +What constitutes the necessary definitions is described below. + +### Context-related + +The compiler will require these declarations as they concern the `context` +variable. + +* `Maybe` +* `Source_Code_Location` +* `Context` +* `Allocator` +* `Random_Generator` +* `Logger` +* `__init_context` + +### Runtime initialization/cleanup + +These are not strictly required for compilation, but if global variables or +`@(init)`/`@(fini)` blocks are used, these procedures need to be called inside +the entry point. + +* `_startup_runtime` +* `_cleanup_runtime` + +### Type assertion check + +These procedures are called every time `.(Type)` expressions are used in order +to check the union tag or the underlying type of `any` before returning the +value of the underlying type. These are not required if `-no-type-assert` is +specified. + +* `type_assertion_check` +* `type_assertion_check2` (takes in typeid) + +### Bounds checking procedures + +These procedures are called every time index or slicing expression are used in +order to perform bounds-checking before the actual operation. These are not +required if the `-no-bounds-check` option is specified. + +* `bounds_check_error` +* `matrix_bounds_check_error` +* `slice_expr_error_hi` +* `slice_expr_error_lo_hi` +* `multi_pointer_slice_expr_error` + +### cstring calls + +If `cstring` or `cstring16` types are used, these procedures are required. + +* `cstring_to_string` +* `cstring_len` +* `cstring16_to_string16` +* `cstring16_len` + +### Comparison + +These procedures are required for comparison operators between strings and other +compound types to function properly. If strings, structs nor unions are compared, +only `string_eq` procedure is required. + +* `memory_equal` +* `memory_compare` +* `memory_compare_zero` +* `cstring_eq` +* `cstring16_eq` +* `cstring_ne` +* `cstring16_ne` +* `cstring_lt` +* `cstring16_lt` +* `cstring_gt` +* `cstring16_gt` +* `cstring_le` +* `cstring16_le` +* `cstring_ge` +* `cstring16_ge` +* `string_eq` +* `string16_eq` +* `string_ne` +* `string16_ne` +* `string_lt` +* `string16_lt` +* `string_gt` +* `string16_gt` +* `string_le` +* `string16_le` +* `string_ge` +* `string16_ge` +* `complex32_eq` +* `complex32_ne` +* `complex64_eq` +* `complex64_ne` +* `complex128_eq` +* `complex128_ne` +* `quaternion64_eq` +* `quaternion64_ne` +* `quaternion128_eq` +* `quaternion128_ne` +* `quaternion256_eq` +* `quaternion256_ne` + +### for-in `string` type + +These procedures are required to iterate strings using `for ... in` loop. If this +kind of loop isn't used, these procedures aren't required. + +* `string_decode_rune` +* `string_decode_last_rune` (for `#reverse for`) + +### Required when RTTI is enabled (the vast majority of targets) + +These declarations are required unless the `-no-rtti` compiler option is +specified. Note that in order to be useful, some other procedures need to be +implemented. Those procedures aren't mentioned here as the compiler won't +complain if they're missing. + +* `Type_Info` +* `type_table` +* `__type_info_of` + +### Hashing + +Required if maps are used + +* `default_hasher` +* `default_hasher_cstring` +* `default_hasher_string` + +### Pseudo-CRT required procedured due to LLVM but useful in general + +* `memset` +* `memcpy` +* `memove` + +### Procedures required by the LLVM backend if u128/i128 is used + +* `umodti3` +* `udivti3` +* `modti3` +* `divti3` +* `fixdfti` +* `fixunsdfti` +* `fixunsdfdi` +* `floattidf` +* `floattidf_unsigned` +* `truncsfhf2` +* `truncdfhf2` +* `gnu_h2f_ieee` +* `gnu_f2h_ieee` +* `extendhfsf2` + +### Procedures required by the LLVM backend if f16 is used (WASM only) + +* `__ashlti3` +* `__multi3` + +### When -no-crt is defined (windows only) + +* `_tls_index` +* `_fltused` + +### Arithmetic + +* `quo_complex32` +* `quo_complex64` +* `quo_complex128` + +* `mul_quaternion64` +* `mul_quaternion128` +* `mul_quaternion256` + +* `quo_quaternion64` +* `quo_quaternion128` +* `quo_quaternion256` + +* `abs_complex32` +* `abs_complex64` +* `abs_complex128` + +* `abs_quaternion64` +* `abs_quaternion128` +* `abs_quaternion256` + +## Map specific calls + +* `map_seed_from_map_data` +* `__dynamic_map_check_grow` (for static map calls) +* `map_insert_hash_dynamic` (for static map calls) +* `__dynamic_map_get` (for dynamic map calls) +* `__dynamic_map_set` (for dynamic map calls) + +## Dynamic literals (`[dynamic]T` and `map[K]V`) (can be disabled with `-no-dynamic-literals`) + +* `__dynamic_array_reserve` +* `__dynamic_array_append` +* `__dynamic_map_reserve` + +### Objective-C specific + +* `objc_lookUpClass` +* `sel_registerName` +* `objc_allocateClassPair` + +### Other required declarations + +This is required without conditions. + +* `Load_Directory_File` + +*/ +package runtime diff --git a/base/runtime/docs.odin b/base/runtime/docs.odin deleted file mode 100644 index f6b439aa0..000000000 --- a/base/runtime/docs.odin +++ /dev/null @@ -1,180 +0,0 @@ -package runtime - -/* - -package runtime has numerous entities (declarations) which are required by the compiler to function. - - -## Basic types and calls (and anything they rely on) - -Source_Code_Location -Context -Allocator -Logger - -__init_context -_cleanup_runtime - - -## cstring calls - -cstring_to_string -cstring_len - - - -## Required when RTTI is enabled (the vast majority of targets) - -Type_Info - -type_table -__type_info_of - - -## Hashing - -default_hasher -default_hasher_cstring -default_hasher_string - - -## Pseudo-CRT required procedured due to LLVM but useful in general -memset -memcpy -memove - - -## Procedures required by the LLVM backend if u128/i128 is used -umodti3 -udivti3 -modti3 -divti3 -fixdfti -fixunsdfti -fixunsdfdi -floattidf -floattidf_unsigned -truncsfhf2 -truncdfhf2 -gnu_h2f_ieee -gnu_f2h_ieee -extendhfsf2 - -## Procedures required by the LLVM backend if f16 is used -__ashlti3 // wasm specific -__multi3 // wasm specific - - -## Required an entry point is defined (i.e. 'main') - -args__ - - -## When -no-crt is defined (and not a wasm target) (mostly due to LLVM) -_tls_index -_fltused - - -## Bounds checking procedures (when not disabled with -no-bounds-check) - -bounds_check_error -matrix_bounds_check_error -slice_expr_error_hi -slice_expr_error_lo_hi -multi_pointer_slice_expr_error - - -## Type assertion check - -type_assertion_check -type_assertion_check2 // takes in typeid - - -## Arithmetic - -quo_complex32 -quo_complex64 -quo_complex128 - -mul_quaternion64 -mul_quaternion128 -mul_quaternion256 - -quo_quaternion64 -quo_quaternion128 -quo_quaternion256 - -abs_complex32 -abs_complex64 -abs_complex128 - -abs_quaternion64 -abs_quaternion128 -abs_quaternion256 - - -## Comparison - -memory_equal -memory_compare -memory_compare_zero - -cstring_eq -cstring_ne -cstring_lt -cstring_gt -cstring_le -cstring_gt - -string_eq -string_ne -string_lt -string_gt -string_le -string_gt - -complex32_eq -complex32_ne -complex64_eq -complex64_ne -complex128_eq -complex128_ne - -quaternion64_eq -quaternion64_ne -quaternion128_eq -quaternion128_ne -quaternion256_eq -quaternion256_ne - - -## Map specific calls - -map_seed_from_map_data -__dynamic_map_check_grow // static map calls -map_insert_hash_dynamic // static map calls -__dynamic_map_get // dynamic map calls -__dynamic_map_set // dynamic map calls - - -## Dynamic literals ([dynamic]T and map[K]V) (can be disabled with -no-dynamic-literals) - -__dynamic_array_reserve -__dynamic_array_append - -__dynamic_map_reserve - - -## Objective-C specific - -objc_lookUpClass -sel_registerName -objc_allocateClassPair - - -## for-in `string` type - -string_decode_rune -string_decode_last_rune // #reverse for - -*/ \ No newline at end of file From e4a0228a8030f1d8d8793464be9ea7f8ae889941 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 8 Aug 2025 10:00:11 +0100 Subject: [PATCH 030/105] Define the behaviour of integer division by zero --- src/build_settings.cpp | 7 ++ src/check_expr.cpp | 52 ++++++++++- src/llvm_backend_expr.cpp | 188 ++++++++++++++++++++++++++++++++------ src/main.cpp | 30 +++++- 4 files changed, 247 insertions(+), 30 deletions(-) diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 40bbe41e5..c2a56d1bb 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -404,6 +404,11 @@ String linker_choices[Linker_COUNT] = { str_lit("radlink"), }; +enum IntegerDivisionByZeroKind : u8 { + IntegerDivisionByZero_Trap, + IntegerDivisionByZero_Zero, +}; + // This stores the information for the specify architecture of this build struct BuildContext { // Constants @@ -485,6 +490,8 @@ struct BuildContext { bool keep_object_files; bool disallow_do; + IntegerDivisionByZeroKind integer_division_by_zero_behaviour; + LinkerChoice linker_choice; StringSet custom_attributes; diff --git a/src/check_expr.cpp b/src/check_expr.cpp index faa338f36..1b62de410 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -129,6 +129,8 @@ gb_internal bool check_is_castable_to(CheckerContext *c, Operand *operand, Type gb_internal bool is_exact_value_zero(ExactValue const &v); +gb_internal IntegerDivisionByZeroKind check_for_integer_division_by_zero(Ast *node); + enum LoadDirectiveResult { LoadDirective_Success = 0, LoadDirective_Error = 1, @@ -4308,7 +4310,25 @@ gb_internal void check_binary_expr(CheckerContext *c, Operand *x, Ast *node, Typ } if (fail) { - error(y->expr, "Division by zero not allowed"); + if (is_type_integer(x->type) || (x->mode == Addressing_Constant && x->value.kind == ExactValue_Integer)) { + if (check_for_integer_division_by_zero(node) == IntegerDivisionByZero_Zero) { + // Okay + break; + } + } + + switch (op.kind) { + case Token_Mod: + case Token_ModMod: + case Token_ModEq: + case Token_ModModEq: + error(y->expr, "Division by zero through '%.*s' not allowed", LIT(token_strings[op.kind])); + break; + case Token_Quo: + case Token_QuoEq: + error(y->expr, "Division by zero not allowed"); + break; + } x->mode = Addressing_Invalid; return; } @@ -4348,7 +4368,30 @@ gb_internal void check_binary_expr(CheckerContext *c, Operand *x, Ast *node, Typ } } - x->value = exact_binary_operator_value(op.kind, a, b); + match_exact_values(&a, &b); + + + if (check_for_integer_division_by_zero(node) == IntegerDivisionByZero_Zero && + b.kind == ExactValue_Integer && big_int_is_zero(&b.value_integer) && + (op.kind == Token_QuoEq || op.kind == Token_Mod || op.kind == Token_ModMod)) { + if (op.kind == Token_QuoEq) { + // x/0 == 0 + x->value = b; + } else { + // x%0 == x + /* + NOTE(bill): @integer division by zero rules + + truncated: r = a - b*trunc(a/b) + floored: r = a - b*floor(a/b) + + IFF a/0 == 0, then (a%0 == a) or (a%%0 == a) + */ + x->value = a; + } + } else { + x->value = exact_binary_operator_value(op.kind, a, b); + } if (is_type_typed(x->type)) { if (node != nullptr) { @@ -9595,6 +9638,11 @@ gb_internal bool check_for_dynamic_literals(CheckerContext *c, Ast *node, AstCom return cl->elems.count > 0; } +gb_internal IntegerDivisionByZeroKind check_for_integer_division_by_zero(Ast *node) { + // TODO(bill): per file `#+feature` flags + return build_context.integer_division_by_zero_behaviour; +} + gb_internal ExprKind check_compound_literal(CheckerContext *c, Operand *o, Ast *node, Type *type_hint) { ExprKind kind = Expr_Expr; ast_node(cl, CompoundLit, node); diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index 5425572c7..6652c51d3 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -283,6 +283,12 @@ gb_internal lbValue lb_emit_unary_arith(lbProcedure *p, TokenKind op, lbValue x, return res; } +gb_internal IntegerDivisionByZeroKind lb_check_for_integer_division_by_zero(lbProcedure *p) { + // TODO(bill): per file `#+feature` flags + return build_context.integer_division_by_zero_behaviour; +} + + gb_internal bool lb_try_direct_vector_arith(lbProcedure *p, TokenKind op, lbValue lhs, lbValue rhs, Type *type, lbValue *res_) { GB_ASSERT(is_type_array_like(type)); Type *elem_type = base_array_type(type); @@ -354,7 +360,6 @@ gb_internal bool lb_try_direct_vector_arith(lbProcedure *p, TokenKind op, lbValu } } else { - switch (op) { case Token_Add: z = LLVMBuildAdd(p->builder, x, y, ""); @@ -366,17 +371,15 @@ gb_internal bool lb_try_direct_vector_arith(lbProcedure *p, TokenKind op, lbValu z = LLVMBuildMul(p->builder, x, y, ""); break; case Token_Quo: - if (is_type_unsigned(integral_type)) { - z = LLVMBuildUDiv(p->builder, x, y, ""); - } else { - z = LLVMBuildSDiv(p->builder, x, y, ""); + { + auto *call = is_type_unsigned(integral_type) ? LLVMBuildUDiv : LLVMBuildSDiv; + z = call(p->builder, x, y, ""); } break; case Token_Mod: - if (is_type_unsigned(integral_type)) { - z = LLVMBuildURem(p->builder, x, y, ""); - } else { - z = LLVMBuildSRem(p->builder, x, y, ""); + { + auto *call = is_type_unsigned(integral_type) ? LLVMBuildURem : LLVMBuildSRem; + z = call(p->builder, x, y, ""); } break; case Token_ModMod: @@ -1111,6 +1114,150 @@ gb_internal lbValue lb_emit_arith_matrix(lbProcedure *p, TokenKind op, lbValue l return {}; } +gb_internal LLVMValueRef lb_integer_division(lbProcedure *p, LLVMValueRef lhs, LLVMValueRef rhs, bool is_signed) { + LLVMTypeRef type = LLVMTypeOf(rhs); + GB_ASSERT(LLVMTypeOf(lhs) == type); + + auto *call = is_signed ? LLVMBuildSDiv : LLVMBuildUDiv; + + + LLVMValueRef incoming_values[2] = {}; + LLVMBasicBlockRef incoming_blocks[2] = {}; + + lbBlock *safe_block = lb_create_block(p, "div.safe"); + lbBlock *edge_case_block = lb_create_block(p, "div.edge"); + lbBlock *done_block = lb_create_block(p, "div.done"); + + LLVMValueRef zero = LLVMConstNull(type); + LLVMValueRef dem_check = LLVMBuildICmp(p->builder, LLVMIntNE, rhs, zero, ""); + lbValue cond = {dem_check, t_untyped_bool}; + + lb_emit_if(p, cond, safe_block, edge_case_block); + + lb_start_block(p, safe_block); + incoming_values[0] = call(p->builder, lhs, rhs, ""); + + lb_emit_jump(p, done_block); + + lb_start_block(p, edge_case_block); + + incoming_values[1] = zero; + + switch (lb_check_for_integer_division_by_zero(p)) { + case IntegerDivisionByZero_Trap: + lb_call_intrinsic(p, "llvm.trap", nullptr, 0, nullptr, 0); + LLVMBuildUnreachable(p->builder); + break; + case IntegerDivisionByZero_Zero: + // Already fine + break; + } + + lb_emit_jump(p, done_block); + lb_start_block(p, done_block); + + LLVMValueRef res = incoming_values[0]; + + switch (lb_check_for_integer_division_by_zero(p)) { + case IntegerDivisionByZero_Trap: + res = incoming_values[0]; + break; + case IntegerDivisionByZero_Zero: + res = LLVMBuildPhi(p->builder, type, ""); + + GB_ASSERT(p->curr_block->preds.count >= 2); + incoming_blocks[0] = p->curr_block->preds[0]->block; + incoming_blocks[1] = p->curr_block->preds[1]->block; + + LLVMAddIncoming(res, incoming_values, incoming_blocks, 2); + break; + } + + return res; +} + +gb_internal LLVMValueRef lb_integer_modulo(lbProcedure *p, LLVMValueRef lhs, LLVMValueRef rhs, bool is_unsigned, bool is_floored) { + LLVMTypeRef type = LLVMTypeOf(rhs); + GB_ASSERT(LLVMTypeOf(lhs) == type); + + LLVMValueRef incoming_values[2] = {}; + LLVMBasicBlockRef incoming_blocks[2] = {}; + + lbBlock *safe_block = lb_create_block(p, "div.safe"); + lbBlock *edge_case_block = lb_create_block(p, "div.edge"); + lbBlock *done_block = lb_create_block(p, "div.done"); + + LLVMValueRef zero = LLVMConstNull(type); + LLVMValueRef dem_check = LLVMBuildICmp(p->builder, LLVMIntNE, rhs, zero, ""); + lbValue cond = {dem_check, t_untyped_bool}; + + lb_emit_if(p, cond, safe_block, edge_case_block); + + lb_start_block(p, safe_block); + + if (is_floored) { // %% + if (is_unsigned) { + incoming_values[0] = LLVMBuildURem(p->builder, lhs, rhs, ""); + } else { + LLVMValueRef a = LLVMBuildSRem(p->builder, lhs, rhs, ""); + LLVMValueRef b = LLVMBuildAdd(p->builder, a, rhs, ""); + LLVMValueRef c = LLVMBuildSRem(p->builder, b, rhs, ""); + incoming_values[0] = c; + } + } else { // % + if (is_unsigned) { + incoming_values[0] = LLVMBuildURem(p->builder, lhs, rhs, ""); + } else { + incoming_values[0] = LLVMBuildSRem(p->builder, lhs, rhs, ""); + } + } + + lb_emit_jump(p, done_block); + + lb_start_block(p, edge_case_block); + + /* + NOTE(bill): @integer division by zero rules + + truncated: r = a - b*trunc(a/b) + floored: r = a - b*floor(a/b) + + IFF a/0 == 0, then (a%0 == a) or (a%%0 == a) + */ + incoming_values[1] = lhs; + + switch (lb_check_for_integer_division_by_zero(p)) { + case IntegerDivisionByZero_Trap: + lb_call_intrinsic(p, "llvm.trap", nullptr, 0, nullptr, 0); + LLVMBuildUnreachable(p->builder); + break; + case IntegerDivisionByZero_Zero: + // Already fine + break; + } + + lb_emit_jump(p, done_block); + lb_start_block(p, done_block); + + LLVMValueRef res = incoming_values[0]; + + switch (lb_check_for_integer_division_by_zero(p)) { + case IntegerDivisionByZero_Trap: + res = incoming_values[0]; + break; + case IntegerDivisionByZero_Zero: + res = LLVMBuildPhi(p->builder, type, ""); + + GB_ASSERT(p->curr_block->preds.count >= 2); + incoming_blocks[0] = p->curr_block->preds[0]->block; + incoming_blocks[1] = p->curr_block->preds[1]->block; + + LLVMAddIncoming(res, incoming_values, incoming_blocks, 2); + break; + } + + return res; +} gb_internal lbValue lb_emit_arith(lbProcedure *p, TokenKind op, lbValue lhs, lbValue rhs, Type *type) { @@ -1350,33 +1497,20 @@ handle_op:; if (is_type_float(integral_type)) { res.value = LLVMBuildFDiv(p->builder, lhs.value, rhs.value, ""); return res; - } else if (is_type_unsigned(integral_type)) { - res.value = LLVMBuildUDiv(p->builder, lhs.value, rhs.value, ""); + } else { + res.value = lb_integer_division(p, lhs.value, rhs.value, !is_type_unsigned(integral_type)); return res; } - res.value = LLVMBuildSDiv(p->builder, lhs.value, rhs.value, ""); - return res; case Token_Mod: if (is_type_float(integral_type)) { res.value = LLVMBuildFRem(p->builder, lhs.value, rhs.value, ""); return res; - } else if (is_type_unsigned(integral_type)) { - res.value = LLVMBuildURem(p->builder, lhs.value, rhs.value, ""); - return res; } - res.value = LLVMBuildSRem(p->builder, lhs.value, rhs.value, ""); + res.value = lb_integer_modulo(p, lhs.value, rhs.value, is_type_unsigned(integral_type), /*is_floored*/false); return res; case Token_ModMod: - if (is_type_unsigned(integral_type)) { - res.value = LLVMBuildURem(p->builder, lhs.value, rhs.value, ""); - return res; - } else { - LLVMValueRef a = LLVMBuildSRem(p->builder, lhs.value, rhs.value, ""); - LLVMValueRef b = LLVMBuildAdd(p->builder, a, rhs.value, ""); - LLVMValueRef c = LLVMBuildSRem(p->builder, b, rhs.value, ""); - res.value = c; - return res; - } + res.value = lb_integer_modulo(p, lhs.value, rhs.value, is_type_unsigned(integral_type), /*is_floored*/true); + return res; case Token_And: res.value = LLVMBuildAnd(p->builder, lhs.value, rhs.value, ""); diff --git a/src/main.cpp b/src/main.cpp index 5a43e3c02..0bfab0344 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -392,6 +392,8 @@ enum BuildFlagKind { BuildFlag_PrintLinkerFlags, + BuildFlag_IntegerDivisionByZero, + // internal use only BuildFlag_InternalFastISel, BuildFlag_InternalIgnoreLazy, @@ -613,6 +615,9 @@ gb_internal bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_PrintLinkerFlags, str_lit("print-linker-flags"), BuildFlagParam_None, Command_build); + add_flag(&build_flags, BuildFlag_IntegerDivisionByZero, str_lit("integer-division-by-zero"), BuildFlagParam_String, Command__does_check); + + add_flag(&build_flags, BuildFlag_InternalFastISel, str_lit("internal-fast-isel"), BuildFlagParam_None, Command_all); add_flag(&build_flags, BuildFlag_InternalIgnoreLazy, str_lit("internal-ignore-lazy"), BuildFlagParam_None, Command_all); add_flag(&build_flags, BuildFlag_InternalIgnoreLLVMBuild, str_lit("internal-ignore-llvm-build"),BuildFlagParam_None, Command_all); @@ -1515,7 +1520,7 @@ gb_internal bool parse_build_flags(Array args) { } else if (str_eq_ignore_case(value.value_string, str_lit("unix"))) { build_context.ODIN_ERROR_POS_STYLE = ErrorPosStyle_Unix; } else { - gb_printf_err("-error-pos-style options are 'unix', 'odin' and 'default' (odin)\n"); + gb_printf_err("-error-pos-style options are 'unix', 'odin', and 'default' (odin)\n"); bad_flags = true; } break; @@ -1539,6 +1544,18 @@ gb_internal bool parse_build_flags(Array args) { build_context.print_linker_flags = true; break; + case BuildFlag_IntegerDivisionByZero: + GB_ASSERT(value.kind == ExactValue_String); + if (str_eq_ignore_case(value.value_string, "trap")) { + build_context.integer_division_by_zero_behaviour = IntegerDivisionByZero_Trap; + } else if (str_eq_ignore_case(value.value_string, "zero")) { + build_context.integer_division_by_zero_behaviour = IntegerDivisionByZero_Zero; + } else { + gb_printf_err("-integer-division-by-zero options are 'trap' and 'zero'.\n"); + bad_flags = true; + } + break; + case BuildFlag_InternalFastISel: build_context.fast_isel = true; break; @@ -2561,7 +2578,18 @@ gb_internal int print_show_help(String const arg0, String command, String option if (print_flag("-ignore-warnings")) { print_usage_line(2, "Ignores warning messages."); } + } + if (check) { + if (print_flag("-integer-division-by-zero:")) { + print_usage_line(2, "Specifies the default behaviour for integer division by zero."); + print_usage_line(2, "Available Options:"); + print_usage_line(3, "-integer-division-by-zero:trap Trap on division/modulo/remainder by zero"); + print_usage_line(3, "-integer-division-by-zero:zero x/0 == 0 and x%%0 == x and x%%%%0 == 0"); + } + } + + if (check) { if (print_flag("-json-errors")) { print_usage_line(2, "Prints the error messages as json to stderr."); } From 991883d0e1376c1e5675e88c26fee89362adc7b1 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 8 Aug 2025 10:24:44 +0100 Subject: [PATCH 031/105] Add `#+feature integer-division-by-zero:` --- src/build_settings.cpp | 12 +++++++++++ src/check_expr.cpp | 15 ++++++++++---- src/llvm_backend_expr.cpp | 30 ++++++++++++++++++++++------ src/parser.cpp | 42 ++++++++++++++++++++++++++++----------- 4 files changed, 77 insertions(+), 22 deletions(-) diff --git a/src/build_settings.cpp b/src/build_settings.cpp index c2a56d1bb..e21e7da12 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -352,12 +352,24 @@ u64 get_vet_flag_from_name(String const &name) { enum OptInFeatureFlags : u64 { OptInFeatureFlag_NONE = 0, OptInFeatureFlag_DynamicLiterals = 1u<<0, + + OptInFeatureFlag_IntegerDivisionByZero_Trap = 1u<<1, + OptInFeatureFlag_IntegerDivisionByZero_Zero = 1u<<2, + + OptInFeatureFlag_IntegerDivisionByZero_ALL = OptInFeatureFlag_IntegerDivisionByZero_Trap|OptInFeatureFlag_IntegerDivisionByZero_Zero, + }; u64 get_feature_flag_from_name(String const &name) { if (name == "dynamic-literals") { return OptInFeatureFlag_DynamicLiterals; } + if (name == "integer-division-by-zero:trap") { + return OptInFeatureFlag_IntegerDivisionByZero_Trap; + } + if (name == "integer-division-by-zero:zero") { + return OptInFeatureFlag_IntegerDivisionByZero_Zero; + } return OptInFeatureFlag_NONE; } diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 1b62de410..b68fe0ed0 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -129,7 +129,7 @@ gb_internal bool check_is_castable_to(CheckerContext *c, Operand *operand, Type gb_internal bool is_exact_value_zero(ExactValue const &v); -gb_internal IntegerDivisionByZeroKind check_for_integer_division_by_zero(Ast *node); +gb_internal IntegerDivisionByZeroKind check_for_integer_division_by_zero(CheckerContext *c, Ast *node); enum LoadDirectiveResult { LoadDirective_Success = 0, @@ -4311,7 +4311,7 @@ gb_internal void check_binary_expr(CheckerContext *c, Operand *x, Ast *node, Typ if (fail) { if (is_type_integer(x->type) || (x->mode == Addressing_Constant && x->value.kind == ExactValue_Integer)) { - if (check_for_integer_division_by_zero(node) == IntegerDivisionByZero_Zero) { + if (check_for_integer_division_by_zero(c, node) == IntegerDivisionByZero_Zero) { // Okay break; } @@ -4371,7 +4371,7 @@ gb_internal void check_binary_expr(CheckerContext *c, Operand *x, Ast *node, Typ match_exact_values(&a, &b); - if (check_for_integer_division_by_zero(node) == IntegerDivisionByZero_Zero && + if (check_for_integer_division_by_zero(c, node) == IntegerDivisionByZero_Zero && b.kind == ExactValue_Integer && big_int_is_zero(&b.value_integer) && (op.kind == Token_QuoEq || op.kind == Token_Mod || op.kind == Token_ModMod)) { if (op.kind == Token_QuoEq) { @@ -9638,8 +9638,15 @@ gb_internal bool check_for_dynamic_literals(CheckerContext *c, Ast *node, AstCom return cl->elems.count > 0; } -gb_internal IntegerDivisionByZeroKind check_for_integer_division_by_zero(Ast *node) { +gb_internal IntegerDivisionByZeroKind check_for_integer_division_by_zero(CheckerContext *c, Ast *node) { // TODO(bill): per file `#+feature` flags + u64 flags = check_feature_flags(c, node); + if ((flags & OptInFeatureFlag_IntegerDivisionByZero_Trap) != 0) { + return IntegerDivisionByZero_Trap; + } + if ((flags & OptInFeatureFlag_IntegerDivisionByZero_Zero) != 0) { + return IntegerDivisionByZero_Zero; + } return build_context.integer_division_by_zero_behaviour; } diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index 6652c51d3..b20aef742 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -283,8 +283,26 @@ gb_internal lbValue lb_emit_unary_arith(lbProcedure *p, TokenKind op, lbValue x, return res; } -gb_internal IntegerDivisionByZeroKind lb_check_for_integer_division_by_zero(lbProcedure *p) { - // TODO(bill): per file `#+feature` flags +gb_internal IntegerDivisionByZeroKind lb_check_for_integer_division_by_zero_behaviour(lbProcedure *p) { + AstFile *file = nullptr; + + if (p->body && p->body->file()) { + file = p->body->file(); + } else if (p->type_expr && p->type_expr->file()) { + file = p->type_expr->file(); + } else if (p->entity && p->entity->file) { + file = p->entity->file; + } + + if (file != nullptr && file->feature_flags_set) { + u64 flags = file->feature_flags; + if (flags & OptInFeatureFlag_IntegerDivisionByZero_Trap) { + return IntegerDivisionByZero_Trap; + } + if (flags & OptInFeatureFlag_IntegerDivisionByZero_Zero) { + return IntegerDivisionByZero_Zero; + } + } return build_context.integer_division_by_zero_behaviour; } @@ -1143,7 +1161,7 @@ gb_internal LLVMValueRef lb_integer_division(lbProcedure *p, LLVMValueRef lhs, L incoming_values[1] = zero; - switch (lb_check_for_integer_division_by_zero(p)) { + switch (lb_check_for_integer_division_by_zero_behaviour(p)) { case IntegerDivisionByZero_Trap: lb_call_intrinsic(p, "llvm.trap", nullptr, 0, nullptr, 0); LLVMBuildUnreachable(p->builder); @@ -1158,7 +1176,7 @@ gb_internal LLVMValueRef lb_integer_division(lbProcedure *p, LLVMValueRef lhs, L LLVMValueRef res = incoming_values[0]; - switch (lb_check_for_integer_division_by_zero(p)) { + switch (lb_check_for_integer_division_by_zero_behaviour(p)) { case IntegerDivisionByZero_Trap: res = incoming_values[0]; break; @@ -1226,7 +1244,7 @@ gb_internal LLVMValueRef lb_integer_modulo(lbProcedure *p, LLVMValueRef lhs, LLV */ incoming_values[1] = lhs; - switch (lb_check_for_integer_division_by_zero(p)) { + switch (lb_check_for_integer_division_by_zero_behaviour(p)) { case IntegerDivisionByZero_Trap: lb_call_intrinsic(p, "llvm.trap", nullptr, 0, nullptr, 0); LLVMBuildUnreachable(p->builder); @@ -1241,7 +1259,7 @@ gb_internal LLVMValueRef lb_integer_modulo(lbProcedure *p, LLVMValueRef lhs, LLV LLVMValueRef res = incoming_values[0]; - switch (lb_check_for_integer_division_by_zero(p)) { + switch (lb_check_for_integer_division_by_zero_behaviour(p)) { case IntegerDivisionByZero_Trap: res = incoming_values[0]; break; diff --git a/src/parser.cpp b/src/parser.cpp index 1ccc3feaa..58d7acfa5 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -6289,7 +6289,7 @@ gb_internal bool parse_build_tag(Token token_for_pos, String s) { return any_correct; } -gb_internal String vet_tag_get_token(String s, String *out) { +gb_internal String vet_tag_get_token(String s, String *out, bool allow_colon) { s = string_trim_whitespace(s); isize n = 0; while (n < s.len) { @@ -6297,7 +6297,7 @@ gb_internal String vet_tag_get_token(String s, String *out) { isize width = utf8_decode(&s[n], s.len-n, &rune); if (n == 0 && rune == '!') { - } else if (!rune_is_letter(rune) && !rune_is_digit(rune) && rune != '-') { + } else if (!rune_is_letter(rune) && !rune_is_digit(rune) && rune != '-' && !(allow_colon && rune == ':')) { isize k = gb_max(gb_max(n, width), 1); *out = substring(s, k, s.len); return substring(s, 0, k); @@ -6323,7 +6323,7 @@ gb_internal u64 parse_vet_tag(Token token_for_pos, String s) { u64 vet_not_flags = 0; while (s.len > 0) { - String p = string_trim_whitespace(vet_tag_get_token(s, &s)); + String p = string_trim_whitespace(vet_tag_get_token(s, &s, /*allow_colon*/false)); if (p.len == 0) { break; } @@ -6391,7 +6391,7 @@ gb_internal u64 parse_feature_tag(Token token_for_pos, String s) { u64 feature_not_flags = 0; while (s.len > 0) { - String p = string_trim_whitespace(vet_tag_get_token(s, &s)); + String p = string_trim_whitespace(vet_tag_get_token(s, &s, /*allow_colon*/true)); if (p.len == 0) { break; } @@ -6413,26 +6413,44 @@ gb_internal u64 parse_feature_tag(Token token_for_pos, String s) { } else { feature_flags |= flag; } + if (is_notted) { + switch (flag) { + case OptInFeatureFlag_IntegerDivisionByZero_Trap: + case OptInFeatureFlag_IntegerDivisionByZero_Zero: + syntax_error(token_for_pos, "Feature flag does not support notting with '!' - '%.*s'", LIT(p)); + break; + } + } } else { ERROR_BLOCK(); syntax_error(token_for_pos, "Invalid feature flag name: %.*s", LIT(p)); error_line("\tExpected one of the following\n"); error_line("\tdynamic-literals\n"); + error_line("\tinteger-division-by-zero:trap\n"); + error_line("\tinteger-division-by-zero:zero\n"); return OptInFeatureFlag_NONE; } } + u64 res = OptInFeatureFlag_NONE; + if (feature_flags == 0 && feature_not_flags == 0) { - return OptInFeatureFlag_NONE; + res = OptInFeatureFlag_NONE; + } else if (feature_flags == 0 && feature_not_flags != 0) { + res = OptInFeatureFlag_NONE &~ feature_not_flags; + } else if (feature_flags != 0 && feature_not_flags == 0) { + res = feature_flags; + } else { + GB_ASSERT(feature_flags != 0 && feature_not_flags != 0); + res = feature_flags &~ feature_not_flags; } - if (feature_flags == 0 && feature_not_flags != 0) { - return OptInFeatureFlag_NONE &~ feature_not_flags; + + if ((res & OptInFeatureFlag_IntegerDivisionByZero_ALL) == + OptInFeatureFlag_IntegerDivisionByZero_ALL) { + syntax_error(token_for_pos, "Only one integer-division-by-zero feature flag can be enabled"); } - if (feature_flags != 0 && feature_not_flags == 0) { - return feature_flags; - } - GB_ASSERT(feature_flags != 0 && feature_not_flags != 0); - return feature_flags &~ feature_not_flags; + + return res; } gb_internal String dir_from_path(String path) { From ee01643229cc015c35b3b1c237caa66a056bb9be Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 8 Aug 2025 10:41:05 +0100 Subject: [PATCH 032/105] Add `-integer-division-by-zero:self` --- src/build_settings.cpp | 7 ++++++- src/check_expr.cpp | 28 ++++++++++++++++++++++------ src/llvm_backend_expr.cpp | 17 +++++++++++++---- src/main.cpp | 9 ++++++--- src/parser.cpp | 1 + 5 files changed, 48 insertions(+), 14 deletions(-) diff --git a/src/build_settings.cpp b/src/build_settings.cpp index e21e7da12..a6dce5233 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -355,8 +355,9 @@ enum OptInFeatureFlags : u64 { OptInFeatureFlag_IntegerDivisionByZero_Trap = 1u<<1, OptInFeatureFlag_IntegerDivisionByZero_Zero = 1u<<2, + OptInFeatureFlag_IntegerDivisionByZero_Self = 1u<<3, - OptInFeatureFlag_IntegerDivisionByZero_ALL = OptInFeatureFlag_IntegerDivisionByZero_Trap|OptInFeatureFlag_IntegerDivisionByZero_Zero, + OptInFeatureFlag_IntegerDivisionByZero_ALL = OptInFeatureFlag_IntegerDivisionByZero_Trap|OptInFeatureFlag_IntegerDivisionByZero_Zero|OptInFeatureFlag_IntegerDivisionByZero_Self, }; @@ -370,6 +371,9 @@ u64 get_feature_flag_from_name(String const &name) { if (name == "integer-division-by-zero:zero") { return OptInFeatureFlag_IntegerDivisionByZero_Zero; } + if (name == "integer-division-by-zero:self") { + return OptInFeatureFlag_IntegerDivisionByZero_Self; + } return OptInFeatureFlag_NONE; } @@ -419,6 +423,7 @@ String linker_choices[Linker_COUNT] = { enum IntegerDivisionByZeroKind : u8 { IntegerDivisionByZero_Trap, IntegerDivisionByZero_Zero, + IntegerDivisionByZero_Self, }; // This stores the information for the specify architecture of this build diff --git a/src/check_expr.cpp b/src/check_expr.cpp index b68fe0ed0..782080c93 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -4311,7 +4311,7 @@ gb_internal void check_binary_expr(CheckerContext *c, Operand *x, Ast *node, Typ if (fail) { if (is_type_integer(x->type) || (x->mode == Addressing_Constant && x->value.kind == ExactValue_Integer)) { - if (check_for_integer_division_by_zero(c, node) == IntegerDivisionByZero_Zero) { + if (check_for_integer_division_by_zero(c, node) != IntegerDivisionByZero_Trap) { // Okay break; } @@ -4371,14 +4371,19 @@ gb_internal void check_binary_expr(CheckerContext *c, Operand *x, Ast *node, Typ match_exact_values(&a, &b); - if (check_for_integer_division_by_zero(c, node) == IntegerDivisionByZero_Zero && + IntegerDivisionByZeroKind zero_behaviour = check_for_integer_division_by_zero(c, node); + if (zero_behaviour != IntegerDivisionByZero_Trap && b.kind == ExactValue_Integer && big_int_is_zero(&b.value_integer) && (op.kind == Token_QuoEq || op.kind == Token_Mod || op.kind == Token_ModMod)) { if (op.kind == Token_QuoEq) { - // x/0 == 0 - x->value = b; + if (zero_behaviour == IntegerDivisionByZero_Zero) { + // x/0 == 0 + x->value = b; + } else { + // x/0 == x + x->value = a; + } } else { - // x%0 == x /* NOTE(bill): @integer division by zero rules @@ -4386,8 +4391,16 @@ gb_internal void check_binary_expr(CheckerContext *c, Operand *x, Ast *node, Typ floored: r = a - b*floor(a/b) IFF a/0 == 0, then (a%0 == a) or (a%%0 == a) + IFF a/0 == a, then (a%0 == 0) or (a%%0 == 0) */ - x->value = a; + + if (zero_behaviour == IntegerDivisionByZero_Zero) { + // x%0 == x + x->value = a; + } else { + // x%0 == 0 + x->value = b; + } } } else { x->value = exact_binary_operator_value(op.kind, a, b); @@ -9647,6 +9660,9 @@ gb_internal IntegerDivisionByZeroKind check_for_integer_division_by_zero(Checker if ((flags & OptInFeatureFlag_IntegerDivisionByZero_Zero) != 0) { return IntegerDivisionByZero_Zero; } + if ((flags & OptInFeatureFlag_IntegerDivisionByZero_Self) != 0) { + return IntegerDivisionByZero_Self; + } return build_context.integer_division_by_zero_behaviour; } diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index b20aef742..b44d2215e 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -302,6 +302,9 @@ gb_internal IntegerDivisionByZeroKind lb_check_for_integer_division_by_zero_beha if (flags & OptInFeatureFlag_IntegerDivisionByZero_Zero) { return IntegerDivisionByZero_Zero; } + if (flags & OptInFeatureFlag_IntegerDivisionByZero_Self) { + return IntegerDivisionByZero_Self; + } } return build_context.integer_division_by_zero_behaviour; } @@ -1159,7 +1162,6 @@ gb_internal LLVMValueRef lb_integer_division(lbProcedure *p, LLVMValueRef lhs, L lb_start_block(p, edge_case_block); - incoming_values[1] = zero; switch (lb_check_for_integer_division_by_zero_behaviour(p)) { case IntegerDivisionByZero_Trap: @@ -1167,7 +1169,10 @@ gb_internal LLVMValueRef lb_integer_division(lbProcedure *p, LLVMValueRef lhs, L LLVMBuildUnreachable(p->builder); break; case IntegerDivisionByZero_Zero: - // Already fine + incoming_values[1] = zero; + break; + case IntegerDivisionByZero_Self: + incoming_values[1] = lhs; break; } @@ -1178,6 +1183,7 @@ gb_internal LLVMValueRef lb_integer_division(lbProcedure *p, LLVMValueRef lhs, L switch (lb_check_for_integer_division_by_zero_behaviour(p)) { case IntegerDivisionByZero_Trap: + case IntegerDivisionByZero_Self: res = incoming_values[0]; break; case IntegerDivisionByZero_Zero: @@ -1242,7 +1248,6 @@ gb_internal LLVMValueRef lb_integer_modulo(lbProcedure *p, LLVMValueRef lhs, LLV IFF a/0 == 0, then (a%0 == a) or (a%%0 == a) */ - incoming_values[1] = lhs; switch (lb_check_for_integer_division_by_zero_behaviour(p)) { case IntegerDivisionByZero_Trap: @@ -1250,7 +1255,10 @@ gb_internal LLVMValueRef lb_integer_modulo(lbProcedure *p, LLVMValueRef lhs, LLV LLVMBuildUnreachable(p->builder); break; case IntegerDivisionByZero_Zero: - // Already fine + incoming_values[1] = lhs; + break; + case IntegerDivisionByZero_Self: + incoming_values[1] = zero; break; } @@ -1261,6 +1269,7 @@ gb_internal LLVMValueRef lb_integer_modulo(lbProcedure *p, LLVMValueRef lhs, LLV switch (lb_check_for_integer_division_by_zero_behaviour(p)) { case IntegerDivisionByZero_Trap: + case IntegerDivisionByZero_Self: res = incoming_values[0]; break; case IntegerDivisionByZero_Zero: diff --git a/src/main.cpp b/src/main.cpp index 0bfab0344..2f0b1c19b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1550,8 +1550,10 @@ gb_internal bool parse_build_flags(Array args) { build_context.integer_division_by_zero_behaviour = IntegerDivisionByZero_Trap; } else if (str_eq_ignore_case(value.value_string, "zero")) { build_context.integer_division_by_zero_behaviour = IntegerDivisionByZero_Zero; - } else { - gb_printf_err("-integer-division-by-zero options are 'trap' and 'zero'.\n"); + } else if (str_eq_ignore_case(value.value_string, "self")) { + build_context.integer_division_by_zero_behaviour = IntegerDivisionByZero_Self; + }else { + gb_printf_err("-integer-division-by-zero options are 'trap', 'zero', and 'self'.\n"); bad_flags = true; } break; @@ -2585,7 +2587,8 @@ gb_internal int print_show_help(String const arg0, String command, String option print_usage_line(2, "Specifies the default behaviour for integer division by zero."); print_usage_line(2, "Available Options:"); print_usage_line(3, "-integer-division-by-zero:trap Trap on division/modulo/remainder by zero"); - print_usage_line(3, "-integer-division-by-zero:zero x/0 == 0 and x%%0 == x and x%%%%0 == 0"); + print_usage_line(3, "-integer-division-by-zero:zero x/0 == 0 and x%%0 == x and x%%%%0 == x"); + print_usage_line(3, "-integer-division-by-zero:self x/0 == x and x%%0 == 0 and x%%%%0 == 0"); } } diff --git a/src/parser.cpp b/src/parser.cpp index 58d7acfa5..c63ffe747 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -6428,6 +6428,7 @@ gb_internal u64 parse_feature_tag(Token token_for_pos, String s) { error_line("\tdynamic-literals\n"); error_line("\tinteger-division-by-zero:trap\n"); error_line("\tinteger-division-by-zero:zero\n"); + error_line("\tinteger-division-by-zero:self\n"); return OptInFeatureFlag_NONE; } } From 7b5cee9f1e6f6048d8689dbdf959409bd4073b3b Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 8 Aug 2025 10:50:24 +0100 Subject: [PATCH 033/105] Correct #+feature check --- src/parser.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/parser.cpp b/src/parser.cpp index c63ffe747..a05e183ce 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -6446,8 +6446,8 @@ gb_internal u64 parse_feature_tag(Token token_for_pos, String s) { res = feature_flags &~ feature_not_flags; } - if ((res & OptInFeatureFlag_IntegerDivisionByZero_ALL) == - OptInFeatureFlag_IntegerDivisionByZero_ALL) { + u64 idbz_count = gb_count_set_bits(res & OptInFeatureFlag_IntegerDivisionByZero_ALL); + if (idbz_count > 1) { syntax_error(token_for_pos, "Only one integer-division-by-zero feature flag can be enabled"); } From 8c1eda3e3a112ac1475674f306ac876cebdd762a Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 8 Aug 2025 11:10:01 +0100 Subject: [PATCH 034/105] Handle `fixed_point_div` and `fixed_point_div_sat` --- src/llvm_backend_expr.cpp | 73 +++++++++++++++++++++++++++++++++++++++ src/llvm_backend_proc.cpp | 14 +++++--- 2 files changed, 83 insertions(+), 4 deletions(-) diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index b44d2215e..a29682874 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -1200,6 +1200,79 @@ gb_internal LLVMValueRef lb_integer_division(lbProcedure *p, LLVMValueRef lhs, L return res; } +gb_internal LLVMValueRef lb_integer_division_intrinsics(lbProcedure *p, LLVMValueRef lhs, LLVMValueRef rhs, LLVMValueRef scale, Type *platform_type, char const *name) { + LLVMTypeRef type = LLVMTypeOf(rhs); + GB_ASSERT(LLVMTypeOf(lhs) == type); + + LLVMValueRef incoming_values[2] = {}; + LLVMBasicBlockRef incoming_blocks[2] = {}; + + lbBlock *safe_block = lb_create_block(p, "div.safe"); + lbBlock *edge_case_block = lb_create_block(p, "div.edge"); + lbBlock *done_block = lb_create_block(p, "div.done"); + + LLVMValueRef zero = LLVMConstNull(type); + LLVMValueRef dem_check = LLVMBuildICmp(p->builder, LLVMIntNE, rhs, zero, ""); + lbValue cond = {dem_check, t_untyped_bool}; + + lb_emit_if(p, cond, safe_block, edge_case_block); + + lb_start_block(p, safe_block); + + { + LLVMTypeRef types[1] = {lb_type(p->module, platform_type)}; + + LLVMValueRef args[3] = { + lhs, + rhs, + scale }; + + incoming_values[0] = lb_call_intrinsic(p, name, args, gb_count_of(args), types, gb_count_of(types)); + } + + lb_emit_jump(p, done_block); + + lb_start_block(p, edge_case_block); + + + switch (lb_check_for_integer_division_by_zero_behaviour(p)) { + case IntegerDivisionByZero_Trap: + lb_call_intrinsic(p, "llvm.trap", nullptr, 0, nullptr, 0); + LLVMBuildUnreachable(p->builder); + break; + case IntegerDivisionByZero_Zero: + incoming_values[1] = zero; + break; + case IntegerDivisionByZero_Self: + incoming_values[1] = lhs; + break; + } + + lb_emit_jump(p, done_block); + lb_start_block(p, done_block); + + LLVMValueRef res = incoming_values[0]; + + switch (lb_check_for_integer_division_by_zero_behaviour(p)) { + case IntegerDivisionByZero_Trap: + case IntegerDivisionByZero_Self: + res = incoming_values[0]; + break; + case IntegerDivisionByZero_Zero: + res = LLVMBuildPhi(p->builder, type, ""); + + GB_ASSERT(p->curr_block->preds.count >= 2); + incoming_blocks[0] = p->curr_block->preds[0]->block; + incoming_blocks[1] = p->curr_block->preds[1]->block; + + LLVMAddIncoming(res, incoming_values, incoming_blocks, 2); + break; + } + + return res; +} + + gb_internal LLVMValueRef lb_integer_modulo(lbProcedure *p, LLVMValueRef lhs, LLVMValueRef rhs, bool is_unsigned, bool is_floored) { LLVMTypeRef type = LLVMTypeOf(rhs); GB_ASSERT(LLVMTypeOf(lhs) == type); diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index 04dcc6662..f2e6662c8 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -3302,16 +3302,22 @@ gb_internal lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValu } GB_ASSERT(name != nullptr); - LLVMTypeRef types[1] = {lb_type(p->module, platform_type)}; lbValue res = {}; + res.type = platform_type; - LLVMValueRef args[3] = { + if (id == BuiltinProc_fixed_point_div || + id == BuiltinProc_fixed_point_div_sat) { + res.value = lb_integer_division_intrinsics(p, x.value, y.value, scale.value, platform_type, name); + } else { + LLVMTypeRef types[1] = {lb_type(p->module, platform_type)}; + + LLVMValueRef args[3] = { x.value, y.value, scale.value }; - res.value = lb_call_intrinsic(p, name, args, gb_count_of(args), types, gb_count_of(types)); - res.type = platform_type; + res.value = lb_call_intrinsic(p, name, args, gb_count_of(args), types, gb_count_of(types)); + } return lb_emit_conv(p, res, tv.type); } From 7642e0a0e0bb0ff79da6ac7a2ba3b787afa32b78 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 8 Aug 2025 12:10:01 +0100 Subject: [PATCH 035/105] Require `@(init)` and `@(fini)` to be `proc "contextless" ()` --- base/runtime/default_allocators_nil.odin | 2 +- base/runtime/default_temp_allocator_arena.odin | 7 +++++-- base/runtime/default_temporary_allocator.odin | 6 +++--- base/runtime/thread_management.odin | 11 +++++++++-- core/encoding/cbor/tags.odin | 10 ++++++---- core/image/bmp/bmp.odin | 2 +- core/image/general.odin | 10 +++++----- core/image/netpbm/netpbm.odin | 2 +- core/image/png/png.odin | 2 +- core/image/qoi/qoi.odin | 2 +- core/image/tga/tga.odin | 2 +- core/log/file_console_logger.odin | 4 +++- core/math/big/helpers.odin | 18 ++++++++++-------- core/math/big/internal.odin | 11 ++++++----- core/mem/virtual/virtual.odin | 2 +- core/mem/virtual/virtual_linux.odin | 4 ++-- core/mem/virtual/virtual_other.odin | 2 +- core/mem/virtual/virtual_posix.odin | 4 ++-- core/mem/virtual/virtual_windows.odin | 4 ++-- core/net/socket_windows.odin | 2 +- core/os/os2/allocators.odin | 4 ++-- core/os/os2/file_posix.odin | 4 ++-- core/os/os2/file_wasi.odin | 4 ++-- core/os/os2/file_windows.odin | 8 ++++---- core/os/os2/path_windows.odin | 2 +- core/os/os_darwin.odin | 6 ++++-- core/os/os_freebsd.odin | 6 ++++-- core/os/os_haiku.odin | 6 ++++-- core/os/os_linux.odin | 6 ++++-- core/os/os_netbsd.odin | 6 ++++-- core/os/os_openbsd.odin | 6 ++++-- core/os/os_wasi.odin | 10 ++++++---- core/os/os_windows.odin | 6 ++++-- core/sys/info/cpu_intel.odin | 4 ++-- core/sys/info/cpu_linux_arm.odin | 4 +++- core/sys/info/cpu_linux_intel.odin | 5 ++++- core/sys/info/cpu_windows.odin | 5 ++++- core/sys/info/platform_darwin.odin | 5 ++++- core/sys/info/platform_linux.odin | 9 ++++++--- core/sys/info/platform_windows.odin | 12 ++++++++---- core/sys/windows/util.odin | 4 ++-- core/terminal/internal.odin | 7 +++++-- core/terminal/terminal_js.odin | 6 +++--- core/terminal/terminal_posix.odin | 8 +++++--- core/terminal/terminal_windows.odin | 9 ++++++--- src/checker.cpp | 9 +++++++++ vendor/miniaudio/common.odin | 4 ++-- 47 files changed, 170 insertions(+), 102 deletions(-) diff --git a/base/runtime/default_allocators_nil.odin b/base/runtime/default_allocators_nil.odin index e7a1b1a74..14edd11dd 100644 --- a/base/runtime/default_allocators_nil.odin +++ b/base/runtime/default_allocators_nil.odin @@ -23,7 +23,7 @@ nil_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, return nil, .None } -nil_allocator :: proc() -> Allocator { +nil_allocator :: proc "contextless" () -> Allocator { return Allocator{ procedure = nil_allocator_proc, data = nil, diff --git a/base/runtime/default_temp_allocator_arena.odin b/base/runtime/default_temp_allocator_arena.odin index ca144b66f..525f81825 100644 --- a/base/runtime/default_temp_allocator_arena.odin +++ b/base/runtime/default_temp_allocator_arena.odin @@ -52,10 +52,13 @@ memory_block_alloc :: proc(allocator: Allocator, capacity: uint, alignment: uint return } -memory_block_dealloc :: proc(block_to_free: ^Memory_Block, loc := #caller_location) { +memory_block_dealloc :: proc "contextless" (block_to_free: ^Memory_Block, loc := #caller_location) { if block_to_free != nil { + allocator := block_to_free.allocator // sanitizer.address_unpoison(block_to_free.base, block_to_free.capacity) + context = default_context() + context.allocator = allocator mem_free(block_to_free, allocator, loc) } } @@ -172,7 +175,7 @@ arena_free_all :: proc(arena: ^Arena, loc := #caller_location) { arena.total_used = 0 } -arena_destroy :: proc(arena: ^Arena, loc := #caller_location) { +arena_destroy :: proc "contextless" (arena: ^Arena, loc := #caller_location) { for arena.curr_block != nil { free_block := arena.curr_block arena.curr_block = free_block.prev diff --git a/base/runtime/default_temporary_allocator.odin b/base/runtime/default_temporary_allocator.odin index b355ded70..671728be8 100644 --- a/base/runtime/default_temporary_allocator.odin +++ b/base/runtime/default_temporary_allocator.odin @@ -8,7 +8,7 @@ when NO_DEFAULT_TEMP_ALLOCATOR { default_temp_allocator_init :: proc(s: ^Default_Temp_Allocator, size: int, backing_allocator := context.allocator) {} - default_temp_allocator_destroy :: proc(s: ^Default_Temp_Allocator) {} + default_temp_allocator_destroy :: proc "contextless" (s: ^Default_Temp_Allocator) {} default_temp_allocator_proc :: nil_allocator_proc @@ -28,7 +28,7 @@ when NO_DEFAULT_TEMP_ALLOCATOR { _ = arena_init(&s.arena, uint(size), backing_allocator) } - default_temp_allocator_destroy :: proc(s: ^Default_Temp_Allocator) { + default_temp_allocator_destroy :: proc "contextless" (s: ^Default_Temp_Allocator) { if s != nil { arena_destroy(&s.arena) s^ = {} @@ -56,7 +56,7 @@ when NO_DEFAULT_TEMP_ALLOCATOR { } @(fini, private) - _destroy_temp_allocator_fini :: proc() { + _destroy_temp_allocator_fini :: proc "contextless" () { default_temp_allocator_destroy(&global_default_temp_allocator_data) } } diff --git a/base/runtime/thread_management.odin b/base/runtime/thread_management.odin index cabd4691c..97dcbc8f5 100644 --- a/base/runtime/thread_management.odin +++ b/base/runtime/thread_management.odin @@ -1,10 +1,14 @@ package runtime -Thread_Local_Cleaner :: #type proc "odin" () +Thread_Local_Cleaner_Odin :: #type proc "odin" () +Thread_Local_Cleaner_Contextless :: #type proc "contextless" () + +Thread_Local_Cleaner :: union #shared_nil {Thread_Local_Cleaner_Odin, Thread_Local_Cleaner_Contextless} @(private="file") thread_local_cleaners: [8]Thread_Local_Cleaner + // Add a procedure that will be run at the end of a thread for the purpose of // deallocating state marked as `thread_local`. // @@ -29,6 +33,9 @@ run_thread_local_cleaners :: proc "odin" () { if p == nil { break } - p() + switch v in p { + case Thread_Local_Cleaner_Odin: v() + case Thread_Local_Cleaner_Contextless: v() + } } } diff --git a/core/encoding/cbor/tags.odin b/core/encoding/cbor/tags.odin index ae1664dfc..be07b926a 100644 --- a/core/encoding/cbor/tags.odin +++ b/core/encoding/cbor/tags.odin @@ -82,14 +82,16 @@ _tag_implementations_id: map[string]Tag_Implementation _tag_implementations_type: map[typeid]Tag_Implementation // Register a custom tag implementation to be used when marshalling that type and unmarshalling that tag number. -tag_register_type :: proc(impl: Tag_Implementation, nr: Tag_Number, type: typeid) { +tag_register_type :: proc "contextless" (impl: Tag_Implementation, nr: Tag_Number, type: typeid) { + context = runtime.default_context() _tag_implementations_nr[nr] = impl _tag_implementations_type[type] = impl } // Register a custom tag implementation to be used when marshalling that tag number or marshalling // a field with the struct tag `cbor_tag:"nr"`. -tag_register_number :: proc(impl: Tag_Implementation, nr: Tag_Number, id: string) { +tag_register_number :: proc "contextless" (impl: Tag_Implementation, nr: Tag_Number, id: string) { + context = runtime.default_context() _tag_implementations_nr[nr] = impl _tag_implementations_id[id] = impl } @@ -98,13 +100,13 @@ tag_register_number :: proc(impl: Tag_Implementation, nr: Tag_Number, id: string INITIALIZE_DEFAULT_TAGS :: #config(CBOR_INITIALIZE_DEFAULT_TAGS, !ODIN_DEFAULT_TO_PANIC_ALLOCATOR && !ODIN_DEFAULT_TO_NIL_ALLOCATOR) @(private, init, disabled=!INITIALIZE_DEFAULT_TAGS) -tags_initialize_defaults :: proc() { +tags_initialize_defaults :: proc "contextless" () { tags_register_defaults() } // Registers tags that have implementations provided by this package. // This is done by default and can be controlled with the `CBOR_INITIALIZE_DEFAULT_TAGS` define. -tags_register_defaults :: proc() { +tags_register_defaults :: proc "contextless" () { tag_register_number({nil, tag_time_unmarshal, tag_time_marshal}, TAG_EPOCH_TIME_NR, TAG_EPOCH_TIME_ID) tag_register_number({nil, tag_base64_unmarshal, tag_base64_marshal}, TAG_BASE64_NR, TAG_BASE64_ID) tag_register_number({nil, tag_cbor_unmarshal, tag_cbor_marshal}, TAG_CBOR_NR, TAG_CBOR_ID) diff --git a/core/image/bmp/bmp.odin b/core/image/bmp/bmp.odin index 057c2ffa0..d5a094e83 100644 --- a/core/image/bmp/bmp.odin +++ b/core/image/bmp/bmp.odin @@ -741,6 +741,6 @@ destroy :: proc(img: ^Image) { } @(init, private) -_register :: proc() { +_register :: proc "contextless" () { image.register(.BMP, load_from_bytes, destroy) } diff --git a/core/image/general.odin b/core/image/general.odin index e92b54f18..336b41d25 100644 --- a/core/image/general.odin +++ b/core/image/general.odin @@ -10,13 +10,13 @@ Destroy_Proc :: #type proc(img: ^Image) _internal_loaders: [Which_File_Type]Loader_Proc _internal_destroyers: [Which_File_Type]Destroy_Proc -register :: proc(kind: Which_File_Type, loader: Loader_Proc, destroyer: Destroy_Proc) { - assert(loader != nil) - assert(destroyer != nil) - assert(_internal_loaders[kind] == nil) +register :: proc "contextless" (kind: Which_File_Type, loader: Loader_Proc, destroyer: Destroy_Proc) { + assert_contextless(loader != nil) + assert_contextless(destroyer != nil) + assert_contextless(_internal_loaders[kind] == nil) _internal_loaders[kind] = loader - assert(_internal_destroyers[kind] == nil) + assert_contextless(_internal_destroyers[kind] == nil) _internal_destroyers[kind] = destroyer } diff --git a/core/image/netpbm/netpbm.odin b/core/image/netpbm/netpbm.odin index a9dc6599a..25e0228b5 100644 --- a/core/image/netpbm/netpbm.odin +++ b/core/image/netpbm/netpbm.odin @@ -720,7 +720,7 @@ autoselect_pbm_format_from_image :: proc(img: ^Image, prefer_binary := true, for } @(init, private) -_register :: proc() { +_register :: proc "contextless" () { loader :: proc(data: []byte, options: image.Options, allocator: mem.Allocator) -> (img: ^Image, err: Error) { return load_from_bytes(data, allocator) } diff --git a/core/image/png/png.odin b/core/image/png/png.odin index 3eb56c245..87efcf9b5 100644 --- a/core/image/png/png.odin +++ b/core/image/png/png.odin @@ -1611,6 +1611,6 @@ defilter :: proc(img: ^Image, filter_bytes: ^bytes.Buffer, header: ^image.PNG_IH } @(init, private) -_register :: proc() { +_register :: proc "contextless" () { image.register(.PNG, load_from_bytes, destroy) } diff --git a/core/image/qoi/qoi.odin b/core/image/qoi/qoi.odin index 6b6149e60..ded8d7971 100644 --- a/core/image/qoi/qoi.odin +++ b/core/image/qoi/qoi.odin @@ -371,6 +371,6 @@ qoi_hash :: #force_inline proc(pixel: RGBA_Pixel) -> (index: u8) { } @(init, private) -_register :: proc() { +_register :: proc "contextless" () { image.register(.QOI, load_from_bytes, destroy) } diff --git a/core/image/tga/tga.odin b/core/image/tga/tga.odin index 46e37a0cf..5fda803c5 100644 --- a/core/image/tga/tga.odin +++ b/core/image/tga/tga.odin @@ -406,6 +406,6 @@ IMAGE_DESCRIPTOR_RIGHT_MASK :: 1<<4 IMAGE_DESCRIPTOR_TOP_MASK :: 1<<5 @(init, private) -_register :: proc() { +_register :: proc "contextless" () { image.register(.TGA, load_from_bytes, destroy) } \ No newline at end of file diff --git a/core/log/file_console_logger.odin b/core/log/file_console_logger.odin index 0fe5c3477..f0acc8a22 100644 --- a/core/log/file_console_logger.odin +++ b/core/log/file_console_logger.odin @@ -43,12 +43,14 @@ File_Console_Logger_Data :: struct { @(private) global_subtract_stderr_options: Options @(init, private) -init_standard_stream_status :: proc() { +init_standard_stream_status :: proc "contextless" () { // NOTE(Feoramund): While it is technically possible for these streams to // be redirected during the runtime of the program, the cost of checking on // every single log message is not worth it to support such an // uncommonly-used feature. if terminal.color_enabled { + context = runtime.default_context() + // This is done this way because it's possible that only one of these // streams could be redirected to a file. if !terminal.is_terminal(os.stdout) { diff --git a/core/math/big/helpers.odin b/core/math/big/helpers.odin index ee09bb2c7..569f0b810 100644 --- a/core/math/big/helpers.odin +++ b/core/math/big/helpers.odin @@ -7,6 +7,7 @@ package math_big import "base:intrinsics" +import "base:runtime" import rnd "core:math/rand" /* @@ -778,22 +779,23 @@ int_from_bytes_little_python :: proc(a: ^Int, buf: []u8, signed := false, alloca INT_ONE, INT_ZERO, INT_MINUS_ONE, INT_INF, INT_MINUS_INF, INT_NAN := &Int{}, &Int{}, &Int{}, &Int{}, &Int{}, &Int{} @(init, private) -_init_constants :: proc() { +_init_constants :: proc "contextless" () { initialize_constants() } -initialize_constants :: proc() -> (res: int) { - internal_set( INT_ZERO, 0); INT_ZERO.flags = {.Immutable} - internal_set( INT_ONE, 1); INT_ONE.flags = {.Immutable} - internal_set(INT_MINUS_ONE, -1); INT_MINUS_ONE.flags = {.Immutable} +initialize_constants :: proc "contextless" () -> (res: int) { + context = runtime.default_context() + internal_int_set_from_integer( INT_ZERO, 0); INT_ZERO.flags = {.Immutable} + internal_int_set_from_integer( INT_ONE, 1); INT_ONE.flags = {.Immutable} + internal_int_set_from_integer(INT_MINUS_ONE, -1); INT_MINUS_ONE.flags = {.Immutable} /* We set these special values to -1 or 1 so they don't get mistake for zero accidentally. This allows for shortcut tests of is_zero as .used == 0. */ - internal_set( INT_NAN, 1); INT_NAN.flags = {.Immutable, .NaN} - internal_set( INT_INF, 1); INT_INF.flags = {.Immutable, .Inf} - internal_set(INT_MINUS_INF, -1); INT_MINUS_INF.flags = {.Immutable, .Inf} + internal_int_set_from_integer( INT_NAN, 1); INT_NAN.flags = {.Immutable, .NaN} + internal_int_set_from_integer( INT_INF, 1); INT_INF.flags = {.Immutable, .Inf} + internal_int_set_from_integer(INT_MINUS_INF, -1); INT_MINUS_INF.flags = {.Immutable, .Inf} return _DEFAULT_MUL_KARATSUBA_CUTOFF } diff --git a/core/math/big/internal.odin b/core/math/big/internal.odin index 4707177c4..8b176e7c0 100644 --- a/core/math/big/internal.odin +++ b/core/math/big/internal.odin @@ -27,10 +27,11 @@ package math_big -import "core:mem" -import "base:intrinsics" -import rnd "core:math/rand" import "base:builtin" +import "base:intrinsics" +import "base:runtime" +import "core:mem" +import rnd "core:math/rand" /* Low-level addition, unsigned. Handbook of Applied Cryptography, algorithm 14.7. @@ -2885,12 +2886,12 @@ internal_clear_if_uninitialized_multi :: proc(args: ..^Int, allocator := context } internal_clear_if_uninitialized :: proc {internal_clear_if_uninitialized_single, internal_clear_if_uninitialized_multi, } -internal_error_if_immutable_single :: proc(arg: ^Int) -> (err: Error) { +internal_error_if_immutable_single :: proc "contextless" (arg: ^Int) -> (err: Error) { if arg != nil && .Immutable in arg.flags { return .Assignment_To_Immutable } return nil } -internal_error_if_immutable_multi :: proc(args: ..^Int) -> (err: Error) { +internal_error_if_immutable_multi :: proc "contextless" (args: ..^Int) -> (err: Error) { for i in args { if i != nil && .Immutable in i.flags { return .Assignment_To_Immutable } } diff --git a/core/mem/virtual/virtual.odin b/core/mem/virtual/virtual.odin index 3027e5848..3f388acf3 100644 --- a/core/mem/virtual/virtual.odin +++ b/core/mem/virtual/virtual.odin @@ -9,7 +9,7 @@ _ :: runtime DEFAULT_PAGE_SIZE := uint(4096) @(init, private) -platform_memory_init :: proc() { +platform_memory_init :: proc "contextless" () { _platform_memory_init() } diff --git a/core/mem/virtual/virtual_linux.odin b/core/mem/virtual/virtual_linux.odin index 3e0d7668b..f819fbf86 100644 --- a/core/mem/virtual/virtual_linux.odin +++ b/core/mem/virtual/virtual_linux.odin @@ -43,10 +43,10 @@ _protect :: proc "contextless" (data: rawptr, size: uint, flags: Protect_Flags) return errno == .NONE } -_platform_memory_init :: proc() { +_platform_memory_init :: proc "contextless" () { DEFAULT_PAGE_SIZE = 4096 // is power of two - assert(DEFAULT_PAGE_SIZE != 0 && (DEFAULT_PAGE_SIZE & (DEFAULT_PAGE_SIZE-1)) == 0) + assert_contextless(DEFAULT_PAGE_SIZE != 0 && (DEFAULT_PAGE_SIZE & (DEFAULT_PAGE_SIZE-1)) == 0) } diff --git a/core/mem/virtual/virtual_other.odin b/core/mem/virtual/virtual_other.odin index a57856975..c6386e842 100644 --- a/core/mem/virtual/virtual_other.odin +++ b/core/mem/virtual/virtual_other.odin @@ -25,7 +25,7 @@ _protect :: proc "contextless" (data: rawptr, size: uint, flags: Protect_Flags) return false } -_platform_memory_init :: proc() { +_platform_memory_init :: proc "contextless" () { } _map_file :: proc "contextless" (fd: uintptr, size: i64, flags: Map_File_Flags) -> (data: []byte, error: Map_File_Error) { diff --git a/core/mem/virtual/virtual_posix.odin b/core/mem/virtual/virtual_posix.odin index 0b304a5e7..4bb161770 100644 --- a/core/mem/virtual/virtual_posix.odin +++ b/core/mem/virtual/virtual_posix.odin @@ -28,13 +28,13 @@ _protect :: proc "contextless" (data: rawptr, size: uint, flags: Protect_Flags) return posix.mprotect(data, size, transmute(posix.Prot_Flags)flags) == .OK } -_platform_memory_init :: proc() { +_platform_memory_init :: proc "contextless" () { // NOTE: `posix.PAGESIZE` due to legacy reasons could be wrong so we use `sysconf`. size := posix.sysconf(._PAGESIZE) DEFAULT_PAGE_SIZE = uint(max(size, posix.PAGESIZE)) // is power of two - assert(DEFAULT_PAGE_SIZE != 0 && (DEFAULT_PAGE_SIZE & (DEFAULT_PAGE_SIZE-1)) == 0) + assert_contextless(DEFAULT_PAGE_SIZE != 0 && (DEFAULT_PAGE_SIZE & (DEFAULT_PAGE_SIZE-1)) == 0) } _map_file :: proc "contextless" (fd: uintptr, size: i64, flags: Map_File_Flags) -> (data: []byte, error: Map_File_Error) { diff --git a/core/mem/virtual/virtual_windows.odin b/core/mem/virtual/virtual_windows.odin index 3fd4eeb68..1d777af17 100644 --- a/core/mem/virtual/virtual_windows.odin +++ b/core/mem/virtual/virtual_windows.odin @@ -146,13 +146,13 @@ _protect :: proc "contextless" (data: rawptr, size: uint, flags: Protect_Flags) @(no_sanitize_address) -_platform_memory_init :: proc() { +_platform_memory_init :: proc "contextless" () { sys_info: SYSTEM_INFO GetSystemInfo(&sys_info) DEFAULT_PAGE_SIZE = max(DEFAULT_PAGE_SIZE, uint(sys_info.dwPageSize)) // is power of two - assert(DEFAULT_PAGE_SIZE != 0 && (DEFAULT_PAGE_SIZE & (DEFAULT_PAGE_SIZE-1)) == 0) + assert_contextless(DEFAULT_PAGE_SIZE != 0 && (DEFAULT_PAGE_SIZE & (DEFAULT_PAGE_SIZE-1)) == 0) } diff --git a/core/net/socket_windows.odin b/core/net/socket_windows.odin index cab820ed5..9127874de 100644 --- a/core/net/socket_windows.odin +++ b/core/net/socket_windows.odin @@ -79,7 +79,7 @@ Shutdown_Manner :: enum c.int { } @(init, private) -ensure_winsock_initialized :: proc() { +ensure_winsock_initialized :: proc "contextless" () { win.ensure_winsock_initialized() } diff --git a/core/os/os2/allocators.odin b/core/os/os2/allocators.odin index cedfbdee1..36a7d72be 100644 --- a/core/os/os2/allocators.odin +++ b/core/os/os2/allocators.odin @@ -16,7 +16,7 @@ MAX_TEMP_ARENA_COLLISIONS :: MAX_TEMP_ARENA_COUNT - 1 global_default_temp_allocator_arenas: [MAX_TEMP_ARENA_COUNT]runtime.Arena @(fini, private) -temp_allocator_fini :: proc() { +temp_allocator_fini :: proc "contextless" () { for &arena in global_default_temp_allocator_arenas { runtime.arena_destroy(&arena) } @@ -69,6 +69,6 @@ _temp_allocator_end :: proc(tmp: runtime.Arena_Temp) { } @(init, private) -init_thread_local_cleaner :: proc() { +init_thread_local_cleaner :: proc "contextless" () { runtime.add_thread_local_cleaner(temp_allocator_fini) } diff --git a/core/os/os2/file_posix.odin b/core/os/os2/file_posix.odin index 2d74618ee..fed8d766c 100644 --- a/core/os/os2/file_posix.odin +++ b/core/os/os2/file_posix.odin @@ -25,8 +25,8 @@ File_Impl :: struct { } @(init) -init_std_files :: proc() { - new_std :: proc(impl: ^File_Impl, fd: posix.FD, name: cstring) -> ^File { +init_std_files :: proc "contextless" () { + new_std :: proc "contextless" (impl: ^File_Impl, fd: posix.FD, name: cstring) -> ^File { impl.file.impl = impl impl.fd = fd impl.allocator = runtime.nil_allocator() diff --git a/core/os/os2/file_wasi.odin b/core/os/os2/file_wasi.odin index 0245841e3..1d417ffb1 100644 --- a/core/os/os2/file_wasi.odin +++ b/core/os/os2/file_wasi.odin @@ -30,8 +30,8 @@ Preopen :: struct { preopens: []Preopen @(init) -init_std_files :: proc() { - new_std :: proc(impl: ^File_Impl, fd: wasi.fd_t, name: string) -> ^File { +init_std_files :: proc "contextless" () { + new_std :: proc "contextless" (impl: ^File_Impl, fd: wasi.fd_t, name: string) -> ^File { impl.file.impl = impl impl.allocator = runtime.nil_allocator() impl.fd = fd diff --git a/core/os/os2/file_windows.odin b/core/os/os2/file_windows.odin index 25e9cb4b0..b39e65fe2 100644 --- a/core/os/os2/file_windows.odin +++ b/core/os/os2/file_windows.odin @@ -43,8 +43,8 @@ File_Impl :: struct { } @(init) -init_std_files :: proc() { - new_std :: proc(impl: ^File_Impl, code: u32, name: string) -> ^File { +init_std_files :: proc "contextless" () { + new_std :: proc "contextless" (impl: ^File_Impl, code: u32, name: string) -> ^File { impl.file.impl = impl impl.allocator = runtime.nil_allocator() @@ -77,7 +77,7 @@ init_std_files :: proc() { stderr = new_std(&files[2], win32.STD_ERROR_HANDLE, "") } -_handle :: proc(f: ^File) -> win32.HANDLE { +_handle :: proc "contextless" (f: ^File) -> win32.HANDLE { return win32.HANDLE(_fd(f)) } @@ -234,7 +234,7 @@ _clone :: proc(f: ^File) -> (clone: ^File, err: Error) { return _new_file(uintptr(clonefd), name(f), file_allocator()) } -_fd :: proc(f: ^File) -> uintptr { +_fd :: proc "contextless" (f: ^File) -> uintptr { if f == nil || f.impl == nil { return INVALID_HANDLE } diff --git a/core/os/os2/path_windows.odin b/core/os/os2/path_windows.odin index e0a00b07a..e5a1545ec 100644 --- a/core/os/os2/path_windows.odin +++ b/core/os/os2/path_windows.odin @@ -160,7 +160,7 @@ _get_executable_path :: proc(allocator: runtime.Allocator) -> (path: string, err can_use_long_paths: bool @(init) -init_long_path_support :: proc() { +init_long_path_support :: proc "contextless" () { can_use_long_paths = false key: win32.HKEY diff --git a/core/os/os_darwin.odin b/core/os/os_darwin.odin index 1010d27a8..77b5825dd 100644 --- a/core/os/os_darwin.odin +++ b/core/os/os_darwin.odin @@ -1226,7 +1226,8 @@ _processor_core_count :: proc() -> int { } @(private, require_results) -_alloc_command_line_arguments :: proc() -> []string { +_alloc_command_line_arguments :: proc "contextless" () -> []string { + context = runtime.default_context() res := make([]string, len(runtime.args__)) for _, i in res { res[i] = string(runtime.args__[i]) @@ -1235,7 +1236,8 @@ _alloc_command_line_arguments :: proc() -> []string { } @(private, fini) -_delete_command_line_arguments :: proc() { +_delete_command_line_arguments :: proc "contextless" () { + context = runtime.default_context() delete(args) } diff --git a/core/os/os_freebsd.odin b/core/os/os_freebsd.odin index aeffdcb87..0542e10dc 100644 --- a/core/os/os_freebsd.odin +++ b/core/os/os_freebsd.odin @@ -965,7 +965,8 @@ _processor_core_count :: proc() -> int { @(private, require_results) -_alloc_command_line_arguments :: proc() -> []string { +_alloc_command_line_arguments :: proc "contextless" () -> []string { + context = runtime.default_context() res := make([]string, len(runtime.args__)) for _, i in res { res[i] = string(runtime.args__[i]) @@ -974,6 +975,7 @@ _alloc_command_line_arguments :: proc() -> []string { } @(private, fini) -_delete_command_line_arguments :: proc() { +_delete_command_line_arguments :: proc "contextless" () { + context = runtime.default_context() delete(args) } diff --git a/core/os/os_haiku.odin b/core/os/os_haiku.odin index b56d516a4..e7c71338b 100644 --- a/core/os/os_haiku.odin +++ b/core/os/os_haiku.odin @@ -317,7 +317,8 @@ file_size :: proc(fd: Handle) -> (i64, Error) { args := _alloc_command_line_arguments() @(private, require_results) -_alloc_command_line_arguments :: proc() -> []string { +_alloc_command_line_arguments :: proc "contextless" () -> []string { + context = runtime.default_context() res := make([]string, len(runtime.args__)) for arg, i in runtime.args__ { res[i] = string(arg) @@ -326,7 +327,8 @@ _alloc_command_line_arguments :: proc() -> []string { } @(private, fini) -_delete_command_line_arguments :: proc() { +_delete_command_line_arguments :: proc "contextless" () { + context = runtime.default_context() delete(args) } diff --git a/core/os/os_linux.odin b/core/os/os_linux.odin index 66c30711d..15d230820 100644 --- a/core/os/os_linux.odin +++ b/core/os/os_linux.odin @@ -1098,7 +1098,8 @@ _processor_core_count :: proc() -> int { } @(private, require_results) -_alloc_command_line_arguments :: proc() -> []string { +_alloc_command_line_arguments :: proc "contextless" () -> []string { + context = runtime.default_context() res := make([]string, len(runtime.args__)) for _, i in res { res[i] = string(runtime.args__[i]) @@ -1107,7 +1108,8 @@ _alloc_command_line_arguments :: proc() -> []string { } @(private, fini) -_delete_command_line_arguments :: proc() { +_delete_command_line_arguments :: proc "contextless" () { + context = runtime.default_context() delete(args) } diff --git a/core/os/os_netbsd.odin b/core/os/os_netbsd.odin index accc5abcd..30511012f 100644 --- a/core/os/os_netbsd.odin +++ b/core/os/os_netbsd.odin @@ -1015,7 +1015,8 @@ _processor_core_count :: proc() -> int { } @(private, require_results) -_alloc_command_line_arguments :: proc() -> []string { +_alloc_command_line_arguments :: proc "contextless" () -> []string { + context = runtime.default_context() res := make([]string, len(runtime.args__)) for _, i in res { res[i] = string(runtime.args__[i]) @@ -1024,6 +1025,7 @@ _alloc_command_line_arguments :: proc() -> []string { } @(private, fini) -_delete_command_line_arguments :: proc() { +_delete_command_line_arguments :: proc "contextless" () { + context = runtime.default_context() delete(args) } diff --git a/core/os/os_openbsd.odin b/core/os/os_openbsd.odin index ec9181ba6..50ee37dff 100644 --- a/core/os/os_openbsd.odin +++ b/core/os/os_openbsd.odin @@ -915,7 +915,8 @@ _processor_core_count :: proc() -> int { } @(private, require_results) -_alloc_command_line_arguments :: proc() -> []string { +_alloc_command_line_arguments :: proc "contextless" () -> []string { + context = runtime.default_context() res := make([]string, len(runtime.args__)) for _, i in res { res[i] = string(runtime.args__[i]) @@ -924,6 +925,7 @@ _alloc_command_line_arguments :: proc() -> []string { } @(private, fini) -_delete_command_line_arguments :: proc() { +_delete_command_line_arguments :: proc "contextless" () { + context = runtime.default_context() delete(args) } diff --git a/core/os/os_wasi.odin b/core/os/os_wasi.odin index f135e4d42..53c242a01 100644 --- a/core/os/os_wasi.odin +++ b/core/os/os_wasi.odin @@ -28,16 +28,18 @@ stderr: Handle = 2 args := _alloc_command_line_arguments() @(private, require_results) -_alloc_command_line_arguments :: proc() -> (args: []string) { - args = make([]string, len(runtime.args__)) +_alloc_command_line_arguments :: proc "contextless" () -> []string { + context = runtime.default_context() + args := make([]string, len(runtime.args__)) for &arg, i in args { arg = string(runtime.args__[i]) } - return + return args } @(private, fini) -_delete_command_line_arguments :: proc() { +_delete_command_line_arguments :: proc "contextless" () { + context = runtime.default_context() delete(args) } diff --git a/core/os/os_windows.odin b/core/os/os_windows.odin index 3c1725cc5..03c194596 100644 --- a/core/os/os_windows.odin +++ b/core/os/os_windows.odin @@ -194,7 +194,8 @@ current_thread_id :: proc "contextless" () -> int { @(private, require_results) -_alloc_command_line_arguments :: proc() -> []string { +_alloc_command_line_arguments :: proc "contextless" () -> []string { + context = runtime.default_context() arg_count: i32 arg_list_ptr := win32.CommandLineToArgvW(win32.GetCommandLineW(), &arg_count) arg_list := make([]string, int(arg_count)) @@ -216,7 +217,8 @@ _alloc_command_line_arguments :: proc() -> []string { } @(private, fini) -_delete_command_line_arguments :: proc() { +_delete_command_line_arguments :: proc "contextless" () { + context = runtime.default_context() for s in args { delete(s) } diff --git a/core/sys/info/cpu_intel.odin b/core/sys/info/cpu_intel.odin index 7c5b38ca4..e8f07c732 100644 --- a/core/sys/info/cpu_intel.odin +++ b/core/sys/info/cpu_intel.odin @@ -52,7 +52,7 @@ CPU :: struct { cpu: CPU @(init, private) -init_cpu_features :: proc "c" () { +init_cpu_features :: proc "contextless" () { is_set :: #force_inline proc "c" (bit: u32, value: u32) -> bool { return (value>>bit) & 0x1 != 0 } @@ -156,7 +156,7 @@ init_cpu_features :: proc "c" () { _cpu_name_buf: [72]u8 @(init, private) -init_cpu_name :: proc "c" () { +init_cpu_name :: proc "contextless" () { number_of_extended_ids, _, _, _ := cpuid(0x8000_0000, 0) if number_of_extended_ids < 0x8000_0004 { return diff --git a/core/sys/info/cpu_linux_arm.odin b/core/sys/info/cpu_linux_arm.odin index cde76a83d..6e8b1a634 100644 --- a/core/sys/info/cpu_linux_arm.odin +++ b/core/sys/info/cpu_linux_arm.odin @@ -2,11 +2,13 @@ #+build linux package sysinfo +import "base:runtime" import "core:sys/linux" import "core:strings" @(init, private) -init_cpu_features :: proc() { +init_cpu_features :: proc "contextless" () { + context = runtime.default_context() fd, err := linux.open("/proc/cpuinfo", {}) if err != .NONE { return } defer linux.close(fd) diff --git a/core/sys/info/cpu_linux_intel.odin b/core/sys/info/cpu_linux_intel.odin index e43737475..af76a75e4 100644 --- a/core/sys/info/cpu_linux_intel.odin +++ b/core/sys/info/cpu_linux_intel.odin @@ -2,12 +2,15 @@ #+build linux package sysinfo +import "base:runtime" import "core:sys/linux" import "core:strings" import "core:strconv" @(init, private) -init_cpu_core_count :: proc() { +init_cpu_core_count :: proc "contextless" () { + context = runtime.default_context() + fd, err := linux.open("/proc/cpuinfo", {}) if err != .NONE { return } defer linux.close(fd) diff --git a/core/sys/info/cpu_windows.odin b/core/sys/info/cpu_windows.odin index 7dd2d2a8c..72d79f9a7 100644 --- a/core/sys/info/cpu_windows.odin +++ b/core/sys/info/cpu_windows.odin @@ -2,9 +2,12 @@ package sysinfo import sys "core:sys/windows" import "base:intrinsics" +import "base:runtime" @(init, private) -init_cpu_core_count :: proc() { +init_cpu_core_count :: proc "contextless" () { + context = runtime.default_context() + infos: []sys.SYSTEM_LOGICAL_PROCESSOR_INFORMATION defer delete(infos) diff --git a/core/sys/info/platform_darwin.odin b/core/sys/info/platform_darwin.odin index 3fc8064ec..07c26ec28 100644 --- a/core/sys/info/platform_darwin.odin +++ b/core/sys/info/platform_darwin.odin @@ -1,5 +1,7 @@ package sysinfo +import "base:runtime" + import "core:strconv" import "core:strings" import "core:sys/unix" @@ -9,7 +11,8 @@ import NS "core:sys/darwin/Foundation" version_string_buf: [1024]u8 @(init, private) -init_platform :: proc() { +init_platform :: proc "contextless" () { + context = runtime.default_context() ws :: strings.write_string wi :: strings.write_int diff --git a/core/sys/info/platform_linux.odin b/core/sys/info/platform_linux.odin index 9c342e567..43cd580c1 100644 --- a/core/sys/info/platform_linux.odin +++ b/core/sys/info/platform_linux.odin @@ -1,6 +1,7 @@ package sysinfo import "base:intrinsics" +import "base:runtime" import "core:strconv" import "core:strings" @@ -10,7 +11,9 @@ import "core:sys/linux" version_string_buf: [1024]u8 @(init, private) -init_os_version :: proc () { +init_os_version :: proc "contextless" () { + context = runtime.default_context() + os_version.platform = .Linux b := strings.builder_from_bytes(version_string_buf[:]) @@ -91,11 +94,11 @@ init_os_version :: proc () { } @(init, private) -init_ram :: proc() { +init_ram :: proc "contextless" () { // Retrieve RAM info using `sysinfo` sys_info: linux.Sys_Info errno := linux.sysinfo(&sys_info) - assert(errno == .NONE, "Good luck to whoever's debugging this, something's seriously cucked up!") + assert_contextless(errno == .NONE, "Good luck to whoever's debugging this, something's seriously cucked up!") ram = RAM{ total_ram = int(sys_info.totalram) * int(sys_info.mem_unit), free_ram = int(sys_info.freeram) * int(sys_info.mem_unit), diff --git a/core/sys/info/platform_windows.odin b/core/sys/info/platform_windows.odin index dd1441d30..ff8ebe2ee 100644 --- a/core/sys/info/platform_windows.odin +++ b/core/sys/info/platform_windows.odin @@ -12,7 +12,9 @@ import "base:runtime" version_string_buf: [1024]u8 @(init, private) -init_os_version :: proc () { +init_os_version :: proc "contextless" () { + context = runtime.default_context() + /* NOTE(Jeroen): `GetVersionEx` will return 6.2 for Windows 10 unless the program is manifested for Windows 10. @@ -43,6 +45,7 @@ init_os_version :: proc () { os_version.minor = int(osvi.dwMinorVersion) os_version.build[0] = int(osvi.dwBuildNumber) + b := strings.builder_from_bytes(version_string_buf[:]) strings.write_string(&b, "Windows ") @@ -259,7 +262,7 @@ init_os_version :: proc () { } @(init, private) -init_ram :: proc() { +init_ram :: proc "contextless" () { state: sys.MEMORYSTATUSEX state.dwLength = size_of(state) @@ -276,10 +279,11 @@ init_ram :: proc() { } @(init, private) -init_gpu_info :: proc() { - +init_gpu_info :: proc "contextless" () { GPU_INFO_BASE :: "SYSTEM\\ControlSet001\\Control\\Class\\{4d36e968-e325-11ce-bfc1-08002be10318}\\" + context = runtime.default_context() + gpu_list: [dynamic]GPU gpu_index: int diff --git a/core/sys/windows/util.odin b/core/sys/windows/util.odin index 10dc907e7..125038ac4 100644 --- a/core/sys/windows/util.odin +++ b/core/sys/windows/util.odin @@ -628,7 +628,7 @@ run_as_user :: proc(username, password, application, commandline: string, pi: ^P } } -ensure_winsock_initialized :: proc() { +ensure_winsock_initialized :: proc "contextless" () { @static gate := false @static initted := false @@ -644,7 +644,7 @@ ensure_winsock_initialized :: proc() { unused_info: WSADATA version_requested := WORD(2) << 8 | 2 res := WSAStartup(version_requested, &unused_info) - assert(res == 0, "unable to initialized Winsock2") + assert_contextless(res == 0, "unable to initialized Winsock2") initted = true } diff --git a/core/terminal/internal.odin b/core/terminal/internal.odin index 44007e14f..9404ff833 100644 --- a/core/terminal/internal.odin +++ b/core/terminal/internal.odin @@ -1,6 +1,7 @@ #+private package terminal +import "base:runtime" import "core:os" import "core:strings" @@ -68,9 +69,11 @@ get_environment_color :: proc() -> Color_Depth { } @(init) -init_terminal :: proc() { +init_terminal :: proc "contextless" () { _init_terminal() + context = runtime.default_context() + // We respect `NO_COLOR` specifically as a color-disabler but not as a // blanket ban on any terminal manipulation codes, hence why this comes // after `_init_terminal` which will allow Windows to enable Virtual @@ -81,6 +84,6 @@ init_terminal :: proc() { } @(fini) -fini_terminal :: proc() { +fini_terminal :: proc "contextless" () { _fini_terminal() } diff --git a/core/terminal/terminal_js.odin b/core/terminal/terminal_js.odin index 2d880420b..4dcd4465e 100644 --- a/core/terminal/terminal_js.odin +++ b/core/terminal/terminal_js.odin @@ -4,12 +4,12 @@ package terminal import "core:os" -_is_terminal :: proc(handle: os.Handle) -> bool { +_is_terminal :: proc "contextless" (handle: os.Handle) -> bool { return true } -_init_terminal :: proc() { +_init_terminal :: proc "contextless" () { color_depth = .None } -_fini_terminal :: proc() { } \ No newline at end of file +_fini_terminal :: proc "contextless" () { } \ No newline at end of file diff --git a/core/terminal/terminal_posix.odin b/core/terminal/terminal_posix.odin index f578e12c6..8d96dd256 100644 --- a/core/terminal/terminal_posix.odin +++ b/core/terminal/terminal_posix.odin @@ -2,15 +2,17 @@ #+build linux, darwin, netbsd, openbsd, freebsd, haiku package terminal +import "base:runtime" import "core:os" import "core:sys/posix" -_is_terminal :: proc(handle: os.Handle) -> bool { +_is_terminal :: proc "contextless" (handle: os.Handle) -> bool { return bool(posix.isatty(posix.FD(handle))) } -_init_terminal :: proc() { +_init_terminal :: proc "contextless" () { + context = runtime.default_context() color_depth = get_environment_color() } -_fini_terminal :: proc() { } +_fini_terminal :: proc "contextless" () { } diff --git a/core/terminal/terminal_windows.odin b/core/terminal/terminal_windows.odin index 18ec98332..6d5f98a1f 100644 --- a/core/terminal/terminal_windows.odin +++ b/core/terminal/terminal_windows.odin @@ -1,10 +1,11 @@ #+private package terminal +import "base:runtime" import "core:os" import "core:sys/windows" -_is_terminal :: proc(handle: os.Handle) -> bool { +_is_terminal :: proc "contextless" (handle: os.Handle) -> bool { is_tty := windows.GetFileType(windows.HANDLE(handle)) == windows.FILE_TYPE_CHAR return is_tty } @@ -18,7 +19,7 @@ old_modes: [2]struct{ } @(init) -_init_terminal :: proc() { +_init_terminal :: proc "contextless" () { vtp_enabled: bool for &v in old_modes { @@ -42,13 +43,15 @@ _init_terminal :: proc() { // This color depth is available on Windows 10 since build 10586. color_depth = .Four_Bit } else { + context = runtime.default_context() + // The user may be on a non-default terminal emulator. color_depth = get_environment_color() } } @(fini) -_fini_terminal :: proc() { +_fini_terminal :: proc "contextless" () { for v in old_modes { handle := windows.GetStdHandle(v.handle) if handle == windows.INVALID_HANDLE || handle == nil { diff --git a/src/checker.cpp b/src/checker.cpp index a13290750..f631a1412 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -2675,6 +2675,10 @@ gb_internal void generate_minimum_dependency_set_internal(Checker *c, Entity *st is_init = false; } + if (t->Proc.calling_convention != ProcCC_Contextless) { + error(e->token, "@(init) procedures must be declared as \"contextless\""); + } + if ((e->scope->flags & (ScopeFlag_File|ScopeFlag_Pkg)) == 0) { error(e->token, "@(init) procedures must be declared at the file scope"); is_init = false; @@ -2689,6 +2693,7 @@ gb_internal void generate_minimum_dependency_set_internal(Checker *c, Entity *st error(e->token, "An @(init) procedure must not use a blank identifier as its name"); } + if (is_init) { add_dependency_to_set(c, e); array_add(&c->info.init_procedures, e); @@ -2706,6 +2711,10 @@ gb_internal void generate_minimum_dependency_set_internal(Checker *c, Entity *st is_fini = false; } + if (t->Proc.calling_convention != ProcCC_Contextless) { + error(e->token, "@(fini) procedures must be declared as \"contextless\""); + } + if ((e->scope->flags & (ScopeFlag_File|ScopeFlag_Pkg)) == 0) { error(e->token, "@(fini) procedures must be declared at the file scope"); is_fini = false; diff --git a/vendor/miniaudio/common.odin b/vendor/miniaudio/common.odin index 0263278bc..e675cb7f6 100644 --- a/vendor/miniaudio/common.odin +++ b/vendor/miniaudio/common.odin @@ -25,7 +25,7 @@ BINDINGS_VERSION :: [3]u32{BINDINGS_VERSION_MAJOR, BINDINGS_VERSION_MIN BINDINGS_VERSION_STRING :: "0.11.22" @(init) -version_check :: proc() { +version_check :: proc "contextless" () { v: [3]u32 version(&v.x, &v.y, &v.z) if v != BINDINGS_VERSION { @@ -43,7 +43,7 @@ version_check :: proc() { n += copy(buf[n:], "and executing `make`") } - panic(string(buf[:n])) + panic_contextless(string(buf[:n])) } } From 8b860da2eb5f65ac23702d7f139da46646ba2ec1 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 8 Aug 2025 12:12:08 +0100 Subject: [PATCH 036/105] Remove unused import --- core/math/big/internal.odin | 1 - 1 file changed, 1 deletion(-) diff --git a/core/math/big/internal.odin b/core/math/big/internal.odin index 8b176e7c0..e0bc1ae06 100644 --- a/core/math/big/internal.odin +++ b/core/math/big/internal.odin @@ -29,7 +29,6 @@ package math_big import "base:builtin" import "base:intrinsics" -import "base:runtime" import "core:mem" import rnd "core:math/rand" From b86932c03c51efbb6c6146f8c91dd03bf82ab226 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 8 Aug 2025 12:21:50 +0100 Subject: [PATCH 037/105] Disallow `proc "odin"` procedures to be called in the global scope in variable declarations --- src/check_decl.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/check_decl.cpp b/src/check_decl.cpp index af46ee40e..ee7906e5e 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -1851,6 +1851,12 @@ gb_internal void check_entity_decl(CheckerContext *ctx, Entity *e, DeclInfo *d, c.scope = d->scope; c.decl = d; c.type_level = 0; + c.curr_proc_calling_convention = ProcCC_Contextless; + + auto prev_flags = c.scope->flags; + defer (c.scope->flags = prev_flags); + c.scope->flags &= ~ScopeFlag_ContextDefined; + e->parent_proc_decl = c.curr_proc_decl; e->state = EntityState_InProgress; From 06e48099ca808dc9d5b3fbcaebebd4123f097a86 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 8 Aug 2025 12:23:22 +0100 Subject: [PATCH 038/105] Improve error message --- src/check_expr.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/check_expr.cpp b/src/check_expr.cpp index faa338f36..e3881986b 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -8166,8 +8166,12 @@ gb_internal ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *c if (pt->kind == Type_Proc && pt->Proc.calling_convention == ProcCC_Odin) { if ((c->scope->flags & ScopeFlag_ContextDefined) == 0) { ERROR_BLOCK(); - error(call, "'context' has not been defined within this scope, but is required for this procedure call"); - error_line("\tSuggestion: 'context = runtime.default_context()'"); + if (c->scope->flags & ScopeFlag_File) { + error(call, "Procedures requiring a 'context' cannot be called at the global scope"); + } else { + error(call, "'context' has not been defined within this scope, but is required for this procedure call"); + error_line("\tSuggestion: 'context = runtime.default_context()'"); + } } } From d3f649d244529d93b489140e5c7a1aaff97bedb2 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 8 Aug 2025 12:25:58 +0100 Subject: [PATCH 039/105] Make `get_args` contextless --- core/os/os2/process.odin | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/core/os/os2/process.odin b/core/os/os2/process.odin index 3c84f3539..635befc64 100644 --- a/core/os/os2/process.odin +++ b/core/os/os2/process.odin @@ -16,7 +16,8 @@ Arguments to the current process. args := get_args() @(private="file") -get_args :: proc() -> []string { +get_args :: proc "contextless" () -> []string { + context = runtime.default_context() result := make([]string, len(runtime.args__), heap_allocator()) for rt_arg, i in runtime.args__ { result[i] = string(rt_arg) @@ -24,6 +25,12 @@ get_args :: proc() -> []string { return result } +@(fini, private="file") +delete_args :: proc "contextless" () { + context = runtime.default_context() + delete(args, heap_allocator()) +} + /* Exit the current process. */ From d381d0ece4b9cd5fcf454fbd7ca79969d2b76cb8 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 8 Aug 2025 12:33:34 +0100 Subject: [PATCH 040/105] Fix more procedure to be `contextless` --- core/flags/rtti.odin | 2 +- core/sys/posix/stdlib_libc.odin | 2 +- tests/core/flags/test_core_flags.odin | 2 +- tests/core/normal.odin | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/core/flags/rtti.odin b/core/flags/rtti.odin index ce7a23773..058292698 100644 --- a/core/flags/rtti.odin +++ b/core/flags/rtti.odin @@ -38,6 +38,6 @@ Note that only one can be active at a time. Inputs: - setter: The type setter. Pass `nil` to disable any previously set setter. */ -register_type_setter :: proc(setter: Custom_Type_Setter) { +register_type_setter :: proc "contextless" (setter: Custom_Type_Setter) { global_custom_type_setter = setter } diff --git a/core/sys/posix/stdlib_libc.odin b/core/sys/posix/stdlib_libc.odin index e31c51704..966dc1d32 100644 --- a/core/sys/posix/stdlib_libc.odin +++ b/core/sys/posix/stdlib_libc.odin @@ -60,7 +60,7 @@ wctomb :: libc.wctomb mbstowcs :: libc.mbstowcs wcstombs :: libc.wcstombs -free :: #force_inline proc(ptr: $T) where intrinsics.type_is_pointer(T) || intrinsics.type_is_multi_pointer(T) || T == cstring { +free :: #force_inline proc "c" (ptr: $T) where intrinsics.type_is_pointer(T) || intrinsics.type_is_multi_pointer(T) || T == cstring { libc.free(rawptr(ptr)) } diff --git a/tests/core/flags/test_core_flags.odin b/tests/core/flags/test_core_flags.odin index 0527d85c5..0cfcf8e75 100644 --- a/tests/core/flags/test_core_flags.odin +++ b/tests/core/flags/test_core_flags.odin @@ -17,7 +17,7 @@ Custom_Data :: struct { } @(init) -init_custom_type_setter :: proc() { +init_custom_type_setter :: proc "contextless" () { // NOTE: This is done here so it can be out of the flow of the // multi-threaded test runner, to prevent any data races that could be // reported by using `-sanitize:thread`. diff --git a/tests/core/normal.odin b/tests/core/normal.odin index 5bc73bd24..a64f38209 100644 --- a/tests/core/normal.odin +++ b/tests/core/normal.odin @@ -2,10 +2,10 @@ package tests_core import rlibc "core:c/libc" -@(init) +@(init="contextless") download_assets :: proc() { if rlibc.system("python3 " + ODIN_ROOT + "tests/core/download_assets.py " + ODIN_ROOT + "tests/core/assets") != 0 { - panic("downloading test assets failed!") + panic_contextless("downloading test assets failed!") } } From 414b1059a80b6fd96e839d761c71338a60b697ec Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 8 Aug 2025 12:36:56 +0100 Subject: [PATCH 041/105] Fix typo --- tests/core/normal.odin | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/core/normal.odin b/tests/core/normal.odin index a64f38209..fe69acf64 100644 --- a/tests/core/normal.odin +++ b/tests/core/normal.odin @@ -2,8 +2,8 @@ package tests_core import rlibc "core:c/libc" -@(init="contextless") -download_assets :: proc() { +@(init) +download_assets :: proc "contextless" () { if rlibc.system("python3 " + ODIN_ROOT + "tests/core/download_assets.py " + ODIN_ROOT + "tests/core/assets") != 0 { panic_contextless("downloading test assets failed!") } From 0c7260e7010461f1321c9c3f7d50f2f35f89abb1 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 8 Aug 2025 12:37:36 +0100 Subject: [PATCH 042/105] Update src/main.cpp Co-authored-by: Itzik Shneorson <35134559+itziksn@users.noreply.github.com> --- src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.cpp b/src/main.cpp index 2f0b1c19b..06b9cab94 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2583,7 +2583,7 @@ gb_internal int print_show_help(String const arg0, String command, String option } if (check) { - if (print_flag("-integer-division-by-zero:")) { + if (print_flag("-integer-division-by-zero:")) { print_usage_line(2, "Specifies the default behaviour for integer division by zero."); print_usage_line(2, "Available Options:"); print_usage_line(3, "-integer-division-by-zero:trap Trap on division/modulo/remainder by zero"); From 78290ceef38e7fff9b605c168eed5f24d65895c2 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 8 Aug 2025 12:38:20 +0100 Subject: [PATCH 043/105] Add contextless to another proc --- core/os/os2/file_linux.odin | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/os/os2/file_linux.odin b/core/os/os2/file_linux.odin index b1d11b425..92f0c1541 100644 --- a/core/os/os2/file_linux.odin +++ b/core/os/os2/file_linux.odin @@ -45,8 +45,8 @@ _stderr := File{ } @init -_standard_stream_init :: proc() { - new_std :: proc(impl: ^File_Impl, fd: linux.Fd, name: string) -> ^File { +_standard_stream_init :: proc "contextless" () { + new_std :: proc "contextless" (impl: ^File_Impl, fd: linux.Fd, name: string) -> ^File { impl.file.impl = impl impl.fd = linux.Fd(fd) impl.allocator = runtime.nil_allocator() From a0462aa8d7bd622d70d8c0d4a25dddbe081dc86d Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 8 Aug 2025 12:49:24 +0100 Subject: [PATCH 044/105] Fix test for global procedure initialization --- tests/internal/test_global_any.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/internal/test_global_any.odin b/tests/internal/test_global_any.odin index 73b70e0a4..850884912 100644 --- a/tests/internal/test_global_any.odin +++ b/tests/internal/test_global_any.odin @@ -3,7 +3,7 @@ package test_internal @(private="file") global_any_from_proc: any = from_proc() -from_proc :: proc() -> f32 { +from_proc :: proc "contextless" () -> f32 { return 1.1 } From aa747a1c10c3b20c589e610d1f7dffe4ddaff4fa Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 8 Aug 2025 12:55:23 +0100 Subject: [PATCH 045/105] Add more "contextless" --- core/sys/info/platform_bsd.odin | 6 ++++-- core/sys/info/platform_freebsd.odin | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/core/sys/info/platform_bsd.odin b/core/sys/info/platform_bsd.odin index 6bb32cd3d..2f8d7f5bb 100644 --- a/core/sys/info/platform_bsd.odin +++ b/core/sys/info/platform_bsd.odin @@ -10,7 +10,9 @@ import "base:runtime" version_string_buf: [1024]u8 @(init, private) -init_os_version :: proc () { +init_os_version :: proc "contextless" () { + context = runtime.default_context() + when ODIN_OS == .NetBSD { os_version.platform = .NetBSD } else { @@ -66,7 +68,7 @@ init_os_version :: proc () { } @(init, private) -init_ram :: proc() { +init_ram :: proc "contextless" () { // Retrieve RAM info using `sysctl` mib := []i32{sys.CTL_HW, sys.HW_PHYSMEM64} mem_size: u64 diff --git a/core/sys/info/platform_freebsd.odin b/core/sys/info/platform_freebsd.odin index b26fb7875..eb39769de 100644 --- a/core/sys/info/platform_freebsd.odin +++ b/core/sys/info/platform_freebsd.odin @@ -9,7 +9,9 @@ import "base:runtime" version_string_buf: [1024]u8 @(init, private) -init_os_version :: proc () { +init_os_version :: proc "contextless" () { + context = runtime.default_context() + os_version.platform = .FreeBSD kernel_version_buf: [1024]u8 @@ -68,7 +70,7 @@ init_os_version :: proc () { } @(init, private) -init_ram :: proc() { +init_ram :: proc "contextless" () { // Retrieve RAM info using `sysctl` mib := []i32{sys.CTL_HW, sys.HW_PHYSMEM} mem_size: u64 From 8ff15eaf6905eb167dc541cd2558599a0a334c28 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 8 Aug 2025 13:02:37 +0100 Subject: [PATCH 046/105] More contextless fixes --- core/os/os2/process_posix_darwin.odin | 2 +- core/os/os_wasi.odin | 13 +++++++------ core/sys/info/cpu_linux_riscv64.odin | 8 ++++---- core/sys/unix/sysctl_freebsd.odin | 2 +- 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/core/os/os2/process_posix_darwin.odin b/core/os/os2/process_posix_darwin.odin index 7625e513a..f655d42a9 100644 --- a/core/os/os2/process_posix_darwin.odin +++ b/core/os/os2/process_posix_darwin.odin @@ -13,7 +13,7 @@ import "core:time" foreign import lib "system:System" foreign lib { - sysctl :: proc( + sysctl :: proc "c" ( name: [^]i32, namelen: u32, oldp: rawptr, oldlenp: ^uint, newp: rawptr, newlen: uint, diff --git a/core/os/os_wasi.odin b/core/os/os_wasi.odin index 53c242a01..fe0a1fb3e 100644 --- a/core/os/os_wasi.odin +++ b/core/os/os_wasi.odin @@ -30,11 +30,11 @@ args := _alloc_command_line_arguments() @(private, require_results) _alloc_command_line_arguments :: proc "contextless" () -> []string { context = runtime.default_context() - args := make([]string, len(runtime.args__)) - for &arg, i in args { + cmd_args := make([]string, len(runtime.args__)) + for &arg, i in cmd_args { arg = string(runtime.args__[i]) } - return args + return cmd_args } @(private, fini) @@ -59,9 +59,8 @@ Preopen :: struct { preopens: []Preopen @(init, private) -init_preopens :: proc() { - - strip_prefixes :: proc(path: string) -> string { +init_preopens :: proc "contextless" () { + strip_prefixes :: proc "contextless"(path: string) -> string { path := path loop: for len(path) > 0 { switch { @@ -78,6 +77,8 @@ init_preopens :: proc() { return path } + context = runtime.default_context() + dyn_preopens: [dynamic]Preopen loop: for fd := wasi.fd_t(3); ; fd += 1 { desc, err := wasi.fd_prestat_get(fd) diff --git a/core/sys/info/cpu_linux_riscv64.odin b/core/sys/info/cpu_linux_riscv64.odin index 3d36d126d..39ed69240 100644 --- a/core/sys/info/cpu_linux_riscv64.odin +++ b/core/sys/info/cpu_linux_riscv64.odin @@ -7,7 +7,7 @@ import "base:intrinsics" import "core:sys/linux" @(init, private) -init_cpu_features :: proc() { +init_cpu_features :: proc "contextless" () { _features: CPU_Features defer cpu.features = _features @@ -85,7 +85,7 @@ init_cpu_features :: proc() { return } - assert(pairs[0].key == .IMA_EXT_0) + assert_contextless(pairs[0].key == .IMA_EXT_0) exts := pairs[0].value.ima_ext_0 exts -= { .FD, .C, .V } _features += transmute(CPU_Features)exts @@ -97,7 +97,7 @@ init_cpu_features :: proc() { _features += { .Misaligned_Supported } } } else { - assert(pairs[1].key == .CPUPERF_0) + assert_contextless(pairs[1].key == .CPUPERF_0) if .FAST in pairs[1].value.cpu_perf_0 { _features += { .Misaligned_Supported, .Misaligned_Fast } } else if .UNSUPPORTED not_in pairs[1].value.cpu_perf_0 { @@ -108,6 +108,6 @@ init_cpu_features :: proc() { } @(init, private) -init_cpu_name :: proc() { +init_cpu_name :: proc "contextless" () { cpu.name = "RISCV64" } diff --git a/core/sys/unix/sysctl_freebsd.odin b/core/sys/unix/sysctl_freebsd.odin index f5fee6c6c..cdd591a5b 100644 --- a/core/sys/unix/sysctl_freebsd.odin +++ b/core/sys/unix/sysctl_freebsd.odin @@ -3,7 +3,7 @@ package unix import "base:intrinsics" -sysctl :: proc(mib: []i32, val: ^$T) -> (ok: bool) { +sysctl :: proc "contextless" (mib: []i32, val: ^$T) -> (ok: bool) { mib := mib result_size := u64(size_of(T)) From 7c93a5ae802b5a17aff6fea7368f9b27deed6517 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 8 Aug 2025 13:16:20 +0100 Subject: [PATCH 047/105] Add missing `contextless` --- core/sys/info/cpu_linux_riscv64.odin | 2 +- core/sys/unix/sysctl_openbsd.odin | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/sys/info/cpu_linux_riscv64.odin b/core/sys/info/cpu_linux_riscv64.odin index 39ed69240..e65e8a3d2 100644 --- a/core/sys/info/cpu_linux_riscv64.odin +++ b/core/sys/info/cpu_linux_riscv64.odin @@ -81,7 +81,7 @@ init_cpu_features :: proc "contextless" () { } err := linux.riscv_hwprobe(raw_data(pairs), len(pairs), 0, nil, {}) if err != nil { - assert(err == .ENOSYS, "unexpected error from riscv_hwprobe()") + assert_contextless(err == .ENOSYS, "unexpected error from riscv_hwprobe()") return } diff --git a/core/sys/unix/sysctl_openbsd.odin b/core/sys/unix/sysctl_openbsd.odin index 49c9b6336..e71b743f8 100644 --- a/core/sys/unix/sysctl_openbsd.odin +++ b/core/sys/unix/sysctl_openbsd.odin @@ -9,7 +9,7 @@ foreign libc { @(link_name="sysctl") _unix_sysctl :: proc(name: [^]i32, namelen: u32, oldp: rawptr, oldlenp: ^c.size_t, newp: rawptr, newlen: c.size_t) -> i32 --- } -sysctl :: proc(mib: []i32, val: ^$T) -> (ok: bool) { +sysctl :: proc "contextless" (mib: []i32, val: ^$T) -> (ok: bool) { mib := mib result_size := c.size_t(size_of(T)) res := _unix_sysctl(raw_data(mib), u32(len(mib)), val, &result_size, nil, 0) From 804984ed35faceee3e7629dff0c8d9df86db3d98 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 8 Aug 2025 13:29:49 +0100 Subject: [PATCH 048/105] `contextless` fixes for `js` --- base/runtime/procs_js.odin | 4 ++-- vendor/libc/libc.odin | 4 ++-- vendor/libc/stdlib.odin | 2 +- vendor/wgpu/wgpu_js.odin | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/base/runtime/procs_js.odin b/base/runtime/procs_js.odin index 58bed808d..3690f9436 100644 --- a/base/runtime/procs_js.odin +++ b/base/runtime/procs_js.odin @@ -3,8 +3,8 @@ package runtime init_default_context_for_js: Context @(init, private="file") -init_default_context :: proc() { - init_default_context_for_js = context +init_default_context :: proc "contextless" () { + __init_context(&init_default_context_for_js) } @(export) diff --git a/vendor/libc/libc.odin b/vendor/libc/libc.odin index 00d687109..3ec25aacf 100644 --- a/vendor/libc/libc.odin +++ b/vendor/libc/libc.odin @@ -10,8 +10,8 @@ g_ctx: runtime.Context g_allocator: mem.Compat_Allocator @(init) -init_context :: proc() { - g_ctx = context +init_context :: proc "contextless" () { + g_ctx = runtime.default_context() // Wrapping the allocator with the mem.Compat_Allocator so we can // mimic the realloc semantics. diff --git a/vendor/libc/stdlib.odin b/vendor/libc/stdlib.odin index 9f578a436..bb9233a28 100644 --- a/vendor/libc/stdlib.odin +++ b/vendor/libc/stdlib.odin @@ -169,7 +169,7 @@ exit :: proc "c" (exit_code: c.int) -> ! { } @(private, fini) -finish_atexit :: proc "c" () { +finish_atexit :: proc "contextless" () { n := intrinsics.atomic_exchange(&atexit_functions_count, 0) for function in atexit_functions[:n] { function() diff --git a/vendor/wgpu/wgpu_js.odin b/vendor/wgpu/wgpu_js.odin index 3c8375adb..3217a97dc 100644 --- a/vendor/wgpu/wgpu_js.odin +++ b/vendor/wgpu/wgpu_js.odin @@ -5,7 +5,7 @@ import "base:runtime" g_context: runtime.Context @(private="file", init) -wgpu_init_allocator :: proc() { +wgpu_init_allocator :: proc "contextless" () { if g_context.allocator.procedure == nil { g_context = runtime.default_context() } From 0f5ced52a0f87187ac3099238c726d1230aaabbd Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 8 Aug 2025 13:42:48 +0100 Subject: [PATCH 049/105] Assign `context` in scope --- vendor/libc/libc.odin | 1 + 1 file changed, 1 insertion(+) diff --git a/vendor/libc/libc.odin b/vendor/libc/libc.odin index 3ec25aacf..a5508e14f 100644 --- a/vendor/libc/libc.odin +++ b/vendor/libc/libc.odin @@ -12,6 +12,7 @@ g_allocator: mem.Compat_Allocator @(init) init_context :: proc "contextless" () { g_ctx = runtime.default_context() + context = g_ctx // Wrapping the allocator with the mem.Compat_Allocator so we can // mimic the realloc semantics. From 443dd566e39721d3e5321212fcfc418d7a7d43fe Mon Sep 17 00:00:00 2001 From: xenobas Date: Fri, 8 Aug 2025 14:40:43 +0100 Subject: [PATCH 050/105] Add a better suggestion for cases that don't need ^ operator --- src/check_expr.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/check_expr.cpp b/src/check_expr.cpp index aa9c8837d..f314ce3cd 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -2455,7 +2455,8 @@ gb_internal void check_assignment_error_suggestion(CheckerContext *c, Operand *o } else if (is_type_pointer(o->type) && are_types_identical(type_deref(o->type), type)) { gbString s = expr_to_string(o->expr); - error_line("\tSuggestion: Did you mean `%s^`\n", s); + if (s[0] == '&') error_line("\tSuggestion: Did you mean `%s`\n", &s[1]); + else error_line("\tSuggestion: Did you mean `%s^`\n", s); gb_string_free(s); } } From 14ca1c8c89dd219dd52d061649d4db7778df2e64 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 8 Aug 2025 15:41:44 +0100 Subject: [PATCH 051/105] Add another `contextless` --- core/sys/unix/sysctl_netbsd.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/sys/unix/sysctl_netbsd.odin b/core/sys/unix/sysctl_netbsd.odin index ad89b9ad4..b70740721 100644 --- a/core/sys/unix/sysctl_netbsd.odin +++ b/core/sys/unix/sysctl_netbsd.odin @@ -8,7 +8,7 @@ foreign libc { @(link_name="sysctl") _unix_sysctl :: proc(name: [^]i32, namelen: u32, oldp: rawptr, oldlenp: ^c.size_t, newp: rawptr, newlen: c.size_t) -> i32 --- } -sysctl :: proc(mib: []i32, val: ^$T) -> (ok: bool) { +sysctl :: proc "contextless" (mib: []i32, val: ^$T) -> (ok: bool) { mib := mib result_size := c.size_t(size_of(T)) res := _unix_sysctl(raw_data(mib), u32(len(mib)), val, &result_size, nil, 0) From 5db6ea8354ec19b0800839d770f6216fde6027c5 Mon Sep 17 00:00:00 2001 From: janga-perlind Date: Sat, 9 Aug 2025 12:37:15 +1000 Subject: [PATCH 052/105] Do not check for explicit allocators when determining proc in proc group --- src/check_expr.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/check_expr.cpp b/src/check_expr.cpp index b4cfaaf00..6a50b553e 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -6147,7 +6147,8 @@ gb_internal CallArgumentError check_call_arguments_internal(CheckerContext *c, A Entity *entity, Type *proc_type, Array positional_operands, Array const &named_operands, CallArgumentErrorMode show_error_mode, - CallArgumentData *data) { + CallArgumentData *data, + bool checking_proc_group) { TEMPORARY_ALLOCATOR_GUARD(); CallArgumentError err = CallArgumentError_None; @@ -6314,7 +6315,7 @@ gb_internal CallArgumentError check_call_arguments_internal(CheckerContext *c, A bool context_allocator_error = false; if (e->kind == Entity_Variable) { if (e->Variable.param_value.kind != ParameterValue_Invalid) { - if (ast_file_vet_explicit_allocators(c->file)) { + if (ast_file_vet_explicit_allocators(c->file) && !checking_proc_group) { // NOTE(lucas): check if we are trying to default to context.allocator or context.temp_allocator if (e->Variable.param_value.original_ast_expr->kind == Ast_SelectorExpr) { auto& expr = e->Variable.param_value.original_ast_expr->SelectorExpr.expr; @@ -6741,7 +6742,8 @@ gb_internal bool check_call_arguments_single(CheckerContext *c, Ast *call, Opera Entity *e, Type *proc_type, Array const &positional_operands, Array const &named_operands, CallArgumentErrorMode show_error_mode, - CallArgumentData *data) { + CallArgumentData *data, + bool checking_proc_group) { bool return_on_failure = show_error_mode == CallArgumentErrorMode::NoErrors; @@ -6765,7 +6767,7 @@ gb_internal bool check_call_arguments_single(CheckerContext *c, Ast *call, Opera } GB_ASSERT(proc_type->kind == Type_Proc); - CallArgumentError err = check_call_arguments_internal(c, call, e, proc_type, positional_operands, named_operands, show_error_mode, data); + CallArgumentError err = check_call_arguments_internal(c, call, e, proc_type, positional_operands, named_operands, show_error_mode, data, checking_proc_group); if (return_on_failure && err != CallArgumentError_None) { return false; } @@ -6919,7 +6921,7 @@ gb_internal CallArgumentData check_call_arguments_proc_group(CheckerContext *c, e, e->type, positional_operands, named_operands, CallArgumentErrorMode::ShowErrors, - &data); + &data, false); } return data; } @@ -7063,7 +7065,7 @@ gb_internal CallArgumentData check_call_arguments_proc_group(CheckerContext *c, p, pt, positional_operands, named_operands, CallArgumentErrorMode::NoErrors, - &data); + &data, true); if (!is_a_candidate) { continue; } @@ -7372,7 +7374,7 @@ gb_internal CallArgumentData check_call_arguments_proc_group(CheckerContext *c, e, e->type, positional_operands, named_operands, CallArgumentErrorMode::ShowErrors, - &data); + &data, false); return data; } @@ -7485,7 +7487,7 @@ gb_internal CallArgumentData check_call_arguments(CheckerContext *c, Operand *op nullptr, proc_type, positional_operands, named_operands, CallArgumentErrorMode::ShowErrors, - &data); + &data, false); } else if (pt) { data.result_type = pt->results; } From 277c6cac7175d78bd2e42db17e7ca7475ec6d574 Mon Sep 17 00:00:00 2001 From: Alex Riedl Date: Sat, 9 Aug 2025 10:47:07 -0500 Subject: [PATCH 053/105] Fix some webgl bindings --- core/sys/wasm/js/odin.js | 37 ++++++++++++++++++++ vendor/wasm/WebGL/webgl.odin | 66 ++++++++++++++++++++++++++++++----- vendor/wasm/WebGL/webgl2.odin | 2 +- 3 files changed, 96 insertions(+), 9 deletions(-) diff --git a/core/sys/wasm/js/odin.js b/core/sys/wasm/js/odin.js index 37a57a59d..1fbcc886e 100644 --- a/core/sys/wasm/js/odin.js +++ b/core/sys/wasm/js/odin.js @@ -392,6 +392,9 @@ class WebGLInterface { BindTexture: (target, texture) => { this.ctx.bindTexture(target, texture ? this.textures[texture] : null) }, + BindRenderbuffer: (target, renderbuffer) => { + this.ctx.bindRenderbuffer(target, renderbuffer ? this.renderbuffers[renderbuffer] : null) + }, BlendColor: (red, green, blue, alpha) => { this.ctx.blendColor(red, green, blue, alpha); }, @@ -809,6 +812,40 @@ class WebGLInterface { Uniform3i: (location, v0, v1, v2) => { this.ctx.uniform3i(this.uniforms[location], v0, v1, v2); }, Uniform4i: (location, v0, v1, v2, v3) => { this.ctx.uniform4i(this.uniforms[location], v0, v1, v2, v3); }, + Uniform1fv: (location, count, addr) => { + let array = this.mem.loadF32Array(addr, 1*count); + this.ctx.uniform1fv(this.uniforms[location], array); + }, + Uniform2fv: (location, count, addr) => { + let array = this.mem.loadF32Array(addr, 2*count); + this.ctx.uniform2fv(this.uniforms[location], array); + }, + Uniform3fv: (location, count, addr) => { + let array = this.mem.loadF32Array(addr, 3*count); + this.ctx.uniform3fv(this.uniforms[location], array); + }, + Uniform4fv: (location, count, addr) => { + let array = this.mem.loadF32Array(addr, 4*count); + this.ctx.uniform4fv(this.uniforms[location], array); + }, + + Uniform1iv: (location, count, addr) => { + let array = this.mem.loadI32Array(addr, 1*count); + this.ctx.uniform1iv(this.uniforms[location], array); + }, + Uniform2iv: (location, count, addr) => { + let array = this.mem.loadI32Array(addr, 2*count); + this.ctx.uniform2iv(this.uniforms[location], array); + }, + Uniform3iv: (location, count, addr) => { + let array = this.mem.loadI32Array(addr, 3*count); + this.ctx.uniform3iv(this.uniforms[location], array); + }, + Uniform4iv: (location, count, addr) => { + let array = this.mem.loadI32Array(addr, 4*count); + this.ctx.uniform4iv(this.uniforms[location], array); + }, + UniformMatrix2fv: (location, addr) => { let array = this.mem.loadF32Array(addr, 2*2); this.ctx.uniformMatrix2fv(this.uniforms[location], false, array); diff --git a/vendor/wasm/WebGL/webgl.odin b/vendor/wasm/WebGL/webgl.odin index 96d363ba2..5616f3660 100644 --- a/vendor/wasm/WebGL/webgl.odin +++ b/vendor/wasm/WebGL/webgl.odin @@ -52,6 +52,7 @@ foreign webgl { BindBuffer :: proc(target: Enum, buffer: Buffer) --- BindFramebuffer :: proc(target: Enum, framebuffer: Framebuffer) --- BindTexture :: proc(target: Enum, texture: Texture) --- + BindRenderbuffer :: proc(target: Enum, renderbuffer: Renderbuffer) --- BlendColor :: proc(red, green, blue, alpha: f32) --- BlendEquation :: proc(mode: Enum) --- BlendEquationSeparate :: proc(modeRGB: Enum, modeAlpha: Enum) --- @@ -172,14 +173,63 @@ foreign webgl { Viewport :: proc(x, y, w, h: i32) --- } -Uniform1fv :: proc "contextless" (location: i32, v: f32) { Uniform1f(location, v) } -Uniform2fv :: proc "contextless" (location: i32, v: glm.vec2) { Uniform2f(location, v.x, v.y) } -Uniform3fv :: proc "contextless" (location: i32, v: glm.vec3) { Uniform3f(location, v.x, v.y, v.z) } -Uniform4fv :: proc "contextless" (location: i32, v: glm.vec4) { Uniform4f(location, v.x, v.y, v.z, v.w) } -Uniform1iv :: proc "contextless" (location: i32, v: i32) { Uniform1i(location, v) } -Uniform2iv :: proc "contextless" (location: i32, v: glm.ivec2) { Uniform2i(location, v.x, v.y) } -Uniform3iv :: proc "contextless" (location: i32, v: glm.ivec3) { Uniform3i(location, v.x, v.y, v.z) } -Uniform4iv :: proc "contextless" (location: i32, v: glm.ivec4) { Uniform4i(location, v.x, v.y, v.z, v.w) } +Uniform1fv :: proc "contextless" (location: i32, v: []f32) { + foreign webgl { + @(link_name="Uniform1fv") + _Uniform1fv :: proc "contextless" (location: i32, count: int, value: [^]f32) --- + } + _Uniform1fv(location, len(v), &v[0]) +} +Uniform2fv :: proc "contextless" (location: i32, v: []glm.vec2) { + foreign webgl { + @(link_name="Uniform2fv") + _Uniform2fv :: proc "contextless" (location: i32, count: int, value: [^]f32) --- + } + _Uniform2fv(location, len(v), &v[0].x) +} +Uniform3fv :: proc "contextless" (location: i32, v: []glm.vec3) { + foreign webgl { + @(link_name="Uniform3fv") + _Uniform3fv :: proc "contextless" (location: i32, count: int, value: [^]f32) --- + } + _Uniform3fv(location, len(v), &v[0].x) +} +Uniform4fv :: proc "contextless" (location: i32, v: []glm.vec4) { + foreign webgl { + @(link_name="Uniform4fv") + _Uniform4fv :: proc "contextless" (location: i32, count: int, value: [^]f32) --- + } + _Uniform4fv(location, len(v), &v[0].x) +} + +Uniform1iv :: proc "contextless" (location: i32, v: []i32) { + foreign webgl { + @(link_name="Uniform1iv") + _Uniform1iv :: proc "contextless" (location: i32, count: int, value: [^]i32) --- + } + _Uniform1iv(location, len(v), &v[0]) +} +Uniform2iv :: proc "contextless" (location: i32, v: []glm.ivec2) { + foreign webgl { + @(link_name="Uniform2iv") + _Uniform2iv :: proc "contextless" (location: i32, count: int, value: [^]i32) --- + } + _Uniform2iv(location, len(v), &v[0].x) +} +Uniform3iv :: proc "contextless" (location: i32, v: []glm.ivec3) { + foreign webgl { + @(link_name="Uniform3iv") + _Uniform3iv :: proc "contextless" (location: i32, count: int, value: [^]i32) --- + } + _Uniform3iv(location, len(v), &v[0].x) +} +Uniform4iv :: proc "contextless" (location: i32, v: []glm.ivec4) { + foreign webgl { + @(link_name="Uniform4iv") + _Uniform4iv :: proc "contextless" (location: i32, count: int, value: [^]i32) --- + } + _Uniform4iv(location, len(v), &v[0].x) +} VertexAttrib1fv :: proc "contextless" (index: i32, v: f32) { VertexAttrib1f(index, v) } VertexAttrib2fv :: proc "contextless" (index: i32, v: glm.vec2){ VertexAttrib2f(index, v.x, v.y) } diff --git a/vendor/wasm/WebGL/webgl2.odin b/vendor/wasm/WebGL/webgl2.odin index 74f0534d7..66a739303 100644 --- a/vendor/wasm/WebGL/webgl2.odin +++ b/vendor/wasm/WebGL/webgl2.odin @@ -36,7 +36,7 @@ foreign webgl2 { /* Texture objects */ TexStorage3D :: proc(target: Enum, levels: i32, internalformat: Enum, width, height, depth: i32) --- TexImage3D :: proc(target: Enum, level: i32, internalformat: Enum, width, height, depth: i32, border: i32, format, type: Enum, size: int, data: rawptr) --- - TexSubImage3D :: proc(target: Enum, level: i32, xoffset, yoffset, width, height, depth: i32, format, type: Enum, size: int, data: rawptr) --- + TexSubImage3D :: proc(target: Enum, level: i32, xoffset, yoffset, zoffset, width, height, depth: i32, format, type: Enum, size: int, data: rawptr) --- CompressedTexImage3D :: proc(target: Enum, level: i32, internalformat: Enum, width, height, depth: i32, border: i32, imageSize: int, data: rawptr) --- CompressedTexSubImage3D :: proc(target: Enum, level: i32, xoffset, yoffset: i32, width, height, depth: i32, format: Enum, imageSize: int, data: rawptr) --- CopyTexSubImage3D :: proc(target: Enum, level: i32, xoffset, yoffset, zoffset: i32, x, y, width, height: i32) --- From 983f3ec423a6a424c0e64ed2a5de41edffc459ec Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 10 Aug 2025 15:03:30 +0100 Subject: [PATCH 054/105] Add `#+feature global-context` This allows to use of `context` in the global scope on a per file basis. --- src/build_settings.cpp | 7 +++++++ src/check_decl.cpp | 7 ++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/build_settings.cpp b/src/build_settings.cpp index a6dce5233..fad4bedaa 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -357,6 +357,9 @@ enum OptInFeatureFlags : u64 { OptInFeatureFlag_IntegerDivisionByZero_Zero = 1u<<2, OptInFeatureFlag_IntegerDivisionByZero_Self = 1u<<3, + OptInFeatureFlag_GlobalContext = 1u<<4, + + OptInFeatureFlag_IntegerDivisionByZero_ALL = OptInFeatureFlag_IntegerDivisionByZero_Trap|OptInFeatureFlag_IntegerDivisionByZero_Zero|OptInFeatureFlag_IntegerDivisionByZero_Self, }; @@ -374,6 +377,10 @@ u64 get_feature_flag_from_name(String const &name) { if (name == "integer-division-by-zero:self") { return OptInFeatureFlag_IntegerDivisionByZero_Self; } + + if (name == "global-context") { + return OptInFeatureFlag_GlobalContext; + } return OptInFeatureFlag_NONE; } diff --git a/src/check_decl.cpp b/src/check_decl.cpp index ee7906e5e..b2522f24a 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -1855,7 +1855,12 @@ gb_internal void check_entity_decl(CheckerContext *ctx, Entity *e, DeclInfo *d, auto prev_flags = c.scope->flags; defer (c.scope->flags = prev_flags); - c.scope->flags &= ~ScopeFlag_ContextDefined; + + if (check_feature_flags(ctx, d->decl_node) & OptInFeatureFlag_GlobalContext) { + c.scope->flags |= ScopeFlag_ContextDefined; + } else { + c.scope->flags &= ~ScopeFlag_ContextDefined; + } e->parent_proc_decl = c.curr_proc_decl; From ecb6b35da561bfdaf89c0d39865a93abc26c3ad0 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 10 Aug 2025 15:29:53 +0100 Subject: [PATCH 055/105] Fix name canonicalization for named specialized forms --- src/name_canonicalization.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/name_canonicalization.cpp b/src/name_canonicalization.cpp index e3090368a..6a4538e26 100644 --- a/src/name_canonicalization.cpp +++ b/src/name_canonicalization.cpp @@ -505,7 +505,13 @@ write_base_name: Type *params = nullptr; Entity *parent = type_get_polymorphic_parent(e->type, ¶ms); - if (parent && (parent->token.string == e->token.string)) { + if (parent && (e->token.string == parent->token.string)) { + // Check for `distinct` forms + type_writer_append(w, parent->token.string.text, parent->token.string.len); + write_canonical_params(w, params); + } else if (parent && string_starts_with(e->token.string, parent->token.string) && + string_contains_char(e->token.string, '(')) { + // Check for named specialization forms type_writer_append(w, parent->token.string.text, parent->token.string.len); write_canonical_params(w, params); } else { @@ -767,7 +773,6 @@ gb_internal void write_type_to_canonical_string(TypeWriter *w, Type *type) { case Type_Named: if (type->Named.type_name != nullptr) { write_canonical_entity_name(w, type->Named.type_name); - return; } else { type_writer_append(w, type->Named.name.text, type->Named.name.len); } From da76c743e9b7c88f2f15bbee1dba3b2ab6ebc0b0 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 10 Aug 2025 17:42:49 +0100 Subject: [PATCH 056/105] Add shortcut for division by a constant --- src/llvm_backend_expr.cpp | 131 ++++++++++++++++++++++++++------------ 1 file changed, 89 insertions(+), 42 deletions(-) diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index a29682874..13c6082fb 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -1139,8 +1139,23 @@ gb_internal LLVMValueRef lb_integer_division(lbProcedure *p, LLVMValueRef lhs, L LLVMTypeRef type = LLVMTypeOf(rhs); GB_ASSERT(LLVMTypeOf(lhs) == type); + LLVMValueRef zero = LLVMConstNull(type); + auto behaviour = lb_check_for_integer_division_by_zero_behaviour(p); + auto *call = is_signed ? LLVMBuildSDiv : LLVMBuildUDiv; + if (LLVMIsConstant(rhs)) { + if (LLVMIsNull(rhs)) { + switch (behaviour) { + case IntegerDivisionByZero_Self: + return lhs; + case IntegerDivisionByZero_Zero: + return zero; + } + } else { + return call(p->builder, lhs, rhs, ""); + } + } LLVMValueRef incoming_values[2] = {}; LLVMBasicBlockRef incoming_blocks[2] = {}; @@ -1149,7 +1164,6 @@ gb_internal LLVMValueRef lb_integer_division(lbProcedure *p, LLVMValueRef lhs, L lbBlock *edge_case_block = lb_create_block(p, "div.edge"); lbBlock *done_block = lb_create_block(p, "div.done"); - LLVMValueRef zero = LLVMConstNull(type); LLVMValueRef dem_check = LLVMBuildICmp(p->builder, LLVMIntNE, rhs, zero, ""); lbValue cond = {dem_check, t_untyped_bool}; @@ -1157,13 +1171,12 @@ gb_internal LLVMValueRef lb_integer_division(lbProcedure *p, LLVMValueRef lhs, L lb_start_block(p, safe_block); incoming_values[0] = call(p->builder, lhs, rhs, ""); - lb_emit_jump(p, done_block); lb_start_block(p, edge_case_block); - switch (lb_check_for_integer_division_by_zero_behaviour(p)) { + switch (behaviour) { case IntegerDivisionByZero_Trap: lb_call_intrinsic(p, "llvm.trap", nullptr, 0, nullptr, 0); LLVMBuildUnreachable(p->builder); @@ -1181,7 +1194,7 @@ gb_internal LLVMValueRef lb_integer_division(lbProcedure *p, LLVMValueRef lhs, L LLVMValueRef res = incoming_values[0]; - switch (lb_check_for_integer_division_by_zero_behaviour(p)) { + switch (behaviour) { case IntegerDivisionByZero_Trap: case IntegerDivisionByZero_Self: res = incoming_values[0]; @@ -1204,22 +1217,10 @@ gb_internal LLVMValueRef lb_integer_division_intrinsics(lbProcedure *p, LLVMValu LLVMTypeRef type = LLVMTypeOf(rhs); GB_ASSERT(LLVMTypeOf(lhs) == type); - LLVMValueRef incoming_values[2] = {}; - LLVMBasicBlockRef incoming_blocks[2] = {}; - - lbBlock *safe_block = lb_create_block(p, "div.safe"); - lbBlock *edge_case_block = lb_create_block(p, "div.edge"); - lbBlock *done_block = lb_create_block(p, "div.done"); - LLVMValueRef zero = LLVMConstNull(type); - LLVMValueRef dem_check = LLVMBuildICmp(p->builder, LLVMIntNE, rhs, zero, ""); - lbValue cond = {dem_check, t_untyped_bool}; + auto behaviour = lb_check_for_integer_division_by_zero_behaviour(p); - lb_emit_if(p, cond, safe_block, edge_case_block); - - lb_start_block(p, safe_block); - - { + auto const do_op = [&]() -> LLVMValueRef { LLVMTypeRef types[1] = {lb_type(p->module, platform_type)}; LLVMValueRef args[3] = { @@ -1227,15 +1228,42 @@ gb_internal LLVMValueRef lb_integer_division_intrinsics(lbProcedure *p, LLVMValu rhs, scale }; - incoming_values[0] = lb_call_intrinsic(p, name, args, gb_count_of(args), types, gb_count_of(types)); + return lb_call_intrinsic(p, name, args, gb_count_of(args), types, gb_count_of(types)); + }; + + if (LLVMIsConstant(rhs)) { + if (LLVMIsNull(rhs)) { + switch (behaviour) { + case IntegerDivisionByZero_Self: + return lhs; + case IntegerDivisionByZero_Zero: + return zero; + } + } else { + return do_op(); + } } + LLVMValueRef incoming_values[2] = {}; + LLVMBasicBlockRef incoming_blocks[2] = {}; + + lbBlock *safe_block = lb_create_block(p, "div.safe"); + lbBlock *edge_case_block = lb_create_block(p, "div.edge"); + lbBlock *done_block = lb_create_block(p, "div.done"); + + LLVMValueRef dem_check = LLVMBuildICmp(p->builder, LLVMIntNE, rhs, zero, ""); + lbValue cond = {dem_check, t_untyped_bool}; + + lb_emit_if(p, cond, safe_block, edge_case_block); + + lb_start_block(p, safe_block); + incoming_values[0] = do_op(); lb_emit_jump(p, done_block); lb_start_block(p, edge_case_block); - switch (lb_check_for_integer_division_by_zero_behaviour(p)) { + switch (behaviour) { case IntegerDivisionByZero_Trap: lb_call_intrinsic(p, "llvm.trap", nullptr, 0, nullptr, 0); LLVMBuildUnreachable(p->builder); @@ -1253,7 +1281,7 @@ gb_internal LLVMValueRef lb_integer_division_intrinsics(lbProcedure *p, LLVMValu LLVMValueRef res = incoming_values[0]; - switch (lb_check_for_integer_division_by_zero_behaviour(p)) { + switch (behaviour) { case IntegerDivisionByZero_Trap: case IntegerDivisionByZero_Self: res = incoming_values[0]; @@ -1277,6 +1305,42 @@ gb_internal LLVMValueRef lb_integer_modulo(lbProcedure *p, LLVMValueRef lhs, LLV LLVMTypeRef type = LLVMTypeOf(rhs); GB_ASSERT(LLVMTypeOf(lhs) == type); + LLVMValueRef zero = LLVMConstNull(type); + auto behaviour = lb_check_for_integer_division_by_zero_behaviour(p); + + auto const do_op = [&]() -> LLVMValueRef { + if (is_floored) { // %% + if (is_unsigned) { + return LLVMBuildURem(p->builder, lhs, rhs, ""); + } else { + LLVMValueRef a = LLVMBuildSRem(p->builder, lhs, rhs, ""); + LLVMValueRef b = LLVMBuildAdd(p->builder, a, rhs, ""); + LLVMValueRef c = LLVMBuildSRem(p->builder, b, rhs, ""); + return c; + } + } else { // % + if (is_unsigned) { + return LLVMBuildURem(p->builder, lhs, rhs, ""); + } else { + return LLVMBuildSRem(p->builder, lhs, rhs, ""); + } + } + }; + + if (LLVMIsConstant(rhs)) { + if (LLVMIsNull(rhs)) { + switch (behaviour) { + case IntegerDivisionByZero_Self: + return zero; + case IntegerDivisionByZero_Zero: + return lhs; + } + } else { + return do_op(); + } + } + + LLVMValueRef incoming_values[2] = {}; LLVMBasicBlockRef incoming_blocks[2] = {}; @@ -1284,31 +1348,13 @@ gb_internal LLVMValueRef lb_integer_modulo(lbProcedure *p, LLVMValueRef lhs, LLV lbBlock *edge_case_block = lb_create_block(p, "div.edge"); lbBlock *done_block = lb_create_block(p, "div.done"); - LLVMValueRef zero = LLVMConstNull(type); LLVMValueRef dem_check = LLVMBuildICmp(p->builder, LLVMIntNE, rhs, zero, ""); lbValue cond = {dem_check, t_untyped_bool}; lb_emit_if(p, cond, safe_block, edge_case_block); lb_start_block(p, safe_block); - - if (is_floored) { // %% - if (is_unsigned) { - incoming_values[0] = LLVMBuildURem(p->builder, lhs, rhs, ""); - } else { - LLVMValueRef a = LLVMBuildSRem(p->builder, lhs, rhs, ""); - LLVMValueRef b = LLVMBuildAdd(p->builder, a, rhs, ""); - LLVMValueRef c = LLVMBuildSRem(p->builder, b, rhs, ""); - incoming_values[0] = c; - } - } else { // % - if (is_unsigned) { - incoming_values[0] = LLVMBuildURem(p->builder, lhs, rhs, ""); - } else { - incoming_values[0] = LLVMBuildSRem(p->builder, lhs, rhs, ""); - } - } - + incoming_values[0] = do_op(); lb_emit_jump(p, done_block); lb_start_block(p, edge_case_block); @@ -1320,9 +1366,10 @@ gb_internal LLVMValueRef lb_integer_modulo(lbProcedure *p, LLVMValueRef lhs, LLV floored: r = a - b*floor(a/b) IFF a/0 == 0, then (a%0 == a) or (a%%0 == a) + IFF a/0 == a, then (a%0 == 0) or (a%%0 == 0) */ - switch (lb_check_for_integer_division_by_zero_behaviour(p)) { + switch (behaviour) { case IntegerDivisionByZero_Trap: lb_call_intrinsic(p, "llvm.trap", nullptr, 0, nullptr, 0); LLVMBuildUnreachable(p->builder); @@ -1340,7 +1387,7 @@ gb_internal LLVMValueRef lb_integer_modulo(lbProcedure *p, LLVMValueRef lhs, LLV LLVMValueRef res = incoming_values[0]; - switch (lb_check_for_integer_division_by_zero_behaviour(p)) { + switch (behaviour) { case IntegerDivisionByZero_Trap: case IntegerDivisionByZero_Self: res = incoming_values[0]; From 4cbcb3ace7c0d066e8d5105e4b3582300f93d533 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 10 Aug 2025 17:53:07 +0100 Subject: [PATCH 057/105] Add shortcut for `unsigned_x/power_of_two` -> `unsigned_x >> log2(power_of_two)` --- src/common.cpp | 7 +++++++ src/llvm_backend_expr.cpp | 11 +++++++++++ 2 files changed, 18 insertions(+) diff --git a/src/common.cpp b/src/common.cpp index 53848cacf..5b007bf2c 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -80,6 +80,13 @@ gb_internal gb_inline bool is_power_of_two(i64 x) { return !(x & (x-1)); } +gb_internal gb_inline bool is_power_of_two_u64(u64 x) { + if (x == 0) { + return false; + } + return !(x & (x-1)); +} + gb_internal int isize_cmp(isize x, isize y) { if (x < y) { return -1; diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index 13c6082fb..f922c6359 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -1153,6 +1153,17 @@ gb_internal LLVMValueRef lb_integer_division(lbProcedure *p, LLVMValueRef lhs, L return zero; } } else { + if (!is_signed && lb_sizeof(type) <= 8) { + u64 v = cast(u64)LLVMConstIntGetZExtValue(rhs); + if (v == 1) { + return lhs; + } else if (is_power_of_two_u64(v)) { + u64 n = floor_log2(v); + LLVMValueRef bits = LLVMConstInt(type, n, false); + return LLVMBuildLShr(p->builder, lhs, bits, ""); + } + } + return call(p->builder, lhs, rhs, ""); } } From b6e0b4848116697fa86a46c0b06a5ceb3654d5c6 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 10 Aug 2025 17:58:46 +0100 Subject: [PATCH 058/105] Rename block names from `div` to `mod`. --- src/llvm_backend_expr.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index f922c6359..dbbc6268a 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -1355,9 +1355,9 @@ gb_internal LLVMValueRef lb_integer_modulo(lbProcedure *p, LLVMValueRef lhs, LLV LLVMValueRef incoming_values[2] = {}; LLVMBasicBlockRef incoming_blocks[2] = {}; - lbBlock *safe_block = lb_create_block(p, "div.safe"); - lbBlock *edge_case_block = lb_create_block(p, "div.edge"); - lbBlock *done_block = lb_create_block(p, "div.done"); + lbBlock *safe_block = lb_create_block(p, "mod.safe"); + lbBlock *edge_case_block = lb_create_block(p, "mod.edge"); + lbBlock *done_block = lb_create_block(p, "mod.done"); LLVMValueRef dem_check = LLVMBuildICmp(p->builder, LLVMIntNE, rhs, zero, ""); lbValue cond = {dem_check, t_untyped_bool}; From 8df69c95c3163562b6caf6c55651363c17c3f478 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 10 Aug 2025 18:29:08 +0100 Subject: [PATCH 059/105] Add `-integer-division-by-zero:all-bits` --- src/build_settings.cpp | 19 ++++++++++++++----- src/check_expr.cpp | 31 +++++++++++++++++++++++++------ src/llvm_backend_expr.cpp | 19 +++++++++++++++++++ src/main.cpp | 1 + 4 files changed, 59 insertions(+), 11 deletions(-) diff --git a/src/build_settings.cpp b/src/build_settings.cpp index fad4bedaa..4bee0ad4e 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -353,14 +353,18 @@ enum OptInFeatureFlags : u64 { OptInFeatureFlag_NONE = 0, OptInFeatureFlag_DynamicLiterals = 1u<<0, - OptInFeatureFlag_IntegerDivisionByZero_Trap = 1u<<1, - OptInFeatureFlag_IntegerDivisionByZero_Zero = 1u<<2, - OptInFeatureFlag_IntegerDivisionByZero_Self = 1u<<3, + OptInFeatureFlag_GlobalContext = 1u<<1, - OptInFeatureFlag_GlobalContext = 1u<<4, + OptInFeatureFlag_IntegerDivisionByZero_Trap = 1u<<2, + OptInFeatureFlag_IntegerDivisionByZero_Zero = 1u<<3, + OptInFeatureFlag_IntegerDivisionByZero_Self = 1u<<4, + OptInFeatureFlag_IntegerDivisionByZero_AllBits = 1u<<5, - OptInFeatureFlag_IntegerDivisionByZero_ALL = OptInFeatureFlag_IntegerDivisionByZero_Trap|OptInFeatureFlag_IntegerDivisionByZero_Zero|OptInFeatureFlag_IntegerDivisionByZero_Self, + OptInFeatureFlag_IntegerDivisionByZero_ALL = OptInFeatureFlag_IntegerDivisionByZero_Trap| + OptInFeatureFlag_IntegerDivisionByZero_Zero| + OptInFeatureFlag_IntegerDivisionByZero_Self| + OptInFeatureFlag_IntegerDivisionByZero_AllBits, }; @@ -377,6 +381,10 @@ u64 get_feature_flag_from_name(String const &name) { if (name == "integer-division-by-zero:self") { return OptInFeatureFlag_IntegerDivisionByZero_Self; } + if (name == "integer-division-by-zero:all-bits") { + return OptInFeatureFlag_IntegerDivisionByZero_AllBits; + } + if (name == "global-context") { return OptInFeatureFlag_GlobalContext; @@ -431,6 +439,7 @@ enum IntegerDivisionByZeroKind : u8 { IntegerDivisionByZero_Trap, IntegerDivisionByZero_Zero, IntegerDivisionByZero_Self, + IntegerDivisionByZero_AllBits, }; // This stores the information for the specify architecture of this build diff --git a/src/check_expr.cpp b/src/check_expr.cpp index e0b6408e3..7020b4f4b 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -4377,12 +4377,23 @@ gb_internal void check_binary_expr(CheckerContext *c, Operand *x, Ast *node, Typ b.kind == ExactValue_Integer && big_int_is_zero(&b.value_integer) && (op.kind == Token_QuoEq || op.kind == Token_Mod || op.kind == Token_ModMod)) { if (op.kind == Token_QuoEq) { - if (zero_behaviour == IntegerDivisionByZero_Zero) { + switch (zero_behaviour) { + case IntegerDivisionByZero_Zero: // x/0 == 0 x->value = b; - } else { + break; + case IntegerDivisionByZero_Self: // x/0 == x x->value = a; + break; + case IntegerDivisionByZero_AllBits: + // x/0 == 0b111...111 + if (is_type_untyped(x->type)) { + x->value = exact_value_i64(-1); + } else { + x->value = exact_unary_operator_value(Token_Xor, b, cast(i32)(8*type_size_of(x->type)), is_type_unsigned(x->type)); + } + break; } } else { /* @@ -4391,16 +4402,21 @@ gb_internal void check_binary_expr(CheckerContext *c, Operand *x, Ast *node, Typ truncated: r = a - b*trunc(a/b) floored: r = a - b*floor(a/b) - IFF a/0 == 0, then (a%0 == a) or (a%%0 == a) - IFF a/0 == a, then (a%0 == 0) or (a%%0 == 0) + IFF a/0 == 0, then (a%0 == a) or (a%%0 == a) + IFF a/0 == a, then (a%0 == 0) or (a%%0 == 0) + IFF a/0 == 0b111..., then (a%0 == a) or (a%%0 == a) */ - if (zero_behaviour == IntegerDivisionByZero_Zero) { + switch (zero_behaviour) { + case IntegerDivisionByZero_Zero: + case IntegerDivisionByZero_AllBits: // x%0 == x x->value = a; - } else { + break; + case IntegerDivisionByZero_Self: // x%0 == 0 x->value = b; + break; } } } else { @@ -9670,6 +9686,9 @@ gb_internal IntegerDivisionByZeroKind check_for_integer_division_by_zero(Checker if ((flags & OptInFeatureFlag_IntegerDivisionByZero_Self) != 0) { return IntegerDivisionByZero_Self; } + if ((flags & OptInFeatureFlag_IntegerDivisionByZero_AllBits) != 0) { + return IntegerDivisionByZero_AllBits; + } return build_context.integer_division_by_zero_behaviour; } diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index dbbc6268a..ebc3ec158 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -305,6 +305,9 @@ gb_internal IntegerDivisionByZeroKind lb_check_for_integer_division_by_zero_beha if (flags & OptInFeatureFlag_IntegerDivisionByZero_Self) { return IntegerDivisionByZero_Self; } + if (flags & OptInFeatureFlag_IntegerDivisionByZero_AllBits) { + return IntegerDivisionByZero_AllBits; + } } return build_context.integer_division_by_zero_behaviour; } @@ -1140,6 +1143,7 @@ gb_internal LLVMValueRef lb_integer_division(lbProcedure *p, LLVMValueRef lhs, L GB_ASSERT(LLVMTypeOf(lhs) == type); LLVMValueRef zero = LLVMConstNull(type); + LLVMValueRef all_bits = LLVMConstNot(zero); auto behaviour = lb_check_for_integer_division_by_zero_behaviour(p); auto *call = is_signed ? LLVMBuildSDiv : LLVMBuildUDiv; @@ -1151,6 +1155,9 @@ gb_internal LLVMValueRef lb_integer_division(lbProcedure *p, LLVMValueRef lhs, L return lhs; case IntegerDivisionByZero_Zero: return zero; + case IntegerDivisionByZero_AllBits: + // return all_bits; + break; } } else { if (!is_signed && lb_sizeof(type) <= 8) { @@ -1198,6 +1205,9 @@ gb_internal LLVMValueRef lb_integer_division(lbProcedure *p, LLVMValueRef lhs, L case IntegerDivisionByZero_Self: incoming_values[1] = lhs; break; + case IntegerDivisionByZero_AllBits: + incoming_values[1] = all_bits; + break; } lb_emit_jump(p, done_block); @@ -1211,6 +1221,7 @@ gb_internal LLVMValueRef lb_integer_division(lbProcedure *p, LLVMValueRef lhs, L res = incoming_values[0]; break; case IntegerDivisionByZero_Zero: + case IntegerDivisionByZero_AllBits: res = LLVMBuildPhi(p->builder, type, ""); GB_ASSERT(p->curr_block->preds.count >= 2); @@ -1229,6 +1240,7 @@ gb_internal LLVMValueRef lb_integer_division_intrinsics(lbProcedure *p, LLVMValu GB_ASSERT(LLVMTypeOf(lhs) == type); LLVMValueRef zero = LLVMConstNull(type); + LLVMValueRef all_bits = LLVMConstNot(zero); auto behaviour = lb_check_for_integer_division_by_zero_behaviour(p); auto const do_op = [&]() -> LLVMValueRef { @@ -1285,6 +1297,9 @@ gb_internal LLVMValueRef lb_integer_division_intrinsics(lbProcedure *p, LLVMValu case IntegerDivisionByZero_Self: incoming_values[1] = lhs; break; + case IntegerDivisionByZero_AllBits: + incoming_values[1] = all_bits; + break; } lb_emit_jump(p, done_block); @@ -1298,6 +1313,7 @@ gb_internal LLVMValueRef lb_integer_division_intrinsics(lbProcedure *p, LLVMValu res = incoming_values[0]; break; case IntegerDivisionByZero_Zero: + case IntegerDivisionByZero_AllBits: res = LLVMBuildPhi(p->builder, type, ""); GB_ASSERT(p->curr_block->preds.count >= 2); @@ -1344,6 +1360,7 @@ gb_internal LLVMValueRef lb_integer_modulo(lbProcedure *p, LLVMValueRef lhs, LLV case IntegerDivisionByZero_Self: return zero; case IntegerDivisionByZero_Zero: + case IntegerDivisionByZero_AllBits: return lhs; } } else { @@ -1386,6 +1403,7 @@ gb_internal LLVMValueRef lb_integer_modulo(lbProcedure *p, LLVMValueRef lhs, LLV LLVMBuildUnreachable(p->builder); break; case IntegerDivisionByZero_Zero: + case IntegerDivisionByZero_AllBits: incoming_values[1] = lhs; break; case IntegerDivisionByZero_Self: @@ -1404,6 +1422,7 @@ gb_internal LLVMValueRef lb_integer_modulo(lbProcedure *p, LLVMValueRef lhs, LLV res = incoming_values[0]; break; case IntegerDivisionByZero_Zero: + case IntegerDivisionByZero_AllBits: res = LLVMBuildPhi(p->builder, type, ""); GB_ASSERT(p->curr_block->preds.count >= 2); diff --git a/src/main.cpp b/src/main.cpp index 06b9cab94..db4dee080 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2589,6 +2589,7 @@ gb_internal int print_show_help(String const arg0, String command, String option print_usage_line(3, "-integer-division-by-zero:trap Trap on division/modulo/remainder by zero"); print_usage_line(3, "-integer-division-by-zero:zero x/0 == 0 and x%%0 == x and x%%%%0 == x"); print_usage_line(3, "-integer-division-by-zero:self x/0 == x and x%%0 == 0 and x%%%%0 == 0"); + print_usage_line(3, "-integer-division-by-zero:all-bits x/0 == ~T(0) and x%%0 == x and x%%%%0 == x"); } } From 2648bd8fcdecc0a632dda59ed39e7f680f53c691 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Tue, 12 Aug 2025 09:51:16 +0100 Subject: [PATCH 060/105] Allow `#+feature global-context` for `@(init)` and `@(fini)` procedures as an interim measure --- src/checker.cpp | 38 ++++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/src/checker.cpp b/src/checker.cpp index f631a1412..44e63b750 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -565,6 +565,26 @@ gb_internal u64 check_feature_flags(CheckerContext *c, Ast *node) { return 0; } +gb_internal u64 check_feature_flags(Entity *e) { + if (e == nullptr) { + return 0; + } + AstFile *file = nullptr; + if (e->file == nullptr) { + file = e->file; + } + if (file == nullptr) { + if (e->decl_info && e->decl_info->decl_node) { + file = e->decl_info->decl_node->file(); + } + } + if (file != nullptr && file->feature_flags_set) { + return file->feature_flags; + } + return 0; +} + + enum VettedEntityKind { VettedEntity_Invalid, @@ -2675,8 +2695,13 @@ gb_internal void generate_minimum_dependency_set_internal(Checker *c, Entity *st is_init = false; } - if (t->Proc.calling_convention != ProcCC_Contextless) { - error(e->token, "@(init) procedures must be declared as \"contextless\""); + u64 feature_flags = check_feature_flags(e); + if ((feature_flags & OptInFeatureFlag_GlobalContext) == 0) { + if (t->Proc.calling_convention != ProcCC_Contextless) { + ERROR_BLOCK(); + error(e->token, "@(init) procedures must be declared as \"contextless\""); + error_line("\tSuggestion: this can be bypassed, for the time being, with '#+feature global-context'"); + } } if ((e->scope->flags & (ScopeFlag_File|ScopeFlag_Pkg)) == 0) { @@ -2711,8 +2736,13 @@ gb_internal void generate_minimum_dependency_set_internal(Checker *c, Entity *st is_fini = false; } - if (t->Proc.calling_convention != ProcCC_Contextless) { - error(e->token, "@(fini) procedures must be declared as \"contextless\""); + u64 feature_flags = check_feature_flags(e); + if ((feature_flags & OptInFeatureFlag_GlobalContext) == 0) { + if (t->Proc.calling_convention != ProcCC_Contextless) { + ERROR_BLOCK(); + error(e->token, "@(fini) procedures must be declared as \"contextless\""); + error_line("\tSuggestion: this can be bypassed, for the time being, with '#+feature global-context'"); + } } if ((e->scope->flags & (ScopeFlag_File|ScopeFlag_Pkg)) == 0) { From b6a0606c98606b8963af94966e1c6d70da4cfcd4 Mon Sep 17 00:00:00 2001 From: Wrath Date: Tue, 12 Aug 2025 19:59:38 -0400 Subject: [PATCH 061/105] Added getaddrinfo flags --- core/sys/windows/types.odin | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/core/sys/windows/types.odin b/core/sys/windows/types.odin index d5c9b1d20..904970589 100644 --- a/core/sys/windows/types.odin +++ b/core/sys/windows/types.odin @@ -3385,6 +3385,19 @@ FILE_ATTRIBUTE_TAG_INFO :: struct { ReparseTag: DWORD, } +// getaddrinfo flags https://learn.microsoft.com/en-us/windows/win32/api/ws2def/ns-ws2def-addrinfoa +AI_PASSIVE :: 0x01 +AI_CANONNAME :: 0x02 +AI_NUMERICHOST :: 0x04 +AI_ALL :: 0x0100 +AI_ADDRCONFIG :: 0x0400 +AI_V4MAPPED :: 0x0800 +AI_NON_AUTHORITATIVE :: 0x04000 +AI_SECURE :: 0x08000 +AI_RETURN_PREFERRED_NAMES :: 0x010000 +AI_FQDN :: 0x00020000 +AI_FILESERVER :: 0x00040000 + PADDRINFOEXW :: ^ADDRINFOEXW LPADDRINFOEXW :: ^ADDRINFOEXW ADDRINFOEXW :: struct { From df849891c1131fba12d170fb76eea626606c017b Mon Sep 17 00:00:00 2001 From: Xotchkass <78706300+Xotchkass@users.noreply.github.com> Date: Thu, 14 Aug 2025 13:35:25 +0300 Subject: [PATCH 062/105] use runtime.random_generator_read_bytes in read procedure instead of filling it manually. --- core/math/rand/rand.odin | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/core/math/rand/rand.odin b/core/math/rand/rand.odin index ece864f35..2fceee736 100644 --- a/core/math/rand/rand.odin +++ b/core/math/rand/rand.odin @@ -508,18 +508,8 @@ Possible Output: */ @(require_results) read :: proc(p: []byte, gen := context.random_generator) -> (n: int) { - pos := i8(0) - val := i64(0) - for n = 0; n < len(p); n += 1 { - if pos == 0 { - val = int63(gen) - pos = 7 - } - p[n] = byte(val) - val >>= 8 - pos -= 1 - } - return + if !runtime.random_generator_read_bytes(gen, p) {return 0} + return len(p) } /* From 2d5652dbd40e966d3373307e463f71b7dd1c37b0 Mon Sep 17 00:00:00 2001 From: Xotchkass <78706300+Xotchkass@users.noreply.github.com> Date: Thu, 14 Aug 2025 13:39:18 +0300 Subject: [PATCH 063/105] remove private _random_u64 and move it's functionality into public uint64 --- core/math/rand/rand.odin | 35 ++++++++++++++++------------------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/core/math/rand/rand.odin b/core/math/rand/rand.odin index 2fceee736..6b9a73395 100644 --- a/core/math/rand/rand.odin +++ b/core/math/rand/rand.odin @@ -56,13 +56,6 @@ query_info :: proc(gen := context.random_generator) -> Generator_Query_Info { } -@(private) -_random_u64 :: proc(gen := context.random_generator) -> (res: u64) { - ok := runtime.random_generator_read_ptr(gen, &res, size_of(res)) - assert(ok, "uninitialized gen/context.random_generator") - return -} - /* Generates a random 32 bit value using the provided random number generator. If no generator is provided the global random number generator will be used. @@ -84,7 +77,7 @@ Possible Output: */ @(require_results) -uint32 :: proc(gen := context.random_generator) -> (val: u32) { return u32(_random_u64(gen)) } +uint32 :: proc(gen := context.random_generator) -> (val: u32) {return u32(uint64(gen))} /* Generates a random 64 bit value using the provided random number generator. If no generator is provided the global random number generator will be used. @@ -107,7 +100,11 @@ Possible Output: */ @(require_results) -uint64 :: proc(gen := context.random_generator) -> (val: u64) { return _random_u64(gen) } +uint64 :: proc(gen := context.random_generator) -> (val: u64) { + ok := runtime.random_generator_read_ptr(gen, &val, size_of(val)) + assert(ok, "uninitialized gen/context.random_generator") + return +} /* Generates a random 128 bit value using the provided random number generator. If no generator is provided the global random number generator will be used. @@ -131,13 +128,13 @@ Possible Output: */ @(require_results) uint128 :: proc(gen := context.random_generator) -> (val: u128) { - a := u128(_random_u64(gen)) - b := u128(_random_u64(gen)) + a := u128(uint64(gen)) + b := u128(uint64(gen)) return (a<<64) | b } /* -Generates a random 31 bit value using the provided random number generator. If no generator is provided the global random number generator will be used. +Generates a random 31 bit value using the provided random number generator. If no generator is provided the global random number generator will be used. The sign bit will always be set to 0, thus all generated numbers will be positive. Returns: @@ -160,7 +157,7 @@ Possible Output: @(require_results) int31 :: proc(gen := context.random_generator) -> (val: i32) { return i32(uint32(gen) << 1 >> 1) } /* -Generates a random 63 bit value using the provided random number generator. If no generator is provided the global random number generator will be used. +Generates a random 63 bit value using the provided random number generator. If no generator is provided the global random number generator will be used. The sign bit will always be set to 0, thus all generated numbers will be positive. Returns: @@ -183,7 +180,7 @@ Possible Output: @(require_results) int63 :: proc(gen := context.random_generator) -> (val: i64) { return i64(uint64(gen) << 1 >> 1) } /* -Generates a random 127 bit value using the provided random number generator. If no generator is provided the global random number generator will be used. +Generates a random 127 bit value using the provided random number generator. If no generator is provided the global random number generator will be used. The sign bit will always be set to 0, thus all generated numbers will be positive. Returns: @@ -480,8 +477,8 @@ Possible Output: } /* -Fills a byte slice with random values using the provided random number generator. If no generator is provided the global random number generator will be used. -Due to floating point precision there is no guarantee if the upper and lower bounds are inclusive/exclusive with the exact floating point value. +Fills a byte slice with random values using the provided random number generator. If no generator is provided the global random number generator will be used. +Due to floating point precision there is no guarantee if the upper and lower bounds are inclusive/exclusive with the exact floating point value. Inputs: - p: The byte slice to fill @@ -513,7 +510,7 @@ read :: proc(p: []byte, gen := context.random_generator) -> (n: int) { } /* -Creates a slice of `int` filled with random values using the provided random number generator. If no generator is provided the global random number generator will be used. +Creates a slice of `int` filled with random values using the provided random number generator. If no generator is provided the global random number generator will be used. *Allocates Using Provided Allocator* @@ -556,7 +553,7 @@ perm :: proc(n: int, allocator := context.allocator, gen := context.random_gener } /* -Randomizes the ordering of elements for the provided slice. If no generator is provided the global random number generator will be used. +Randomizes the ordering of elements for the provided slice. If no generator is provided the global random number generator will be used. Inputs: - array: The slice to randomize @@ -597,7 +594,7 @@ shuffle :: proc(array: $T/[]$E, gen := context.random_generator) { } /* -Returns a random element from the provided slice. If no generator is provided the global random number generator will be used. +Returns a random element from the provided slice. If no generator is provided the global random number generator will be used. Inputs: - array: The slice to choose an element from From d60fba13df171fb0fb1e9cacf942ac83d1f56bd9 Mon Sep 17 00:00:00 2001 From: Xotchkass <78706300+Xotchkass@users.noreply.github.com> Date: Thu, 14 Aug 2025 13:49:59 +0300 Subject: [PATCH 064/105] fix: throwing away the last generated byte in default_random_generator_proc --- base/runtime/random_generator.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/runtime/random_generator.odin b/base/runtime/random_generator.odin index 81432b330..ca5c008d0 100644 --- a/base/runtime/random_generator.odin +++ b/base/runtime/random_generator.odin @@ -97,7 +97,7 @@ default_random_generator_proc :: proc(data: rawptr, mode: Random_Generator_Mode, for &v in p { if pos == 0 { val = read_u64(r) - pos = 7 + pos = 8 } v = byte(val) val >>= 8 From 88dba1194ac9f2becffc5cae201de93d2fbc9405 Mon Sep 17 00:00:00 2001 From: diniamo Date: Thu, 14 Aug 2025 14:59:47 +0200 Subject: [PATCH 065/105] Fix ITimer_Flags_Bits enum value --- core/sys/linux/bits.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/sys/linux/bits.odin b/core/sys/linux/bits.odin index f9c4ec22e..64cdd2208 100644 --- a/core/sys/linux/bits.odin +++ b/core/sys/linux/bits.odin @@ -1838,7 +1838,7 @@ Clock_Id :: enum { Bits for POSIX interval timer flags. */ ITimer_Flags_Bits :: enum { - ABSTIME = 1, + ABSTIME = 0, } /* From bc78aad45fdde11b21b6c6c4c102ca65f78c20c4 Mon Sep 17 00:00:00 2001 From: Tohei Ichikawa Date: Thu, 14 Aug 2025 09:56:36 -0400 Subject: [PATCH 066/105] Fix typo in newBufferWithSliceNoCopy --- vendor/darwin/Metal/MetalClasses.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/darwin/Metal/MetalClasses.odin b/vendor/darwin/Metal/MetalClasses.odin index a4c7b43f2..67cf84f1e 100644 --- a/vendor/darwin/Metal/MetalClasses.odin +++ b/vendor/darwin/Metal/MetalClasses.odin @@ -5581,7 +5581,7 @@ Device_newBufferWithSlice :: #force_inline proc "c" (self: ^Device, slice: $S/[] } @(objc_type=Device, objc_name="newBufferWithSliceNoCopy") Device_newBufferWithSliceNoCopy :: #force_inline proc "c" (self: ^Device, slice: $S/[]$E, options: ResourceOptions, deallocator: rawptr) -> ^Buffer { - return Device_newBufferWithBytesNotCopy(self, mem.slice_to_bytes(slice), options, deallocator) + return Device_newBufferWithBytesNoCopy(self, mem.slice_to_bytes(slice), options, deallocator) } @(objc_type=Device, objc_name="newBufferWithLength") Device_newBufferWithLength :: #force_inline proc "c" (self: ^Device, length: NS.UInteger, options: ResourceOptions) -> ^Buffer { From c4102701fdcf42321a204e0b506706e70219a3b9 Mon Sep 17 00:00:00 2001 From: Michael Lee Date: Fri, 15 Aug 2025 11:04:00 -0500 Subject: [PATCH 067/105] misnamed parameter --- vendor/OpenGL/wrappers.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/OpenGL/wrappers.odin b/vendor/OpenGL/wrappers.odin index 1eb8fc72f..3f4593b45 100644 --- a/vendor/OpenGL/wrappers.odin +++ b/vendor/OpenGL/wrappers.odin @@ -880,7 +880,7 @@ when !GL_DEBUG { // VERSION_1_2 DrawRangeElements :: proc "c" (mode, start, end: u32, count: i32, type: u32, indices: rawptr, loc := #caller_location) { impl_DrawRangeElements(mode, start, end, count, type, indices); debug_helper(loc, 0, mode, start, end, count, type, indices) } - TexImage3D :: proc "c" (target: u32, level, internalformat, width, height, depth, border: i32, format, type: u32, pixels: rawptr, loc := #caller_location) { impl_TexImage3D(target, level, internalformat, width, height, depth, border, format, type, pixels); debug_helper(loc, 0, target, level, internalformat, width, height, depth, border, format, type, pixels) } + TexImage3D :: proc "c" (target: u32, level, internalformat, width, height, depth, border: i32, format, type: u32, data: rawptr, loc := #caller_location) { impl_TexImage3D(target, level, internalformat, width, height, depth, border, format, type, pixels); debug_helper(loc, 0, target, level, internalformat, width, height, depth, border, format, type, data) } TexSubImage3D :: proc "c" (target: u32, level, xoffset, yoffset, zoffset, width, height, depth: i32, format, type: u32, pixels: rawptr, loc := #caller_location) { impl_TexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels); debug_helper(loc, 0, target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels) } CopyTexSubImage3D :: proc "c" (target: u32, level, xoffset, yoffset, zoffset, x, y, width, height: i32, loc := #caller_location) { impl_CopyTexSubImage3D(target, level, xoffset, yoffset, zoffset, x, y, width, height); debug_helper(loc, 0, target, level, xoffset, yoffset, zoffset, x, y, width, height) } From fbac18ec008cc555262ff7380343cf229f2f5d34 Mon Sep 17 00:00:00 2001 From: Michael Lee Date: Fri, 15 Aug 2025 11:12:30 -0500 Subject: [PATCH 068/105] missed a spot --- vendor/OpenGL/wrappers.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/OpenGL/wrappers.odin b/vendor/OpenGL/wrappers.odin index 3f4593b45..d68efee6c 100644 --- a/vendor/OpenGL/wrappers.odin +++ b/vendor/OpenGL/wrappers.odin @@ -880,7 +880,7 @@ when !GL_DEBUG { // VERSION_1_2 DrawRangeElements :: proc "c" (mode, start, end: u32, count: i32, type: u32, indices: rawptr, loc := #caller_location) { impl_DrawRangeElements(mode, start, end, count, type, indices); debug_helper(loc, 0, mode, start, end, count, type, indices) } - TexImage3D :: proc "c" (target: u32, level, internalformat, width, height, depth, border: i32, format, type: u32, data: rawptr, loc := #caller_location) { impl_TexImage3D(target, level, internalformat, width, height, depth, border, format, type, pixels); debug_helper(loc, 0, target, level, internalformat, width, height, depth, border, format, type, data) } + TexImage3D :: proc "c" (target: u32, level, internalformat, width, height, depth, border: i32, format, type: u32, data: rawptr, loc := #caller_location) { impl_TexImage3D(target, level, internalformat, width, height, depth, border, format, type, data); debug_helper(loc, 0, target, level, internalformat, width, height, depth, border, format, type, data) } TexSubImage3D :: proc "c" (target: u32, level, xoffset, yoffset, zoffset, width, height, depth: i32, format, type: u32, pixels: rawptr, loc := #caller_location) { impl_TexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels); debug_helper(loc, 0, target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels) } CopyTexSubImage3D :: proc "c" (target: u32, level, xoffset, yoffset, zoffset, x, y, width, height: i32, loc := #caller_location) { impl_CopyTexSubImage3D(target, level, xoffset, yoffset, zoffset, x, y, width, height); debug_helper(loc, 0, target, level, xoffset, yoffset, zoffset, x, y, width, height) } From c6db3cc6709bf53d0bbfafab66769175e9a871ae Mon Sep 17 00:00:00 2001 From: alessio98888 <56458281+alessio98888@users.noreply.github.com> Date: Sat, 16 Aug 2025 19:50:06 +0200 Subject: [PATCH 069/105] Fix buddy allocator assert The last address of "data" is not "cast(uintptr)raw_data(data)+cast(uintptr)size" but "cast(uintptr)raw_data(data)+cast(uintptr)(size-1)". The original assert would fail when for example the allocation size requested and the buddy allocator allignment were both 64. --- core/mem/allocators.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/mem/allocators.odin b/core/mem/allocators.odin index cb9301f60..2d7e7b3ea 100644 --- a/core/mem/allocators.odin +++ b/core/mem/allocators.odin @@ -2331,7 +2331,7 @@ buddy_allocator_alloc_bytes_non_zeroed :: proc(b: ^Buddy_Allocator, size: uint) } found.is_free = false data := ([^]byte)(found)[b.alignment:][:size] - assert(cast(uintptr)raw_data(data)+cast(uintptr)size < cast(uintptr)buddy_block_next(found), "Buddy_Allocator has made an allocation which overlaps a block header.") + assert(cast(uintptr)raw_data(data)+cast(uintptr)(size-1) < cast(uintptr)buddy_block_next(found), "Buddy_Allocator has made an allocation which overlaps a block header.") // ensure_poisoned(data) // sanitizer.address_unpoison(data) return data, nil From 17f9ad29afa8e40918c5859a2c7f9b6ef7a3740e Mon Sep 17 00:00:00 2001 From: connnnal <216976529+connnnal@users.noreply.github.com> Date: Sun, 17 Aug 2025 18:35:25 +0100 Subject: [PATCH 070/105] Make D3D12_FEATURE_DATA_D3D12_OPTIONS.MinPrecisionSupport a bitset https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ns-d3d12-d3d12_feature_data_d3d12_options --- vendor/directx/d3d12/d3d12.odin | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/vendor/directx/d3d12/d3d12.odin b/vendor/directx/d3d12/d3d12.odin index 2bfd4de4f..0d4dbc4e0 100644 --- a/vendor/directx/d3d12/d3d12.odin +++ b/vendor/directx/d3d12/d3d12.odin @@ -851,10 +851,10 @@ FEATURE :: enum i32 { OPTIONS19 = 48, } -SHADER_MIN_PRECISION_SUPPORT :: enum i32 { - NONE = 0, - _10_BIT = 1, - _16_BIT = 2, +SHADER_MIN_PRECISION_SUPPORT :: distinct bit_set[SHADER_MIN_PRECISION_SUPPORT_FLAG; u32] +SHADER_MIN_PRECISION_SUPPORT_FLAG :: enum i32 { + _10_BIT, + _16_BIT, } TILED_RESOURCES_TIER :: enum i32 { From a0f6084b48e86295e3e6f4c444cbd936651fbdb0 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 18 Aug 2025 14:26:52 +0100 Subject: [PATCH 071/105] Rebuild stb libraries and compile `stb_truetype` using the `stb_rect_pack` rects --- vendor/stb/lib/stb_image.lib | Bin 274620 -> 288820 bytes vendor/stb/lib/stb_image_resize.lib | Bin 107674 -> 99126 bytes vendor/stb/lib/stb_image_write.lib | Bin 80908 -> 81326 bytes vendor/stb/lib/stb_rect_pack.lib | Bin 14996 -> 15174 bytes vendor/stb/lib/stb_sprintf.lib | Bin 25212 -> 24726 bytes vendor/stb/lib/stb_truetype.lib | Bin 170652 -> 168724 bytes vendor/stb/lib/stb_vorbis.lib | Bin 151738 -> 153860 bytes vendor/stb/src/stb_truetype.c | 2 ++ 8 files changed, 2 insertions(+) diff --git a/vendor/stb/lib/stb_image.lib b/vendor/stb/lib/stb_image.lib index f0cffb1fc67063e24f0ab4ac9bcf79a1ff77e4a6..bed913f617349e638a341ea8552f84b8d6b6d426 100644 GIT binary patch literal 288820 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�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 bu4T2k@aGqT|A(sWkrq6CXP~|;H1+=ha;e(^ literal 274620 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�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 literal 107674 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 P|0+j0{2y#n(YXB|4^1*V literal 80908 zcmeFa3qVxW+Bd$38DIo-IT`2xuspvtdT}=!}wDQd)pq)Iuf2v_i#z8rqC` zO3TjaoMX3>bvk8bN>>L^K`q7mEz`_O(#+Bn&7A-5S!?eB#u=o}dH?VEzOSWg_OsXe zt!F*!_N@D+*PzT9S(9%IyCtf*>DxcPZ~uP%;s*3>?jEbY#>MsT&&iB1K@bKBLWfTO zFWDhO(o@Xov2nv3_MyqiBh9lX4lzlRSy0`RC3CWE_y}ui%20FPzI})Ei;H7FadAWX z;k6mmW*+WHNgg?LgdNZ!{SpX_2cBd(odDA;R7$Ej#WvJ2d{in$&{8OHVZ4Cxif2hS zj~wnuPL@Wdn5}84qsH7Z+B(E!89AiirT_X4Nr-JUUKZ9AvpjU@Q0s`HvU!Lp#e(3e zqa}+CEUiQOGnanjW=tt4$eA{z-^7Q8^qW~QF@4I^%t;!DzVRuehD#%DU_>d4rJtrr z>>F<%YO~rTIhFb6U*ezaFsE4T_GG)o!4P?b$f2KU^fQTm3g~At{UBlVYqB`h=g3A^ zRv>Zop2$5LOR{f@)hs(kS?nVmLt7JzDaB4Kd^xrdIg6M1tDvTl+sq>*`zV{kKAc59 zy-{XXTs%chQo;bU2*pyaC7KK6eH%dlA80zc`D7tEd5gV+wh(YQudVr1!?U#4rp!gYjUY8wF%S^MK5efwBT3SyrG?CJOe@GupU!b+ z^8oVzAw7M{%*^!62Q#PSWlqe?Nzcy7&77520QbNl;W;BGGtV5GnUFiNZ{J+)Jw7|L ze`3GviH+|$18z;s?&p2aiOb5$jLT_!Ph|R`@qNI6zWoz#ZG6uhFd#FBgk=VZm_ z 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 z z^>^M~`QED474LsgRlRoI`kLAe8@FxWv2)k%J$v_kdHAa%Uw`xM(faRx{OQ!`pU<3a zICq}QiQMGL^i3%eprw-|gLFX#gWeEI>C^?yR)e21^fRyN^oTjV7}tLHk2TZ#z5(sb zoqwnvQnhXv@=-P5*WM7^t8YjL>Gsgf2RdF8x4_sb`A;vrUD@W^_|YdjPn@wetcxk( z%jrcjbsTLwxeXvrmZ7qcdx-Z!a_oPiY8ZJ)EBPa(eWodek+&&<-{6 zD!ko>w|S@!7f~xO>e^_j{^R*a4*Zb=|5xNd5F6u?7HFy6U(|;Q7emAUuSoG9iTEQ2 z{>TBI17U2$$#sAM{eC#!d!XN+gFe3jef}A=`$s*ILNRP06M-;SAk0Gua|UCCGtd(y zz?Z^42KzXy6E=|PiLmDo*IC4MT8t3NfPDg1fh~u1!7hXiWClWWokhGqBkYsFErR_M z>{GB$!!Cwh0vpIAA$$Ykeg>FlVVA-_2m5E(zra2Z`&ZaN=3%7!EYkcpVEzuf4E6=s z7hzw5eHr!@*g)nH$~VaV4`5z}T@L#i?CY@qgna|{U$BA9dCEJ4e-oIuU{}Dt4f_u4 zyRa)^--8Wg8jyGH`J%82nANZqu)y0 z2fH3NkU5X=HSn*6-2l50b`$KUu%E$hhTQ@i$ecsj)xm!&>^9i#usdLP!tR3I4Z8<6 zkU5X=d*Qzic0cUrum@njfISF%2=+_ZK&Am@e;EE>!5)GA8ulC5Z()zZ*28`W8^|1k z-*MRQVNbyR0DBVlN7$cWPr;ss^=Hl@?w{dz2KFp$1ME52^RU0bUV!}-_9Co*)7bV& z7j#2g><*iVHbFYzG|Gl_0JY0NhIGaN;Lo5Q{!Dn133zJrP1|yy@T70fs_mcJK^5v^ z({``5=|JI0_mHllHcainU)!g)9mtUWAidR6+o!f2$dLY^I@nU%r?wr)klrNy(Nf!| zwjIcj{-HY9QroAt9mtUGZK>UBZ97nS(!DLUd#!B;3Qzi{rFO5i?Lgs4|FqQZwYD87 zJn5g7+P&7c1BItH*iyUK+IOJvhlaGfY}=dCf)rRDh^umfQS!QKi>?zD{EH0%JpTVWGn$)7d^y1-ruOMJ({ro!F^+X0sR zu7f4K1$HXzBv=P5$#X3%#bt)Q9dOd8SCYtiaT5oLqc7)~4*WDGjpn zldRMqCA?kPVprD7%1&7^%8JF5As27Z$z>K(GzE`h7+INMG8b>~$V#3`E_KUFfhkp# zE9K&~vFX*lz+@S$fmNZG8P%$o2^4KtHp|7EJaSo~Dax)?t8zdDHR7fb!WVM*#!3}X zi*>9i(hkwP*~{#vs4;i46wAs!*;RmaDd*G#Z=&poX3^GIOi>7rTmbXklm%MUrEXEK zW^vs+zWN$KmcbeX8-CT;6q~UgZ|KW#-UgO3yuH0lGFF?%AgiNfWv`u=iR`kQV$}qV zHN{%v-N;1Mt4wbbt#xwgHo0t!Q4*K9CB=Tl}^r39_J!MC(QwWgyF?8wzf) zpo$^Kqb$lg#!uO$<^=%C9!4wG$AaSBvQo}Ok>fw*hy`m&R_WgKd+!-vO)cM!+HGL# zp*!(r5QgHH=g}BYFEBT1oji|Rpy&dUL3j?oyo}xgwT-#S%Gxo=jeMk;5?g%EAeMXs zpZEI*oxxB1nsVTTM|c2+}Y$MbV(ZS+JB9 zMS(0^)D6EiMUnW8W&k6o{-C@S!ETyEd6sV#->Q>}tNL5Y#+oLhf@Y9f#WO9L(5T+2 zvVtN5a|>FKOkvEjf=X>MB?1=9W3`*2Ey_j<9HXS-T8|W7r)4Q6czkvI2Bk_aD>r2j z9|fgVZb}15&s6m(t537~OjMr~1L308XO#NvramLpr%`RoNa=d8+))aDY=hErKqThPW1 z5f-koR%m``-dJdVG|EkFqKEN86OIs8v>XgBx#?!$9#i zITaLdb+iYiwl&|bXu(ELao84AZMr=~i8o36Qqng**g;Ae*7p#p*8 zS+DG5sh1UBozo;`kw{rLn=%tA{3^Y=59H$s>IaG|nPgBez#4?n_~lBb1k@VlMn&)< zqwLD(cibu6A>ApBgN9-4rJ25^+G$rlG8N&85`wx_ezGg|R&+WGuY_CaHgRERJRPMT zu_OY7%diBD1zXwpIytM>QI_Rq$q}Qu7I&dn5u@8i0wPsN_!U>THREAd4v9BHB>)#i zt~Vl6fQtp4ORC1EIE(~HC7%q*a|cwxX4%yl{-B_(%S}ZfSzLsbU5lB6MR5~2et+rr z^KO^RJ~Bm-jB`EW)s!28P)s9H6mPXd`4n|bwALuQ(7M*+zr57uig=vb4YK(&#@SQt z*^+diaHEVIAx1WZtAD%lvWav`1uU!Eq;Rx;g0fJno$`XUl*dxKbgy*Jz4ug;{Jd6X zgL)d)Al#4NpIEb+?WIUq?nW3+{oPBsLH*1^P=$IG)_^@$-kk;uH-Vx{TLvK+)KiSQ zA5_5lPPIc;&ZDfo6+Tf?e)Lv&s=2jwEJ1`1FBXqrCiaO!(R2=G{)@C{8P*eR`8imn?UHLc`{-lKR zv>vjTtu)nv7H?c>anqO(D^-<8uh!QUpV!R|Wh2aEp;8js@TgtQf(#Q^EsiDz6gJtp zxbw0|wEoNTuzB1BJ_N9>xWO!z7ho`SN{qaYSV8ksD)Gu>w!7MrD_;B2)9&gV#b23@ ziQjh0B1SSTNCbz1AQeDiuB2yUdQVAWWP35XS`t^u9&uGkTaq_doK{OTi6f5R06*g? z@ve=qpPmx$t<<~;3hz^5`;yM2xWUFBjJObcofiuo(un;m5X+KgESteJmO&cJl4dM7 z2V&`L#S^~;wasKr&Je_}a;y1UZvpV53i$Sf`y(oCP5JTCu zWEmW!3Nw(J(^ylg#JchI7;NY?*Cj0bn*o=Q9MZ=$uCyxaIMC{{HXxD6ER`P|POGW* zBI;!ff>Mcnq}Q!^C^dvs@nTa(jp0WBnn_@fT72AT5Xtp)}OtB{j z^MuI|NvJ@P(?pLZC{Q7PUk^H;==d|BGKg~M&w`}&F(Iiz9CZ?^-KIZF-BlVDwfN-X zHqlU3dJ1^$<%^b)nvs;t}7fk@S@q04Iy93tP%G^hFDZ&39lisIU4-}so?Bs$b5BSM;*BLmp(vK$DXLQSpOLhrB}q#( zNlPH9C29Nb%~johMpkD_vN|jO5xWaI3v0_*QW5Lpt; zTVh&Ca1pCFk>$bEB%yE0gGq~kC<%5mFSxihm$jP9T5^FRs-Yi@!rEKf7BRlO8X~aT ze9GGvA#34P9!wRJML-RTMNq4;tJPdS)m%QkG=dTq0jXvdcrhc|m$#)^G>c%77QteT zU7g0RPIK9zx$L+!0w;@LsTRTWS_Dolf~8sn&ui@VXzccAE}v^IpI;h5Ig4PK7QxF} z1m#);%d`ky*4Q1=*d5Ybj%Y4NE{$Lji(t7H!5dlxi?j%qYZ1Jmu{)}w6 zfkJ7nIG_O>MNQNTZ?#Y)dCe3FhD}~YVgysBNYL8yNE=ZkTtTU70!*QensQ~#z%`#M zmeL}>3@t!lkhLz7DMCQ=B@9_e$%me$jRJQh8-`hvD#h}z&tN}5jOL@I`pKA{vN2f> z2o&Ida!f`8urtU$>0?ScAAcFO@z-V)$Zr^bHF(Eg3lLBpe__GuH;up6VeExrQjHkB zorYjk+;wam_V10qkhlQjudz#t_}~k>;=f_=wT=m?juUC{wVjFj?+p`46$TU&`V(Ws z5{UU*MqUB(6RQjV&UltoYCu7uhasr5d49Hb*yT^&Mp@Ni_gc#9){ebNI|q~%Djl+x zLssvYYlJrDT8)4{wYL>xuK#=jidsrQW98KbT(;%|E~7T!>K|yp1@_HVoL5f<9&k0) zlargM*~==)ycU(Drgf=2{-avg*i`E_kk)Pg3)8yBMy-4DJY3k)0aW#bHS>`#P{Mqv zqu3n^nlFJ^Vvd65>nB*L`wTC9VFkouw&DsxTZ4_}tFolbSJ3ha__^`4D||_p_9$qf z*N!t0bGCmQUTDfFZZH-OQ%=g2C-jSKY(WI81j<3a{!#f$q;momLp)uIe(}ue>h*72 z9TDJH`7I72oY2j3`|9fV^mEqtTIMGMp@)$ zoI%(ODw(gU5h-K8b=-^C@->2w7X|>BB8~}v{ zcTn`V7`ie_1Vt-H24Ntm?u;4%st2R;L0!S9xuAM7YB8wm7!`z3N@o^ZIH(&K)d^Gt zqpk!cGwM1}y%^O8l*p)CL3Lx48PrvbvVm&DsPUjWFlsRh+Dp?1+aQ0*Z$n3W{^S%j-+?Z0`H6CN> z+}DU{829Z7iu(=&#eJUv#dGNIpm+`~2gP&fZBRUi-Ur2Vs0tL%p-rH84($NNbLapl zo&hz>{<@Np8>l=nDvW=zJ&u-Wv zc(k-PhkdO&g7|FBLEA;s!6|j)4zE$aeVcAF81ro_CK#PrGRqjE#?r1hMsN9SY-^zn zQ!AFrlqzMcY0gmug2WASsk0~)qw@2vo=se zIA~-}ueN6)HoLNk?enOdH>uAp>JwnT4a-9GM(p$@9Rn`vYkT7|s27;qB>XVql*@c{9;HgN2kD*_$&&!Zo5s^Y zBXs22b|lxc3nyZHMQ=nVfIpW%6BL&Qd-h|-dH3vDaW~tuUj}5ZI2~#SYEEfDp-1V^ z!6@I+!bF;k4O`lt<~xRL!Gem+LcNn62YF~aRF-N|mO|kOcrGhT9XSlom)nN*2*YS- zeu}en+pGwSaummZez4%sp4pDvQ2W{KV2u z_Z%V);tqATq)mli5Q7N7`l>K@ip$X6qIX-9YUYNZN?Md-RE(bL;$MQr@;5GG4yqKI z>{8N!f>?M^vCt^W!g7}ihGj9;wOCZ3=*D7_lmiwV^)$2dpms>C>~eOKU9wI)t|#j! zVEXG>OVLp)&R{Eo-(lb_E1OxhvM8(#&|Ete@gd!)K57L7g@Y;V#Zh{spqrePXG(S5 zGXPbMIodIJLKO`~)$EHJXoo0RWL(USa!D0Nl&nqJES25ED>O@z&2_J_27Rp17W>0^ z2sJ4Nn`{{^DK(W1-JB^#MnpPO+AzZCObL^eN{jQ6aONF>m&yisw`Hy)M4XDnKAJP7 zUGZj*4E2bbxqf|0q)}W|UQz`1&Jpc%%O2@qc0STctH0Qa7#nWDd;>$uTAQa*j^A2& z6jO1-Qx&Ojy)+d^V|M)kmUS+x!H!d*JP%6U^KOD#x5s=&6&+%Y9dJQe zZx&Z=mOV9GJV{A-D*mJ`siE-D*qYA*pSTu>PA?DK(k3YCS<_JXf)~+DBgQy zK(TFLzRSH-4JeG2G29EqFZYcGwVdIGgW_T7j|ozY1|b{NIz~O<^?eK!kC#^ac-W1g zFs4I@RmcVIRtbvp+YE~Pu0~&Q08Pjsd;;nsqpCr@&cdDmwT)4&J{x?V&J~_yXM?eE ziZ%Lw|7`GQ>e=A+jGwamC?rDB`JU7BQ+O)?{I|{q)2597v%%=GBQYSbm5nftxlFC~`vgb`}NfOu4i?2ZgdL-9Kk0dT$Yb`xuL4RsSAW5`r zj^9>%E=YX7s<kja7i2lUD~WlT=7+zAKiq5paBj$?R~Lv#pFnt)UDG%6{sGSZmA z8ovRsG;CK>casX?y=;jv6Eh+bHG;7xmuPZx$&SvTxh3+yY9dV$RaoiO3jCGAcpJhSq*mmxuo-=s}wG- zVLFGhp4>k~YsBcPPS$U=sbjHHw`*9CSVCu3Y|0N((z>}0^y;q37lFUH;FlrVx= z?FI)~znCAjQ_oP+X|#R_=c%^oPe}TUs7*0RC8k6;6|S>D5fWulcy+XA4NY}D;<35R zI*dfj4|YL?EKpB0+==58HA7Po6@(j_YIYXJMtX*(mhPVyr~Kj_EZK1oG1|%wccP4< z2#v9-*7-a17v zketYMrGfHYyxJlNYUW>~W&Wb5%bV3F18-yCy_ho~AU=@#CQ6 z>9lt7ag0rWj6b7%fg|ie&>6U+Lsb0P<&3un_lwE1YvU~%JxF)3m<$-pX zazS>DXjpIPHpi24LBan49(Phr;SkrLxhO;cc4PJ1*c$#3jQ=AIj6X4cUoZ>8$B+iH zqtCS|9ta+V!{3PQ-gr0SJ0<@!9-W%S^eY;D0?iAb#R}B14$WpycFZ))_N;Ft+CRiG zrPFrw7O6D*#md4D80_5{grA|h%0tG=!;$(ryoBiMT!x)M3-NVy+%#BEk3$Cj)}Ft0 z$J@rr`Vjrb1z&oGfV0wRi^DYt7mA>O9HrX|LL?>m!m%Kw#-6nYqjnOHMnTk|mgDJq zOemsR2_N}cNspf-!AB^AaNfLz=3+_f=Q(gfNm6#lSWF3M*cdlohf%b=;2a(Ip4$ns z8rmfq#93jUD%n$MOR6pWN?mK2u1;N{NEcAjQbXZ%dW}$Q z4X!~BD)M8&Yp7}fO-n!_n4C2n)5}V&%8~k&R@R8lw&EeetYB189LFqn8*OC}pn(L) zk}lZG5-Jgg$9%zoUasU>Or!14*UJ#K9Scb26ig}%di+`pL0ZwWH=VxD8h_;XlyA>X zj?(>9tSJ|c=}|8BtUBBxpmLp$SZPKZ>v~K_g_?D;arTVz+=TM9#ki?FQz0XjzNGBn zW%{Y77Nr`CQdK)>t#CV|a52|zUb=_1G)hUk#V23Ek_{`;jfKylAaQBtkTvFOi$2?w zKtrNvX~6{#M4NA1aFOcEJj_kj_;20f>R>9g_-&qAT+LF>C!L&kh3py(Cm~r}T{0i) z6*1L#YCV-nC+8n`Eub5ogP(+}$Ue%tpprED8Y3K(O8vItL%OZ!!t1D~JxTNRC`tKj z`(bQR8^gboihnhVJ5?>)7M5z-(Up$Z%p6wRBm1IBR)yfK2PNuG@O>pEL2O= z6a@QkOj9i@sMqlO8!8~3@%S%H3^ij56mzuN1w#pZL|aILxda!kYCuqXe3)F&rj%VV zbyzj2*?!ofKdKeeU*H!gW#ZNUo2{#9!c>ied6%bFQm|IjfR(y=U2_+)^fl2paGrlm zQtH;wC&lKw31?=OQBHe3?efIR7>SpMi~TIW}{9-|#u$K|Z`H2Fxh(MkHRz{{b0 zJ<>HO)*f>REmAE%)Rj=|&!}~UwpYD%g-v*U>kE{Jgux-Te+dU1#B#dpXvI=sv!R8{ zfb|`SlDo*KQCy~e{6`x;`+F9bs~W96sr61Prq&$+DP)+#ftla|neL+&C8C%0I= zd#)w9e_O5l&r3}Lm)?%`RzAH(8#Y%6W=yS>i!z_lVbP$nfp-CDv$9-VgOff-*#}qT zS^KpGG|5$Nx`;UiCeym2v-SF|mFL^3H!@ujOEBoA1!Mij0V6Jm3-88jP09swv?^z@ z=qxTAh8H@ZvyZZZ=N4s11)n$eAA^#%{ma-u<=1)2yF0OP&(72x_8Mk1Pv955GtM^ps4dllbIculH z^jqT`qgCZ0YVnlaLcK3$fi%BJ(BcshPi5gSS8p~;=JEW-7{VH3Am+;E%5z5Fgdl<@ z3HkRTpbfb*TmL6xP&S|4YRlS%blCJe?OE%2TyoZk3$mVXx$0(Ku;|ZNlTM4}+pvd0 zTds+$4oiwh`h<#%=Kl*9u(IRZ4i#^`Htk;N>~ROSO3#O@wR1|<3T(e(IOWJ%iM5Ueo3#ZzOto9ThSw-Jn_Ww&p-lzS)rh#GjJ|ryxaNM_E z+zBu46ex}(#kU-92H{&!Jj6LroHOmTa?Zh^c!(U#aJX+Cs9#vT4}jvnb3hpxzj9Fg z*y9q_O)tb@CdA{gfZ|+6fZ}nag5q2{V0nn+OrSU}1{BA|g5tPuytoE0&f~=yFgM}2 zcR_J}>p*dSbQ_2B+v>%IL3A#2M^LnOq8F|MMJdt?i}2uFUIfLtyatMMc@q?m?JH26 z%Xgr{SZ)M^8Bu!SSx}tIYoIun6`(km_dszj--F^@&Va(|Fv5m{1?Tbz9-NB{6z8%S z6zB3BsMlG%`3T5ykAmX3GEf}15ERFyVso40CW7L)DWEuR8Yqrigd->%_aZ2cdkqxF zy$OorGTLdl8K5}sAy6DQ50n}&4oa%=f>PrJrN#@2<3b`eTsKf0cQq)EGlAl`d7$`? z{hz&5AMD8RILx4U*kPb}SUV^l_8Bj3xfl1A7q`-jYw+U2I%xdbgW~+Ufa3h_0>$IK z-;0~!#m)BOKJ?-~^Wt`RaeKYE@Q(Q7udGzR1jRX@0>x8w9u$|r1By$K)JelRKylny zP#kv`D2{v1i~FY+_l_60+KW5w#f6}A;r!Zy;`};*;{2?jmNQAsW3bI`&)R2YA80Av zHZP98w-TwY(B>|(imM`e&~4>aZkwmd5nl_no2(d~jK^~S_QEe^EKNtAts7t61Kdyv zp{H=J0y|1LJha$U1P65~!dglnSi^pSoxXd7=;1@(fXgZ|Eds4XJjxFqVzaXd?^xeA zT4Oe{%hFbbjsn)&vi92a`{ALN&h9DQFsqmN)*I~GR!m`+vy)QxtaVV#@;&40!2_E+ z1$0DkCG(UHY+Jja$?MQ%2(q_MXRhsa!+ z9{KDZoC=d;wqw6TrtNvVatbF9aS1(mcA6~APz}I z+)A%?^*2=>i@|HBTd{-^zu_o>;n7ZwRK}sPsGDk&oe^=z@L4>BcN*esp7plk?{%}D zqpXgm36K+^u(wl$2m1_5u=w~j(DL$9pZMRxtaztPoA7#g+p+QEin!W_G{l^eV|IJD zwZ&CB=_Z5GY3M7vY}gzBPB-g#{ZFZj*@MJE4c;_7(m9}c_&@oCUx0V^ z)x{cn%qB-njU7jtVs^7xx424=v_{~p-FO{N0j{!K?b(WqlAMZjbrF9wxomegQcW>^TMR0 z^A_a`i#YNC_!vT^o2pZsh7f$v#a3LeoAtN)mrxXxTd00GRwlZh#ye6gyE-Ai_aejW zF*V-&qQtfrR|VlSAUdiMPD>Y$4b!1n-yFM_GoeJz9ZeswFV_% zZG<-MVtK=FtOhau%FRTUiHKS@leZ#0vL4C`pIxmiH+VT*4Kz+x2>2mBbMjZlm zoKbY2^?ODg1$BZ^$3gwTD5x)NVOGh?R(3p#7-IH@gJ0~EkMx;G38lj&@!HcwEObEbL6Ee4 zV)QO}O~9ug=-OFYCB4wcAJVpo(MO5L7J4~G&U^S*0@B=w`Jxz2V#2jrj6Q_hf^44- z9$zD}qY~tR-(46)(4Ec+RRAzePEjHNZq44sv?uZ2NJ#z$cDu!BN+u%4wbm_H8IwH9!;gz_}MdlxOgOK<#5F z@D*_DX+rsAjIZ7cL2p928dw>d70@?wakU&o#Bg!7lbVaTx~K||Tww5#OnfeYJk!`|Ei8oKTUZ!;)2Tfjj?&w* z*4tczp0v4o;?s24qK7kE!-<6-9qeFYvyKAtGB&v# zF(+`E>lI3~E#?f4lTlExb;Mi*WwOO!?pWuD`NkHr3;9(fm)+sCo&7>x=N;}c{F9y8 zv%5OIOEdb|k*=N}+FcO}$sG-~`ZOgdYPhS@OT%3e@2U+PY>KN5vT}!$9prkSPJ-v- zOI#=el+qG9OeT)oW>>6>XtIqq%xbp{E5x!gYboL?C2_Itgz6Y6H=r>LZxCNFh-mhjE5-gFH#QocZt3uX4w6_>(v8VV8J73Lo!c|kI`-!B6hZMNETcnTB^T$JChHiu zbS0L3ElSRc54#~>t;$-9>;8I6Oeq~MorU`n?EA)>?NH2fYzjIzGz(Uebdw^remlb8 zd^zh9u|%mhWJz4Tvmi9rQ$-D!v5=Hs#nt=7)m6%--0k0j5o!84xt=X(&JBzyD$W9J z=FfPGt36g_phf=+6AXijm@V7CmBMe6iao}{G%QFqo;z?2s=>a1dLh!R9K`pX_-#lt zzYN*Y>jxivW66xKJ>epxBj)E>8<==33KpwWcAK?q;0HsHE_?&zWqP1CPgXWADxPB$ zX7wq?)P7d4;zVIq*W&N=a&bNE(FlgYIhy(VjztuI7j!JhgU{X~7%tuvSj5$Zrr}oo zKziDxn1kY~P2PlP2Pv8-hK<;~GXJ*p)K}3cH4ES8&BIqXlRgv6`@_MZ9Kc@9vGz?q z&?m8Tq{+pFudF~3uA9}(p7iDXb~evi$+M2T7JSc`;8-xes6=;;=HOGtkz)B5tk7|- z!BE_w6U#T@6^X>*Ui{|a!^?G+GOH8HqNv$9E)=G+$*TWV!dSj(QQnWDls=~B->g7? zZ+Swq6tUvu!dMimlNB*5T^i}4gh@7(vRF#TnrXi>pJxVL_&^%J6o)F7S629~*P9C3 zsrpatpTyPpn)NSI<(G!Ws_j^&)@+AT1qB-}LvQ_-+MVfJyD1}^)Q6@Qe$^_jejp9E zo4ogZ)mqLD#$ZB-hTK@qX%aLU1&xYACC(~6D{NE(ap9L(s3nz9e13>n@+dFfz;(Fr zo=e5Gpbj>+$KNY&lNO2NTC(C|U3udj3+n3m9SeyLO5Rg_HDtB3u|^wseTp}O@V1xQ z0t!=ixYdK|#c+?{mnyJ9*zKj>L-)N^ZZ#g+zFGio#`dsmr z^$&JoH%(BMIFU!AR*C{&<`?hAoryIa6@Z5HaycZb9CLutFLK>NQpjx%eHy z++=)Xoqu+|_;@M~X)lA1L|>N2@(2C|!H=b$Inzt`&$(Y#Qq$}%a|RPtTX9x4(a;S? zQQ=U_0`7u?8T}6&+;G5KB26x6ZJh==v7nc8_h^(Pzm>pGd>5}xRj-QRz((UsU!bYF z8Uz{=(iI=?pH0AGjz!s^oVUi*Dtqyr_x6%fWsRweslI!e11izrTPg5Lum6O9zPN88GN^H*t2-0c6auXcC2zLSk%2 zUXwhmT2y;01Qoxmw4qa=p^DU?cOMI833CmKBsZMgtZYzfFlToA9{s!_;9+A~VFekB z{D?}&-#SPVW`)+6u>g+Tq>)^i9tT02gOcF4nB|fKzv?0#D0Ptz6kk+xCF3J)w3t?h zH7;xdNp{GdRi&*8{2RF!&rMMnvwBTkLyE}(vm@jM!*1GDj zZC_d6&1u9F4wdzhPFbhXMyDJEM~l;}w-xIRO_t#rbJ3n9rHZT0BQt#u=DTi>q}=y( ztVu~lGSE4v(B+42k)D)PDlsjWsD(EFn;KCN`XnqSEyNtRf`~ar9E~?CE@eI@)s?I- zOTjNqKU~Q{W@laxNPvAev$LQ(DC`}>2O`jmZ~W??^N3RR*_4w`y4tOrTX4Pza?|nC zzhEq(Ei5)UTrMl4m^MpPt5{cZu+U$=*yRCDaj;lfb?6OVynN$9{Q!;zArTZWU;Y;^ zEQ*wh)M7}9+as5x5p2eTH~zpxn$cb+N0p^Uk}B}d1t-6Td7v9C#T)Z09LksCjdPac z>^)}i=B4vw@j7uPU{jj%g@Iz?wU%jVGX%8)~ADlEY7*l3_gpND?Yvx0$TC4 z^o3FAG-TzT`S=dyub5-=4*}a0wmNVnBE#VMhcfGvm^lqW=gFpLS#G)VP!Q&pZ`rbH zhPwu}p;O^y*1rQYUtY>zUe(Uc;9JbIF(;3F#7Nvn80c4j46}sDBuuuqz@imK{|LQ( z);;q-&vLtxsWE zgfCHw_ijcEcd@kwd^zr}bEj-#?^^oV>U2DL$}aY0@f_7;V!hMY3vW{1ShL+JAvka7Uv%*KX4A)o&T8u#j5%`RI6}ET* zEP)_PS$TB=6V9_4X59(O%X32<6WQJi9Dmr3rY{kJs#a?7qe9``1M z3H~P%TuM4CmM_Nq4n<(sAL2z-fcJVD!n5Mo34$uM)s@k-QhTWKu}aNL(w2p<&U_Pu zMfl%aN86}1^wp?Hp1oM`DFLan0cQfy!Cr0A zS0YdlXJbLVXWxeB2a&*s@laRJ7?;s(EF#6=uRA~vdjxugO>{GaFGAEixqQQPYM5r| zhye`TDUnsRW4($oWJYC2_^t&axNU^3;(o#GfxkI1(2m}jmgs14&8$Pd4rrRM$_Vsx zViNsX1P1KB$$<7Z-x9Wh0`jWhvdTY!HdA3}d&+ z7;`RzH*SS^@2@K7=(d3iC(WsY4C>h>d#b!y$0Q*P!Wx z4mcu;ia0M%+aC z^at5jsdf|3MF7&IJXT%Q$H*bUq72inUD8NnT%@OK%`i5avZy0=b(A~G=;=zaEhQ%U z6Id5zLQ|qk>3g&MHW|&EXhf1m#g#!D3Pr%v92w{4aP@9NdUZcI(B?|8Z~?#kZX(s! zZtO2`xgIToD@G`AN#rk=)7&zvI~apaO{zEKb3;n=1Ri>J~O({ z5;&n7{lqQ19@G^djS@?W@LqhheZjrhGbhkV7)|I~Zz-E%Fzsxg-hL0Y2 zhCtrZ926UkAh0F@nYrI0E2yBvloDfxq@fUk5->AQdMXZOTzQmEm4|fCUMl z!ZpjT2XGy<5G@zS74gJhMf)vRuUd61vLoFXz}2hfhigY%z`P{HX`qu^Qe_`wu~ld& zo+}td*F$P6Ljxm$P-ZAN%mGOy-ZQ>>B4p?DyaG_XXdVH@=Xph-c+u#>3_@5!m=HE2 zBp;5cgZwT;jHNbV-AA;1qG7Z}5QwK4vFohYKQdSDX>fVt=?v$o<}soT8BJ zS;+1;v=KUw?Jjgq=q7ZAC_4VK=I1deF3ohu{>2ka&oYAR#1k)rzn(zh3bXNt-;7cGFk|FN@I#j%rC= zlipRkz3h@9B z!8CS=5EjSFc7zrL&z0U#oT5;(c_`LS&_2e7qMd{Yo#J>qDFQ+>G=%1Ha*9IF<)J$m zg$`rGg$@aAgbs0y`iRz;G(%%I9-31Wx|oG#_3AXe3xXDc-Z+lx6{jLW@eqWX2CEr= zyvsOm6{7K_JZ_A?F$T_;c_FQ_-x54F zf*nuNLK9COn)(P%^#sL36N(NbX~thXFYtH(X(|=vDo0aVIYnvWe2J%W8NRQ2`63wO zP0v7ldA<yvsv|>(O8L z5qKEXKd33qybpqh;uM9Vzu$&d+apxyp^Fka9%^4Fy4z+%uo#=ytq;7RIYpuAVjz`b z2ukrvp+~`0f^qECaBmDr^@HQ7EICDG$wN}zrB4%R#$O!kcpNH3tL>E2jdE~`N|5s< zo+mEDcazFDL=Ygm0NI7#Bs=k6Mq;SOpX^(IhwQ}joy+ju&G_nih6p_;2VuNx^!AKR zM}r?iGG5-Cq7pm6Lxv$#TnH=W94!HOe&h|oDGKow55Y!%MvVS23XJ2UzbQ>Ze(Vj& zDGEv3rKnqDx(Z_|LIel?)Wo2rM&VXx8{w8YVM6reaKV%ih3`6d6S|-5dZ=?YFr%)i60@2epIst zPtK21#P4UuuU9y}IlcB;XuRtfRtv@I77G=LUmlA1^H7BP9#%8{`2WKB8-oO6fr&|@ zg`n7Zh~}~I5QMr7VKw8AH+`)F?GTWrl28V6bn_TEU*dVsW%!1A`BLm!UIgOH^MZKJ zzYO2Dj4z+7HTL|AC=%7U@#H1MDM~>{9;%H&XcHHFNSmcmf1sI45Ihv8C{%ZzhAtsO zmx4AzyVGGpa5lN~FK*M5N|fWNL^;(B6c0)KYhg9xFOI95<&!262mRMa>cVeg1we6mk8+2$4Agl+?ONLXFKeoo) zD*y?jg&<#!qmtnil?)F-C=0A+{P7;uER`BxlDIMc#uzwX;wfuPy~yTa?%=7U(K=)f zPS7#@{Y^sEg61jZ6s2W64~6fIhCZsbSV4HANvI9pP@JMrnLG`BBZR)ELxkS=!$zhZ zMxpCkQRq<64(+!s3$JmZ_Qu0Tc_|Yp&V^8JJ$_W2H*YQ&cLPFY%;5 zWuzH@e5W$LypQUk^-=lS*lZbsQkAWP<%~WBrJ0i;cy4lv@?|EMljiAI4KiX)g^U)8 zWaHRKFGc)$C_*)zC;H?65a&-CV{KP{5Q-Nwn-lU7&12yqi0`&wM4%dfyytuKxTz$R z#~e-RYm9;OC7y>b!?)DSmm(+LWCHQ!c|knsuQX`JpS%j=s|ybn!jnT!qQA+|T6dfl z49`ulyp%XasrVC@s7Hv_s-@%<}L^`q^CM=LNWUak|yE)5cfJN3d49AUj4e>p1T9i9)* zsx^bSQLgh`;1uP;ON>+Zo5O^jx&cDlli`Qj)P=g)`f6-YDur4B4wULTSYH1-Q9#vf z#*_2p6nVX-@(cyf2|*|oTCG*N2|`o{-}W>|V}|DzFF#HZzqfcUIwCPTjn-L~-l$7* z-lU706QjFna&O%=NA3>lvSWOZacvH8f}n9Tf#y7-y;N^doExD&rGik6zj)u{@s2hM zqmP<&L-$;#>s))iu1&=ax~8G2Zt&3EycFp=9-88C;Gm&q{KZ3`bVV=SCP--0aILOs z2ueK<7P}LD9D)>HSwXSnFSNmr%cV9l#@OijyZiMhYcMy z+98b{93OY{#3=>oGxBoMXH1%y6DC;GQb&!sW3+W}l-Km_6Wi2;h24Bt)OFcWF=_Y> z6Y?QawpYk_h;H6Vnz`}K{nYb zSavCG(*hmDhPITYEk!nkQA3)h3v@F{%c3Bth%({=qB6=RFX&qI1r<=iU2GUIP5)^2=-9cfbGr-n;L`cf^0>?Jttcs_p_2OY z^1;g}#V|KTC}Ege zC6s$%Zktdxp#sgDb`FB_u~t$_A`uX%;8J+p*0Qk3Kk&O@Sjgi_37ZweYXy(H5|5lv zzPE>w(yf4pi8Tum6I9F+^~$|6+YWN183p#rx^MtL8U3Xy&c zJ_9nwllG&CccT#cVyyI|E| zd*R@NMR9#Frrl80irs_fI5p;BQCtOgEQJk(@9Z9I!Q(E0Db_sFu=uY|Ph;{-W>0GR zs;iwIyiD`p-w&td`MG}=7>~GQ_N?>BW9={nt+y|8dhqn&ap&U{UQ-5t5^#F(CdLE5 zbXGM@r_SEy^uT5X5B2~q#j*ag*El`R$ny$JahcX`fAWyi1Ls|6=O*YJ*bJ`s_y6;s zP7nUK6^|QMhCI(to(P{j#jZOHD)4N8DQ>y;J6cX~dSIA=2R{PBHEdroC*A469n|BV z1ykH!qraZ=k<){B-5xi7;D=fHDb@dWda(CAZah5~!n?G~BOf|Fc<%PN=ff1UULDi$ zqtnxtJdeW^`?~$NOJIz}t~=grnPr~ZvG46pPkZvA_#?dED0ay5X&s zOPwCP%=5VMV_+O@8%v5-IX&>9HF!?Fy*iTzKfss??_O9}4_zL+UR}sD0;X8A{I%a6 zaC(x+gSWf5RgNt#c*g1JN*+8{U^{K+Y^ry9x{(KO9q=fVH|FfwPS3^U$%84Ddu#ta z-04Y%8jl-q7jR#_;V-Ylj*F@G{j@uIw!sw3@F(Wq@AUM58a1AAKlPtH3ab~}PEYcz zf+>!lm4E3GXPJAEXBtegeEX*%Fl=Mn!JhHByOIO;)vVVRIz4^Ja~Di;Kg}q9<@Zic zU-H}xQ%v~0xbsS<=MwT1z!b~14`<))^z?%ok9#f}pu9Pu8U|GCGN(WdoKJBIujwiH zzfWU5{mFxChvlvf{a~xadQzdrg3{JyDLYwdrWL$8!_q-3->}j`D?hN( zS}SLtt*CZd>B!23TJf^dNh_mRX{D6_D;H^H1}hh6z=>sCcCWt7;=5 z7L-EwC3XehZ{T)Zy5+Z7X{42pSvi-KNL{$HCR#=fH72DxR9#)GF4aNBUWKhQqmCRn zLB&5k5Q&7sQ6*YE|0TD49(ZuPLBZ1=l=HQMPxivnRV!UsX{wb0tTfRI{=rc!nOd35 zN`_V{Sn02o>saZnl?AL^qLrnr^wY{3R?@Vxk(G38>ce28x*B`8y7K!qy&Prb;Jg^r8tM#Bq4=Qzd2||UHNQn0V z)pBy-=rlY}U}+1lb6lw4Q5XweeuPR=lDG#38w!sicf}b8-_jEksH*zb5JYIw@ z6bha-lZ1ljzu|Ue5PI;LJ4x`9TK3{XFR**O*g-pmf*k~(91^9{@l1AwP;kZYt~CjM zDi1C*{vl?q3_=A9UK^j|N||Bq*5Tp?&S-c=fMvy8cel25U5In^XBFWmd0Z)VhJwoi zrf`4BJF#f6q2A+hNFI?z_o!~Xu7;I#UHkXo6U}tiS4^qog ztjmb9XLZn7EpP}xA&*$EY*1Bi;Cf+}p?Wh#9+BlE3ilT*|8UpMXrZ&Rnessme2!%6 z!=b29&r=`no_VFACNf1Hk(EP~J*&0Os$z;fA}d#9Eq(2J_`8PIsrDwO$Ro1yh-wZ~ zEQ>Gcd!(JFmN7*hku?mwX1%Ulbk`6=ZDxu*A}gP$B$(pZ7<1d+qziS{hfI-2WDO?@ zM=$o_zNg+xHPkVt$Rn~w5S0W|E31>vY6*8SSjZ!?MuKYA3$qNB&J=k>)+nN^?e*Q4 zE629dS@;c%>&JyYZnS>rT?a3!@9e)UD^q8!WQsf@Ym%n04`=t=-PKSVnIezKnoJaq4Wu4; z^u4KudWR|Uh^#*lWgRy*UwpEMp}u5_JR<8Vku~sm#}q^T!W4N#*3}~GrWH+g8LAa7 z0u=IytZP8^xbfJF>vi`Vx7=^2OPC^$$nq0qt=HST+nq2}9#iBISyPCz#^I);;VBt< zdtJp8c|=w~Wc3Y=+hV9NQ{)j@B_a#QVSk;qfGP5btf0ukF>k1cm?DqJDiv9s4sE!x zx6XQzDe{P{kjQ$oWPhfi{>l`2L{^!m;Ek*Mu1Vc5(OF+GMIMn=t|{EgTRuA;HPlZ` zkw;`z5M>y$Rn~UK{fmGzWIa487i46@`$XdL|Ivvb=%%HO=o2> zMIMngO=Pv3zV}H(jc1BHBCASgVQ*wLYzY{uhAHxhtZI>UBzf}3hFZuJc|=wXQP%!- zZ227*8R`+H$Ro09MONNBxnCJ-J5%HlS#_F%H?Eq&rO|ZVho3P;9+7perm#1jD?Y!K zp?+qHJR&Ph6kY=$m7lg`tD#z701_1Ph%Ef9#*B@-hd$ZfQ0YvOM`T5bO2R3;nlJ27 zW2j=L$Ro1qiNe8+)PLvXtua&;Q{)j@4MbVnYxWaA*{Iu?B9F+LF0xv5`QXnc>k+2N zBeG_QtVs_~UT>&ZnIezKnklkwUAN{VLmgy_JR)nB&Vo0ttbRGK_S9qJBva%OS=WiI z+rKG#+)%BWVM{I-c|_Lrpqgu&f@|HEHP=~vm?DqJnyo3?%1io=GE_cOw_-JZ7?jOp!-q-Kw+TjcdZ7 z$L{N)$HrWy$Ro0D6Ipq1zig-#Op!-qEhOq(41zLk^Q)b_I%^A4a#DeV~WoDfo1ZDtVJU0t}TCl&rq!|gi0vn5m|SD>TzdKE&OKj zUu}D&>MSo)B$Ro1uA_~W$8(zPyuKcN`&T3$aJR<9Ekrny& z)msd;m?`pzti?oG=dZJ0y?BG6)-y#Ok+no*<#c?go1xxfiaa9g9-{CVg~yFiA8wju zsBf4ekH}govQCa@a?nt}YXOx|$Ro1u1=U>7Kl#J42MpDfDe{P{`-rl(*UXQ$k2ln1 zOp!-q-7m6Mo^?;Qq5i-Wc|_JSk@a}ftDiO$e4s^zJR<8)nnD9!_x90aV<}VQ5m^st z3VZ%P&(7^{sC7({M`S&yDR|@B|6}ndSvqSwQ{)j@%Qb~rrOB=O8tPM~$Rn~=5M>>E z54E1u(@@8mB9F*gDYAb1aAYS|Jhp^!&ptpe4Ija%Q%U2LfSOp!-qttQGE8|Qxb z+a5y|Fhw4b^$<}w=CSl{e$CF#x(~~lB9F*g176$l@aHf5hPsg{@`$WI6J_mRJ!)^h z(ohdFMIMp$u*iC(6nR9}qay36?}z6b>IhTh5m}EB zg$HyTQKNo3_MM@ca@UeaWUUoh&+RTaV5nY9kw;`bF0#DMpZ(fUc}$T+z0P?Kf1ADe{P{O+;D8sJ{EQzGA4Gm?DqJ z+Dw$Sy?%|XyUtK+m?DqJdR}Dhc>485hJs&rP$7@VdVwhG+GhQo%a*p+efR}avbNWutuN0p)E}85kI337vOefM;sQghWr{o^>n);^V2WkN@OC@8={|geDe{P{ zx4~=r@T!gJHyP?PrpP0*-XSUprfzt(aWxAh>#Ujv`@-jLFw{t<$Ro1;N>nON;T82xU12Er z4k8uuh^*b{*S}v5%yXSE)I6rhBeLEnDha3XO6qy6o1s=PMIMp$0a4a^t!_4Av7ugM ziaa7~4^h@JYSyp6!Zte_G%Wj=B9F-W8`PThdT904>kRcHQ{)j@9};Da`J%77^fgqQ zc9>{AlFa@)`j0?0S;wBa?Mp*tFhw4b^)XS_dM*Fe-^Ng5nIex^ue~Dc#!lN-8mf*d z@`$W`L|N;#bIRwoad-z)|6a~-y?>C(-al- zNa_G69ybpQSM*?)ZH9uA02TB|>L4f{cYmsd|J(f5taL;5>7ZovNb2vPsQWl{+m>s=jc!USbM8lKQux4$lAlXG85`3O$lKEU3-1-)L;8PnklGq+s{9_58}-SHKXn zmJn{Zsh~$v{}EK1weP`jwy2X#p+{2x6;#&zx`T!~zYA1CL64-q2gQu=A^pm1+p7~( z=#kV>LAC9201mCz682*XJ(4;msN!>W4K~yerqCm)9|YC;*F_5q1-H&r&?Bkig4%n_ zoE$@4%@leh^`oE~p8IN%p{kiekEDJQ)SRy2o`#yu6nZ2D!_L<8bCx1r)USeSbKo|(7_`R5 zE~d~Usow;(>)GD6G5;x3=#dm&xSG-1r}^Jt7qqgzV+uWzatkVO>%={VI>{7zR7>Y4 zK`a;94n9EFoGU*GHyUCw@D1Q3g`fxiuYOrov_29lHSOd>eRfr-raW2^^kt`IXT!Ih zEB&*oDogzMUEXjg67l)6d|8$$RB~!pX=NmOnugGFx@Lmmpg$TYsS4?|>3%OfsxWlg!gI#d&^Ee-kWYRdgpl{FzYmQ{u$QE;EuNh=N=R9WY5fUh%D2H`6vGySzS z>RaC~tcGQnT37C$TvF2mn;kskKv+yWcjlcL1D;Xfq`X}Ji1DY{QWGYgiEGl( zGivHgT$3(8{UV*#5(q@fPP1Yap+IS>FFT8Ocl!QN>@Y=7`e{66l~q+al~EY+g}zg? zMZ1;?iIxZa(<`GD_|yd2r+6R1z1BM5RKiYI6>11o*$rj2Vc5ga2BFbV*j@*!eYOO? ztRW-qvlXR+g&o>niviJEe_4G^&@Mxh@nl?^IBtlDC*!e0xDy_1{C@btTcFAhhl!k(z2g>5uiXg%Ds)pwvs?_T12fQH>kcw z#s@n3;+d{CDD*yWIDe?7l-tuH93iQdvIau+teAs?Y<;A{lIrTCs;ez?npHzBdBvQ+ zu5t#C3(Kw~wI-m|)<^Zy@Y3PN!{aZt#2RintpSE-i~wyle3XaG4AH8YoHEJZ6 z)cX`_ zxTwgRV2{8CsdN1P;p0XGYD%j@;oOQ)a2gKwP_Q1JyD}3_4j_Q7c3Ne~m0Vvly|Sh> z*|wkKQ6QPV6yi{wW;{kX&7?ZbFj(T4Np+g>_~LAtRHqq_K29^KPP6^kwq0+v>qFg*BTI58W|`QX3Ml)&^S#JUF)6AiEl@2vpW2r_%7Z>uRTP>dK#_y(Rhv2X!oo&4s+<@eFX?RO#7vc1DYXxBo2F82@&uKNRC{9r zGC`#xGpHjIkO?XkskUqaGC`%Sdtk?pxeT*)P@GDMs{Kq~t4TDrG9GF!=;E=q+ITRY z#`I-hJYE`XO>lQ%eS$$@s#G_tT`vKbpi+@y#F%E|3@1~mNHJner6LnlDpHJ?STaGS zt$Sd*TbIhRTeT|9_6unVh#Gr;K!m8XcSmfUy*Fa(?41!?XIsda>vY>f#@47Xbw-G- zQ(^Jz6vrch?-|r*dDc-sex1Ej;^*-IifPl{De*ZTAu*h-Q=q@porgNs`9GUHmY0zbweZ0w0CBlYJ0E7saCW&=s1%TRx4T@Tby*lYDJ6Vi<3@RZR;`^EqI$jXAruXwe^^@ z&c4ddTGd}_jh(gj6?WDtR;{nI*15oVFYa7aQk`aVSMEe?bvBSUH+D^e)0U}HE2gf& z5^xDB6`3YZYNlNtehF%s730gnCa7grj4lV8pq5!Nwj6ANT4u$yl7o$3o9!=F9}td< z)`sC}we%72sXj>LUyx+`bAA5Q^x;K?`8heGebY;_lZOuVxw1)5%g^=Y73LKbjuHZAgpcA$Qn#BKS6n6N*(JiDU{Ubo#M|607lD z04L=*3F$@m<`$0{I(p==Tw3r{ti+d9pPDn$H>xN%XLNo+p)V~hJ2N9YGd&%Cz)yUs z_xS8#LFJC|<&MlR8dW?d|1=b|LTy2FCUdASXXL1YVPkTUhERBbF-|ZHW^Id?mOIQh zqNq5pu%IZPR-g)NO?T4DQqNUjMRsy-A^xN`sQU+zoT)1FiumVfqmqm2*<|`AEvLwr zn^#zvQ`dpswCoJqqnNEG(!7QFBZrL~I${j1 zXr1aOTUX=_^A#85jT%ujI)@xIj-hqx^mzSBI|p^{Ks3R63>`}EEGT!lg83&kMZ=%A zuGu9lf4mU0@zi#7#Pe9 z+UjGLuPiXoTRPC>m&xUUVH@&hl?JT#GE!yx8L62Wr6uq%EneP?)B(Xk-b~$p8L0zH n(lScSyjQMIhF33-`LJDm%uL>=B#;&YLQt$A?T~Ki zCDwIaS0C4|f86XIXS=80wmSQC1@RB+YSlVx|Jr{0^Qml8+pSvb%J;tK+?$&l!nDt} zKF{|(J3RN?bKmp(z3+M7^EWqPN|Cdrw*HR9S$bv4nVX-VpPQFokgt?yi;p?k1!A!# zkr0whNW!##=3218QDSoB}#Db5Rqu6;f^&tHP91K$wLJ z)1u-EbMc}Io?7rA!;4u9X0)w-s^yDg%m^kl}3F*Zpg+$&Qw}yF0+*J|Ng+0mzWk7mznuR zCCnchB-+R}Y%XmYbwnN&^pV9(8qjR48O-cXrHheXZ6Xebx7F!zu5o%BoU0n#4wu{G zY-{j?yuGo}l+9AkXm=$nPlV-0z_UrKe^pDf!|U_<9e!s^o!c);nw_=xIa=Jc{#H@Y z>h`xaJDd#-O=}%ZZGK0S$I<9+R8-cx+giM>es3-L@@r219Jc(_B&uN1nU+8o9-_L& z-+$JYFS~^OXKjJm^`Eun|MJ=rvAA6GJX0W@b7~S{wWEug1DCg~rd9WnS<gm|EELMuIq z_rzqtxmUH-85T=59Z;ADt6q3Ak>uhmzq{RUX!J?)=}`D(1Wun^Srds%2iynOfqONE zkk0`3%Q4JC65OKc)5EfC7)yxxYYc~~qv4K%{3*crbPR{9c{JQ0RI~%eG>+laqu{Op zZY5yuN@2M8QE=$*QzC{TquX^s<*xuYDV3q(;6~fm?sEE_5|iyd%SDVNH6>@8vYM4R z44W5lZ6X%^ptuNqSp8kdwnyTk=-UUFW0ANBeP0KC=K+&69tw~`cBAN<0hs(qT!cP2 z=99&Msg1-%(f1%=f|0l=`gQ>3l}KC^eQyKi50SVCeQD_9jp(VIM(dAsz}+fhLve|s z&jOfxB5_gLw;nLxio`|e!}$FOFu#bzMbY;rU`|KkBJ|<7`n!mcJRZ&8gb9RJ}03AovWB~$Xq_Ekdtq!BoX->TNuFe<^gM5YIl zv-=|BjN`d6n!bqmA+9qTuD1TZ);Y67rutxC4MyMyyzhad%`CHJA-BXY~gubQE+ zX!d&>z4v>4b^4N~#%6DWy9M1BIIXc*+jT={+%AX#84#=*p-N*sv>|TSFr;;P_@XmTPp6d<{x`V1=Qc4|Eu6cws}DE#NZT zWea*}!DJQQ6LiHv%?#rn-6M~I2D7k@YSP^dCN~;>Mn(O+aD)$-4SI|4IxoCMt(%3V z$-h}ZHsKwNTQ(2=rdfqJ`d}8aX@rIn(A1C`LdJDpQR#ZdKsfBeY=c$!)KZw$ zIZk);Mrb9<)@VV{afuIZ&_eq;VKSHb{<@pET~Ch|!1%(nu89)gCj1XCT;PN4T3#?| z3)43Ig%=iTQ5lpqg_AdcrXP={sn_s4G(id(#tGwP76y3Xq}W@JQHa=6>Oo_frt5a& zzOES{!7z6~u-@pOLwOf3(0+yFVZAOH;aJd~cIvYk+3xS>$($548P)?NzLPK3e8wBV40 zS<+xgTPjWweQ9vE)*^hyK@SM;mcB727G`$=AS*hcFb~-|(JL)^?{dPB zML29O%^TM=QSg+xXpKq8cqzG^D!rfXf^Dw7-@t|2aZ5C2EVUO`-XME;BVJd2j1vxLzF}4$(!F>{eb!<;+3_SV z*l+@ZwZM!a=mE2##vDlFp-XuVM@fUB5;{bW{j_o*3nIs&oDZc(X&mQ4&Z1lqs$B}D z@6p=3L$%mzjEh^!6STHHREv?``5;dxku9Ja zQriMCyiiHCOtA#V%rqA!c7fxIV66lcW$oc%fdn&czvBR44Z!r%c8&>XAy5ZOwa|E2 z>{b{|yl?;m#q%)iFpute#s6{^=p;m9To)gkv77&i4`c=+QO& z9+qO^gJ8vQ&q3X$H$g-9XByo%4`E?GWF$t{`zqXoe%%beAz3%0$l%d6(V7f69X-$) zKRnnycy+iBq_-p98oYD5S?D)s_U*!b%%k&N@NhccVJ=t_(g#j+OSjG2$sIg@Z@ZEh{tGeH!KIQR9%O78R zh!2{Q`TmbI!+WgigU~w{tlei+ZGXhrXIq11)2+1wyt>aG@b_zjrNdkxSG}JL+^gAw zol?LB?oYKID8|*9*aKyHYoILc66|;#Fu()FT5GVlAOJ(nZ!nnyIhH`nZPq|>Hg}-7 z2=FF*pv6Ro|H^?y@cb-Xu>@b2?0`!{)%uT8MSEIR0~vBJ@V3yk9eR+vH-y;V>vXHdeB z+8#)GJH)UZkHP=#@j5EkC&LAZ9*%_eicg4Xmxz+%OGbkQr5bT@pLKFN6fyGz( z{&V`F2?t89!q(BX8?&JVc!IW(yyJlszI!0ep7|$T&jhH#^{QSBmL+I`ZJF)+xaDNq zpu-_F5RV7DsIs;(4=zA`ZJNBkp;&r^$~zb+)%5gnI?HeP?gMFN;UjDJc~#pH91+bz zKlFA1EOsmIxqCpg!ukX3NL|7Sd&5v>Xyq+%X~+`DC(+V&$n~_e8hUOjEy2l8tbHpa zI}?(@Ql>q?Y2g{pc&gz+HJ7^O(z;ZL*8p7_aY58~uN$KhuJFR!{;AxqKLb>`3DNn0 zqt$U1>PYvnY7J~RSXScbC18oNo%rHWO3~WOL8Y3gCMJ@J{sc17r6m)q zPQ-2M;IO-uz>2W0e_=F4NKTJ6~t|qw>g!HI} zcT9S?n76EiEm}=wQ&Qqc%HAZB=pRF3XO9J$%tR0MaH$E7306vj5@S9Ar60#YCMG@H zBW>V5C3}qwOz5>9E;Ye+uo8OB^rBAu!az!TC`9V*q%u{imZZ88NosWhNu3Sls$@D! zj!IOxPYJPE2`zS0*)lSZtRNLIro6-lr8Uq;K6q*(E%4Mz{4kI4-a=|a&klHU!!vwA zPMV1mO81d0QV;s-LEZ+nUdr@Bjh@VhKRsDYs!1`aB9*}5i3PTsDq^KlD=7ilV$iXU zG|*PK;klUDAaAAZ@B_mQHFcoh54t+wPya8qwQv+$gk*zP9Nhln>pTl8QJ z<NZGHQgSALov{M*}m4sQB((XUotDVp@Q$+&xp{)^9zHFu7$KTuHDTTr;w{PrW? zH)LF`dh~LkWre}^=7|sDdZ!h>I={TQJ6${X=TAQ8Z^)_Nef5*AFEx}V9jIGyK(*Ya z8myo2di|x>EtN-}Dabzm&M|J{AGhDPx%uxeKe5dDy}ciOw$SC=n0&D1)w>^a{UT;} zRrUJ)zrOl`;pod}KdJXjJN?@ip1uD)eW!iL_9aH&@tv=@W4hk>%f4-=AA2oj-?Hg9 z6t7D7r0-zIm5Oft+mpZl+l86mxMRp)x@d;?#LD%FOHzNH^TqPm{wErac+WjFaqe&K zbf2>QY0lo>hxVT7{lST+pInR!2uF z)i6la#N=^1{aM-Bn^md@M9G?_hO9;x!9Hh_@UL5Obf{GxNnz+7{#7d-Evk-Com2?_ z`V>c#S~Xp)8Y(M=*TSef9E0nmT9qzhK0dlUI1&>}F}PkPLCLG_+c6RoM=^R(p8%!J zzVq<0G}2Z)#o)?`HK%?#w|XQ7*G{zxcW!L`#o*+rBQa<}t-^B+YTWZ|O3p}3BE?94 zbu4Iv=g9V;H)@p&a%}y@ORzjs3_Q^N1Mdk$PkRZzn8HU$+K}W{CV;oi62>e_lBi^L zYg3C~ln^R$taY}wx+S5+`i6*!0}OgiV6|c?HYE9uD2WeAUKAzjkYqrVXsENX zC?5{yP1$qM^A2KP&~Dw*QpOPRL$PbR=eT$bJv?-WDAzf8vc zU9DnrLiTSz@~F(ZAhIY%VGB?CY89RVFakr9&JM{et%}hoMqx`wS(2^$%g@P(fRN+mQL3%qkLD6r->;PGPHL?cAd>YpKYh7=^7HD2r($~r_c}7wwhHFI@8>Qj>g|880TigrJRLiXIi7bjy*uqci zY<{7wJ+XIN;Il6lA-yEBC`REI{j?C8%QtNKe2>gJA+jh&VM`A><+&WFpIjod{wA_0 zMqz6TWl3{+NAK+)%B(c(3`i8CuyqSa<^KAj^{4A)mQiF;jKbDb%93o^ugr{M?PvB;trg)RDdGqgr6bI$rmW*rh) z6r-?(JCZy$`jUL#ky#f+7R4xR;R!*G;q#VUi_E%F1C@{{Mq!J-VF-;4&;5tT%d8@i zMKKCnGeMU;4i8ScX`9Sg_sxx>voW+RmVl#(bkua%B*o>cOyp0%Azb$DS75{<^`FxPGliQ$)az6 zR5dkNjo(m--<) z)9PrwZ(W1e=XQ9!K9{4>>vOCV?I~+kxm*2?<|gSU^P$R6tDL^N1~^`~!DFlj0wEBx95vp|mBVSc{}S z84bmBN#l1k6w`GrRCEU;CU$fWBS7N+tb7&!5A|>VAEj&k|IPou|CcNNxBrvjSN0!y V|GNLY{7U}sF5_a*7Vn}YGy_FD>;+4ZS%RaNDxl`EImRO;mw z>SN`Kl~ughQa}i?5mGq&_qo=r3AkN>$|`qbo!B6I-L5qbQLMlWFBehuwO*IM!B^kl zY49;bA8NZX>%y!Dvo$MO?(j6K_XbUx#iHL;C)N49-Ubh|7(*~K7Q#}PacfwvT4X-c zPW-AW!wCaq@zm(5uWj_y);CJbQv{h&%;K1_x+j>mFT|aDovYR(uk+NcYr4#av8J;I zvld*kEnGJtS~VICNe#VC-T0Bc3px+YJZw@&)9dUcxFgbyVlm$d8B%`m-Pf242;*Cjs@!iEvD>|$50(KYG>;@eFM^)F{{OFJ!Vaq zu^3BO@?y3TGp3cXq|w-;8)b~a6nEm|4i^aoqCLSta9c3i5!~7l4uryyU~fkPws1m~bO&4S48+5&i5^wZ6HfGY2Z9|P zUE2d)y@^0qB+wb|)G6D;z42&IBHBv+2P^&Zn$${ff~9_TAzSW==@Nfmt?1gAUGvq7 zj#G!vT3sx@TG78+(Z5>Jf6o=&aCpDu*}Xb-rf(^LO@{3y0o+x}ySCmzmZgsPsgr){ zO~5Fxs93dXmEB%hS-k>okXi~te_lm)UM&XSnoG#{VXwec9>Tq9TbMr)5`jXYHT9(4 z3v7T3Z|!Y!Y)EPPp%6FVT*Oveo(T6P9G$Tg?s_PkGvMsDrWPX(szi!sq*(l(4fpps zgj53VmoqsAZ`p8PgUxU~?1i0Ia2%S>hMNHSIAH$bN{+)lG#hR|C>{mOH{e|glNqjT zxbuM94wyE0-@=p&S2o<&K)zSSAP!SDTnOaP0j~He1|fMVTwf@d2yz+b&{Wc_Vp39< zt-@8_Jr&mixDFMI?O-^Ay&{nB2FxQyTo!vT0Oqg}XRv1nd+z}z4-G>~`^{p{0hkIS z&R`F_p#d;kjJPcJ`T=u~5tqf@$psNy8w6ZCG27Seh8R@MqHNood(RWjW|R6 zus;f}A*2K@OzF5}u~!Wkj}d3Ehwa^}Vwge5rist}BeG3~Ndj2h#Nm=sBEF@EzYBZmf^#bV^yQh zqr$_ZV;(9N(Yhj!^T2>AhobO(P$)i!U4qQIVdEyTS==PvDh>boHV<8I^(Ol!ee_+g z`BRaOSDo4`DVrVD;>Ay21UD{xsPL41syye|2hV`;(F=R&Ina+BODq)kw?J*ABwH?} zBs-y;0UYtrdmVqv2t^K$^HbseIdIzXI(-g{aQ{pwN=m<@Nv8ddVxQ9Cko?IGN3l$Q zMupm>rN((sxPKpzeY69d)908aDS0=mf`=ZE>8q0BaoD}|pC$S>^Cu4XJ8Xm=?#*+) zJm5GxPc$DAogRl}sF-q^^R@oG-kHur1Nrp4kDjH!l9B0rRcOc1|Rl;uRY+{ zKk@-qtAbTaZF*vsM1775iJGWQQkosrXY-k$>KOBF5=O3oQ21#tk?BX?np*~D_~|w) z6#6ep$w8|~=Zj_kvSY5ee_!^9Ni@HvcxbM$U>8&Xn*Q$+JufBuppGtUP4VD4iLSMx zAt+mF<`06Q$EPs_f%;1@0nzc$F%~F^9*3B*K&ky=J}hEq4BhN}d8h_tNa&wKzso}G zJla1~qR_ud$ZnII5s$&K58bivqUQKk|_8~2z;&z6=Q#M?rV&JgMG zvYBGp1k53m=sYAeydlz8#ImCv^FiU6qvi`TJt@{)*Z&yySd&tD7RHvx(d1EzB?_}# zguwzGRxQzl!-ZWYL4VlAEn_PoXgt6-L1~1AP=uTZcvD(?JCyEWT3G5-E$#@MyAw*3 zX@}BUL(p+af(iDCNH0i9Sg%BS213q;tzaXjH*T^tcyoya!B#WfD?GnxL)Yt~DkdhLcMLxxJ*6dSqq~Sg*Ni6mz3$K@GlhspG zFf>P^^{_kwj`0pk!#k~{_ZK2SWCiA*b)ZnOLcGS;S)uX-;{_oa$9PE?uOa6#b2t{yf<@IdVj}?^Uoc{E0=lYYYoF zLq>9hdw&eKh|skJAL#+%x)qKkaI)GpkUx2N`0!_wqoBJHb#n5LN@0!kl#TAkJu4!_ z&I=1jL=<9gib;1)MCd*SLwCLFLt*eGxL%70pHGOxV-~o-5fQ4F90bM$Lq&uS4@HEx z#v;P;+IWSSAn3<|EJ-=jGuurr!53)^<5rS1PxTN#;?% zk~m;ZuA3B<<*>vncUbmfCzOiH&LVldwh(3(@hf$9S*a_&IEkaUT2yMSaOj1JC|l66JG0v8b$+zog_6qA&cizi1#=VMwmKB5(ytH z19lls8D7OCDl#}<$0rZToIEpd@)YpNv&5S$Dvj*n(`PnLpGI~1ATwk7l*)>T(hOoEsFtSApVmVkNC%rZp_22CK46XMTezTh0Emg|V!PArV{Sk$gv&yjA-|TD9)q0E@!eo(5tBUxC9Z|V$vQ4t z(Zv`wO&&IjMSCyqD1sosP7F%|E^+qZ9fcWj&4!9p%q#8h#A-GQQm6I&l|V7P10zzErPGYyD8dW!OU2r?sX63n_RY@4V%7 z&IAbA=P-E3v=}Zkpi?F6s!}Ff2wP}w0zZ?|7^vk8e3#}WJiT)U%7SpEQa0P=pfr<( z^Q~ll$VRSu$x5zl7D(=jD_N~lYa<-bq$4?D*e^H+pv9IPVrl2F7JehBI!#E*=+kj&ZCKl z7R(@7;Nob#2W}T_vNsxrO(FFh9HY=`9G@%lNWt>FZUl!^2HtSA^Oo`wdb*9tc&uhX ztgH|#h#6QYSQjpeu? za5gU?8|w$r5G+J^YX-~_{P_y3;VkE4f@5tU;Uyf;oQ0@|;B1;o+3eo|N-f$cyBImG z4!nf@$?c*|{M0q@8!*eb1LEgjakpM;* zG;Lr%0k-<#&;Et_T04y|_)HjD6#?II)}kB9Eu;^8-^AL~$FwmPy)Z#t4C>hjbxh%I z0qj(i(ZY7H9|Bf8pqIea%J@MRjW)2EiXqme4kjUi&elZ-r(*IM2Im>JuxRPr*;6q%)66DZH?j8L`>V!7Q!(hlY{DG{ zYqnux)96$Tu1RJSeuIOle@!Rk=ryzL*c!75*AJ}yg^M`F5rYZif@ub^6O1(>SF;>G znM_N*u1X5h5|1jG$s~W;(-lvs62c^b?ZKX&a7vi6j0bW|d4R!I6Bye(<)$V0_Kzt) zEqR6ufRSR2sS*p5ID8E&t5gX_ERTR>d8I1BI5SCQN`leIBjp*NQRC`rHertGDLVKd ztoHnYysh3DhGc$&bp>cR3)|9o^)t6>tn(_1VRXK(WGvh#koALHZ@tE1hfa_(jLw(9 zSiBB|JoZ8TT#dEJ1WHH@qw{40so7-59IiX=Jo%)?x=Cd*jLz3A#ItB1%l0>eK8>|W zWigD-7YuP=acgkQ&A)b^#_CpC45RafAEs))UU>SkLmCSY=a?8q=Zi%z?dz{6KR&0i z9#dI7!kPVr<686ee8X!48tX-s#V|Twa~KOxrd;g=4YuYcNi zc0yzQMrARK&KG(yn^I#V(Oy@gvG5~TObny*g=?DT>%;i&lNxKO%3>IuuM);e_1CR+ zFGMw#sInMF=L^>v&DZp_*pFgjoC>}N{#*T(1HIGC6A^{mR`=fljg!A?=>F@I#~cPP(#l*n z?5u{^Uzk3dQ~ulBw6FhES$5Evb?sV+lC-Z2&+S^Ku}W~tL1GwPyB2}e%-V&J)&Ed+ zQDfbrvKU6^YcXS`){O_8KU6eUNM$jM&XuDMSq!7|wUqfv#qh|yxjXXHF+8ra7)Iv{cO)%_*KV7ar?Ea$SqwumzpE-`tOm$2 z1+ISrny7XYyiai{Vsdn>>p)^Q9ph>;(evzt#`>wsLX4h;rxCMBRg*_QE<3NW_Nto; zV)U#s#=`N5>8Vr2@B)*n;XkS@#OPT!fW&OVC}CQB`>uq>D#a}y5@PhM8$n_=;k?82 z@~cH>G}e1CeMf6zGh`0y|WHdd=2wPa@FWmHLTrTA8j@FxJ))Civ5=Kzlga)}9F9IX@Uz zWnJ-TTQnBz2z13m@NK7~H?|!dI;J$u!G1lEMc&#TjK&-lSu~uHO~W}WrsZVQaL&qU zIoULvvuavSHjOR-nO&)ifKH(gflj55flkF)m1^a5D$dHP(p8U-EA2Pmx++dl>Zs{~ zk}MmGHTc8TG+a_F;OKVz9 z9ir&2isA)zUD5U31uw{Lv1zfT+$_i<$g13wmM8)W<)Y;Mo@bIt(-s!rec#XL_s4Je zWaiA7bIx;~bIx;~^E^{#KzdGb?wrw`M#Kak2`M8-j!e{#OdT1F*ZFSs$$n@?CywK~ zaGW~*fASkMCVQ+gTcy=zitrkG)zkTXHSCS_W!R*Ptv zWSnoGJ6A!E95>N=w=i*n$(Vh2=J?40{9Tho>)4D5qA~knhR@C}&d-@^Owy&!O40=m zPQj-Ikbr<+G;f|UH3+HGwZ7*{Y%@!WvP<%9_!Z?8=hzC1OZ>?BMa2d4ZL|EhL3ayE zf}buZY4upX&7H~pW*;R5e58Vt($&mSoazSu{FeX!{_uP2`u>2&vwhBrFP!<%2xZJ9 z1&^5ooh~^!IVL7ipQ=w`k7jhrdwe9v4SjP?mdJ4j;Tt;Q^NRCxZ42_{JB}LxU|P8U z&Uft;1-ks1_SxF|{7)7EkXq3hxu}fz;=CMNj-QI-N;Mdv9Rv3S8M#Tucw7D=n|9uO z|C1R29G(4l@--%E(u~%0Btg|BH|2M)If&`TaSr7(Y5f@M}+AEC$=-p!r)2QE^--e(ljE z0Dn4$<8B!M00)iH_UNMVU@&M#4P<23m3J#1F9yx?KDz74+i?rWtpUxP(XzY={&p7y z#|wp&O^|8)XJeGk7+(}j7m0^UK37~o1CSlp)9(uCLNjEV>&YYiw4h1%(W!8MJ$d6mbML>AHw^qmpn3Tw zpm45j=3H56oH2a41|N-r>>IjT|4qFfktCu-3auf9eD#mlh~TB z9eI;LGp#jUJMtd!(a0@dKdznx-ShuO9>wX0pxND;t{weOgXUsux_0#IVMgrZM~51} z>%~h3XeP9#3r+`I1P0Dr9}N>o^0-M=t>>c-z%Lx{|ghnA|8Yi2=iabZc}EL%+My+dLq7TF5s z6+BWfe|F5+!g)mnbMuR-6*|t2k*`{#e0@N^8lRT0&Kmjp&?R;)EsqyC91Y!a*|q$O z7uYp_&mOwQWUmRKWY)MqOrh%=f9g9ASL3%Y>)yb1g{2_6rY3j^#>^rYx=z z#&T;8RZLA)2T1ijNlE`uCouNk1Mxc(U)^rf2_|8T#4T zQr}?WxR+j}W7C*Nd;D$uu}8|s{PNDZ{h2c-jTt_+pXYdT-!bRroN#`0>EvkF4Fjz6{7Jo>qVw>L(_cOAXuA732)X33FJ&*d#Xw*1$(Ms+q8vbM* z{>>m=!)C+AzkXsH_rd02u5a=ucPifeZfxeGTbsw<`FP{Svv(}Noc7!|Yu;MCXYZy{ zqZ}POzC9sr&4uy394U)8z4*j;p6U+=rw!3{3V;9O&YRAxm>(Kj`^CnvQLo)1x?$>)Bf=JO`E%2LzPc;EvSeD$sEDU89sGRYtWK_qRF$Xk zp;6tme=sjyR~Y?>ZOY#LcH3im+w$(m(-*I6elhLWe(Gh26L#G5emCO>!($COQ-*2x znr0?z)Ia6ru3nw+alhsdnvWb9rW+l8>WKWb;}71h|5D{|Prl9& zjGoRrGCuN{J8gJ(Q>meG=iFY8>>C*W=4V}^<5z|z-+SPR_;HVYTsY)#*M^8;&t?7e z)!e(^T+n^R+sD7TQ~OJSz3kLq-hE+h{vW4*zh+R*;K&Yr{_vN&xnI24`^bgVzEjh# zb${cEzrDprhiv>WgF7YfwNb8j#+`XTKkmr^b$2AjH>uuzvEcAMLuRJ^^6J3q_x}8d zF?Zly4d1^u_4Oytl^VLO?sj;>GXp0~d;YNzKks?IdUe-hg~xtAb-8}U(3NY8J9#=e z!;{?Io*Fp8@jy4FDb}RFqf~a&ktbicMw(x6MBO1@*E}v$8Z&r?D1CmF{NUIHnjtW^ zzeFnmjyoAKIfSkl-E4&r_11w#x?fW~A)3}A#z&%l`W>#NwSQjbqDI_>=N})0>yy(L znRC%d-rFB+IEpI1u~IXr?n#p>BhoB2NEzW)X{X6hW#T6`m@D?%^rF-)Gxtl;u+w&H zrb`pS_b-PGEKN43M6cT!BD(HXSqwXhf6P?%F%P*XT#$tDimGK1qc~`{L}QUuH5Qi; zRYUScS4LD#Z3tIhzc_SOU5ILU%|*Ay#=sbWA+`>LjjK7&cb%+_o+3)$i;nM&CVq%X z8^y<-1`w&WO8c$SVZm{^7yra^^n%}Dj&Yi!a2en&jsA9W-Syc?aq;nC2ho%wTdj6lZWKgL^SJjKM9saNfi}uoIe7KcGcd=#0zF>pLYH zU95(xUy>v@A6s+Y%ujQlXYd|ecH;LHo@G_h$xWx4rjyWPBN>e!V$z5tvd>gdU60-h?n_3`Y?!{n$P^*YcSl?Ux*OAO^pgEvt_L-Zc3)Dti3CMn+|weOf0G?pHe$x0c7551 z-TSf;gMHbE!M<$7U|%+3urC`i*q4nM+$J0SN1;ne2>FNQBg#dsa}di*!HI|*@e+E2 zF^^C^3oB=xBU8V}OwGrBi}}QkXsvB8TL05f{oixUIe%jLKXc4~5JOX<;h5tzBpdnI zFX5EKeC&2yzLWj47f+@g28@X!>kxi`v;GAq)&#Q2U(v7MlubVKWfN-Ep9pA%@5_>k zJk9^Myt4OyY5^AL|5w?B4N*S!YotLMpMlDRI)1k8Xo6|4-E=9!9ETBg9L_mL{-B8* z&N?PL&NsPd9feS!vQEHfYzC;~V=<}ov6#^@sH(t%X+5ebM#Q47zO$skle;pWG*VH z)!g$6^cMwsUxBtM&`t$9s6fXR=!^nQLmrG^l3xWxWsaJQL_ValT+Pu0AmgSeP>ur4 zQ=r8PRG~o6D9|ek^fe&4zxN~0%FrwYDpsIn3iPA`J+DA-DA3;&$bwug%llD*yb2V7 z>@7d-tw4hmXoLb86llBxeGiCsyVYDzZ06uq1)vuI$+$Na=4Vkc{hM5&3X7h{#Kkkpt==^O+XS)@aBI{@$>2p9;Un1De5N(j&bun{mA zfSrKb0W2Wk4gd>9iHYASO6OZDb!JS(MOzp@wI@u?m0c!H?aAUszfDAW1tV58h%UGv z-QdkT#L7%gs8ex8sKD#OXl`$c!nvZ}F8DdU%fVug-i$%T36)*N%ITa?%jty5-c8?P zIEWib7RQBiL>95qTQBarBvw@0F1pH8C~(EfCE7{W$~3(bm<*z^(b1C#)cAsU-XU+GWcx(0c7|UjAhPDg% z{zh)rtXck*xJ9bTgzV-f(S0RMl&UFsMRkK%u#cGPv!x^8HO5XOgPf)8^wXAKDttl59WGQDd}hS$;}a?KFHh#jLNg zy6(F~2Ez`;lA+K>R;5osm4a$|#*{F{?GU7TsN#u)Pm0X?dghagdYj(gAJO3n+1MYu za?QsCM^%XXbcctl^Wt`>>ofR|%LgF1IBDmsN_EA4`#)hY+W?EEv z%wswsTX^unnm?kk{rG9P_i(Ob&<30-2sGSW444!KH7fHF5B+GzTFnhqps@<{I|X_Q zt|3WkGPhN#7bW*ax7yZg)=E-zQfVq@yIb^DLD98p`}cz5lBPHo9*29RaMv^5YuBzd z?;EtQxw;gGy}RhB(!f@~5M9aFB%upQ=tvSARbKmfA%=uvIwV~YrNi(;yohu%L|-LV z+9(O`fSh!z%cM2Z;MV!l5*yo1ucIX*oTk-Pc!|y=)k&Y3cuN)9O|?p&Tcus3f4U{N zL994p8`vVy`3>RD$Y}IQG*lO#NBDpq@+Y_=y9seDHg(cICWhLs*uSh(*%jJ_%H%WM znbIz%T^o%cM&}yujoW4TjJLYQRkfOE4g(}zlvc>y)$eASi)Gu%9@!86zJ|8jK4TW6 z{k3EUW#c@8LEqzyzh*#u&}#%4*9Y;D#&9$Uq5_7-WRfaE+esJ^ND!0>V)Xm<^>UMr z?Wr}fiV)+Cyke2gwQ&e@CF?MJ;`0KHRv3pYFFWKl$iEqf-05>jjFNZ$UvUQ&9=Ze^s$~C>;z};iz!i z?+Z*3uE!{2RJi$y)znJGNgFRnHF0$vXm}uJEV;wtsMA#T7ID6TNZZF)2Zf~%wmn#m z-JzI1vZy;Tgw1g^g3G9qH+_eg)n_fzK8v)AbwcnSptwee9}>|I+F0rbR;!fhByr9# z(OYNn)-?@9swRZz4T0Y_UIi4*EhsK9OZ;GhggK7J7!&HSBvYliRM-Y`FExBRGX89qZbj)0P z7AzOz$9T-L;;xCR^knp+ba_aUoo5t|I<;)9f$4gCH+qt2k3j7Duw98rq$1BMU1m+g zTfI&E1~$4(&Lzn88J{>VrSMPm=C7-|q!L|hl#=N-QfI?^{8Vi}?YN>TzJrZdK{9hLC!4h!2JL8evspXJ z;`mhKsQv|HC0|1VFG~oA1V^>ke$Etk#+-N(-m)U*v#2*Fv)*fR=C8$X9l20!x(mq< z#$rweu^du(>a6$#xu?#g70JC#BFOM2Mh*q!73ni8YM&w@ZWkMc>b;d{6%mX0Xj+5) zYpn63U<8()u*5O1w90Vl6+u*%U{>BlJG(2L=2avZ;4^~b8n&`u1o*7e{1PsIbedP= z@+YVHWn7+fnqR@?d8heRTwZXRU&CIsq0B?8 zF>%no@+upK;N~B~n0w8M^(JTLT66gii^FHtnb)d@dypAF)!5{_7!1japN7~vvS)F^ zdX-RimDVgMnNTP{tlyP10dcXa7PciW4ImMECJR1@!JB2u8r=uSFT2E|hK$fglYzErZ{n!M-nt__1~2 zH!$0RJ;Z5N0VTSo!{Fu+LE4KTJA{@yFX+CBYPDsNf@|DQ2m>TNPZ+MKd55A(qPSB^ zW~%y+Yp6-qjNnB2bUWN$`?rV=Bi;wCH&+~4+_BdD{&1oBh(`k;4yK?5!jcYVsoHa^ z;JBK%BwW}?dU<$cULauTSEztgZ=8)X%;Yq$6Pi6%*OYbcDIJE0SJtm9QR8O1?)5S;&8Gw0L40nZv?*)$^bd)q3~bW);`LT?Q|XoQ%JSEAh$53k7lo!h zT-Zhd=81&GH$p6D;!S5^UU?qjH#hdTVi`)aRjd__QSD?x{G&dg<>?|;F`+nZ5r8Na zO@ee#lx*5Xf}vL6$Jc_}WRe=0ijGUF1w*N(zi8_txH7$^=?OZdGVfmGC=fL{E~^$E zXW3Zp5k{pbIK00sGnx!nmK)3!-em*LhF_OPnWa7ExX(;f-8P-pV2tSN<(seQ#&E&R zPrP7`Yi6RFYGvHAj)H57x9NHG6AJLh|S{obZ>04;}j=@ql+V#Z_L7kSem>OR?y znP4LsO|c>~1v8vfOC}?0$wp%KF|j`QOcHD?6INFy)=`fJ6JjcimxQcUYhK6E2q~{p z263;ofg#*!ZD0U@hym=Sy$pK$WvZM~imaLHA6nnYLkr$vu?|;aR({1TH2)|#+!_}6$XDyw&)4#W3;wf#w#ORUz&ue5hh+ z6+}AZ5sy`HeEXxYjaI)j4YT}QdL=8kNnxWA!HKD(ZNpJ58)oZq>@-L@~8Cjswj7c+R(=2R930r8)^Zl{SgI$Ok zcT>3N-TV1b+=;71FZTbM!YzZ`md~3giAFg?NosG=<)T(Z7c1xE_Qus>oG%>&m5iu| zvA~w9+>IJRU$vIEzb!b9o;5j_c_G*Hl2CT^EZU=?F1U~OFuDFgf=qF>tWOyIX7wee zWYaP@3=7dD#a}eovM#z~Y~3tUpVBLK%=O6M{YB*NZi1we4iPR2`)!fUhp^kYxhV{- zB=MV%h4T(O3@nyi#R8No>3|{P=}fs#Np~~|llZCiw2!t6GbxJR47x;Mo4=t%&BuNr zl>G{|H6?Mg_!0XSMB*<4_^GvkcP#87lzoavs`LDVJAG8eUouC_DT0zGHKrs_N)vLv zK)FI$!ivp4s@Vgnf~C&ul0oswjE*W@P+PLamw8AyrV?u%g~`W~zkdZ_I|vNU@jA(vRS@br-1g>nzlU>X0A= z#}7ylNGF;lw+qr&o9X|?h;C1aMcQk{ZkYRM2)Ax0t z0SkL>RsTdu5lP01K4+QZz8LG$gc+)rA?B+QqqHs3&k}bL@k{ZUEN3T5PG?zS`obL7 zASVFIN=>^d)}%%ZN~0}$OBTle#=pM%?z=+VH_a#Zopx#NjXUHC(H~)L>Gzurm-xqi zhCNWbU`K=$?CPy?T-De+>5rJ5UC>R>X?{awBKAGmonUAvJ}el%;2kT7EA9$d?Dvpy zdd^ze$~<*mGLKhNoFGWeKJ%QB%~RXbJRAJ=jNqvIMRc4|*)Nj7c<7WT>(oWoDU5Ww z-4jL*5WJs3Indd^W^_g}B9#he>6$6-l2BGx<@JWpJ7U^E^|@KL9hvDZxzDDyeWu*s zs?QR}{ujjunawbzRK>YFkZ{a^ix4=r&Oy?V7=*Yw!Qft?!4i&#!AgcoJAuVwG_G1| z2%2wD{8^Ow<}`(qR7W%EA|b9yP`gq4nJ7W%_tR{H;d(5*WS&`a*P7SI2=2yC!o>!m z^e93eB^q{OF+__e2%BjsiiF~gJcoPz!8}(wea1BMgM&&g1To24(E*dO` zYCD#^8>;XOCGGkG5-S&97|a+uuK86a6g*fFDplB4M4MTUxt675lXT9%q3-z3X!*yl zdvnUWF5LZBzkjW+2QQhV8p=}G7%q;sNS}($Cq(H>44b|MHH0+9RZ)0SGLK)0Sdh1b z*^V{s2jj6>T{RXv!ZCq2` zE^jr-?1B~`7BV5(gI(smlpPE|*}rJ&4C>O+Ix8}7mYw&_B%AhbC$_P?{TnDo~xY!)fb0jYG5}^Ei3lFC!vm9 zDtOZMRnF(A=*A)dQn1^CtryI#2m(N&@DDs<^%|R4;c=p6p+F^>bOGaU4pu|!)Yzoq zx9wK%5Y&6|$1&D@=C})S`&jm;P(~onx#(8eV=lU*Y&`_SLHxzxc^2Pu7>y^)aqJVC z)dZKO7i}6{gQKm|yft9rD}I6w7}HOAaJ5SLPLpFDm?u&rfifWWgt+(BxHeAUf} zEi+qWZCDI8oCL})XE0Z3mJAl8uQ%hb#A7IDi?lQjHk8bsZjlbK?J)md*gsqEg+vXrGDslxa%(RM=YRuV`(iOxA?46-|+}h)qbh z2xX^0i{*%jS7eyyMw_Ke&Dip|f(j2&gyqUpv`Y)uuEBgqJC>+>{5zIuCQOrXu4xFY zL-S5%kbe>WE&YqXO#E7zlUww1x#lF7ziK z!kT>fIw&mfZwk^La%qdvYBDrZyvAWgtXVQp+9$eCV~e5rkSnqb{gXmPN38~L>99X7 zIxsz+ftq~-``cImB9jKXGq_Q`^or{y_7srPFp~Nbg_-v zXDJTjE+RX0W%(sS4iHK&KT>uXbp7CylM8YSB_|V7iw@D*CbOKh!TiBJ85BGy+w_3u z0aCi+ZuFpZ={hW4rmtu2<;$0%A1nE7nd_)0t@A}}<~kU**UHxU!513;fl-G-CDO!R zPV?Pb6<_`d6d{jLZswm_fAi+0^c`g08|Lm7=B3Qtj(IWWg3a6ihUT?RXQrLVA{(2i zzP(~OxUh+eTt0(#Rhy=M=k>zK_6{cJ9iHL-MoPV~g#4bQkMf=bnL&O#;_1NT2ys_2 z>){2py!7M!mc5+R<vf5}hR0g|Qc#$T<-Pd^7FbA(}+REEX?lAn%K zaQ9&XlBIkHNR}etoxz=~-5dp)ftMySZVw=tE-uOseG16UICcZt#-QY`emlPcNdAk5 z3*G%vdi3x^MSx`c>99j3L;nQi)1a3hcW<;GH(!C)<87i(D+TJ`*Wd1AfYO*Q>i~@f zq~<;ZWMa@pK;sy+6%a**nyUho!JzGc1P1K@Br<3>pz#c905qLJJ#NAO17%P&pt~8= z4-mzcnu`HsWsnxogAAGmXflIl0Lo%e9-#XfGzZWW2F(TZdj=H&x|cyVK+_ns2+&jp zEdfNIKu~j~fGCpHTsffMF~|w%9tN!dl+7TOM#X7n0>p8vd|_t;&T7Ob$H@>vjmu@Y zKDTzj|7N|5(-f&^gy?|6VZ>w!XLG6eA;@t=W1RR8d<4ZOONK~R0mG@f<9|o`TBpeK zAEN-st;-N`6f#_&+dFVQ(0b>h$QcpWZJoY0;6Fw)KI(}Kkt{pI^)WprwYhjPGnq63k|8~vIH3-3FQnophF1P!A5_67T}<#GF_wsk?my; zk~{d{$bJ&kYL3a?9>Fy6b6iih%t2JUWcNaXUkkEqK<|~fgKV5zY7$Hn&|a2HGQa&d za_RMjEEj-cz3a)9Z9y{Wdl&vgZa0|cWjs`Ks(ztdzf~O9!>QuB6o)aduWMn&6h=jy zGDLQIgW(2r)^ME{!Ao=GhWuRQ8=01TBST1TJ}#nq8kyREv?qTp9tL{smm92u%tvj> z+K^28Vu=4}PwwCFP|d{;^V9gR*se^_CF=CLB;80|vMvQ*^GQq4B_t#yCg>BA5=JH@ zC!{2#CZr|m5)%>=6ZMHni6aw}6H^jX6VvoMeS$twuh%E(N9vRHDfp;MT9Pg)At^CQ zpOlm|GATJJB`Gy2ZKQ5w!pOvt`jJWal2Y=>6nsi4Em@bGkeryTPfki6iBH0$B&Q~) zrRY);QW8`2DM=|KQ<76sQc_dWQgx{bsfnrj)TGprsmZA+si~=HX;3i@&8I(-@GTG@Nqn|8nRuO43=zCUclSO0ZnP=47HYu{PBBY(v` z@dro8n8PE}tIkb}J@eIwKW}(G@slb155Ek*w(ge1+OmgYpBnP!%ENDze_Om{m^5>} zv%i?JuT#JCrpos^HtswpMr=7gWQ=?M!iOV1^Q3PP-zXatYj=&lc4T$I*x322ubn&R zN_^n+wPoTd+w+I`(2s@Bd;t3S;+(&x&)hKEh6&kvNIa`nF4^|r!OJr6fF$Nv7V zBYp1wsPjFaEcp7azQ&RZbJCl2sZm=W{9~U>r-o#`uzS}nU0*oY@3kusBR*mor zRIV+*Iz*gm)gtAYA87f-1IiIJ%af&`?!T6ojE@KdN9_e$|NdQmba*Oh>;pF~{Vu^0cHu5epiB z;u(CO2){weA;1gjz*WKu=!$%Yk-urujy# zq6&p-(WZBHq4*GL6ur6S}AUT-P z@LiIYm;^o8YM~R+Fs=lBGQM9EjKKuHKNy1|^iVJcZG9btNkUsEgE43;3}y(lm4vop zTVm3Z(N-*?hG^7G=VY`+YZ?WUFcRiSgfjzjMndxBU<~BU48kPqQ9!lXjyHApN0t~6*!|KCW#B|6V%oq#^oO=PsBxL1h^*pxEM`PTiT$ux;XCtF2MD$kBiX+wKX`Xtwr3Z zF9Tdp__!ENP+PYvZ2{oMM31;VOo@#*eO!ztsI5DK+UovQSy6zi#>d5Ig4&8@T=EFQ z7a^C%lm)ns`?wfQP+LQS+A5oT;@tq3+BXy!O;B4y8JFK*-jsv&0WPhNi_rwN6&KXj zdeOclb(PAz9GXk z`nZTDn2T0S0WN9zxP1XGf7lRBFqe*T`Gj)Mey^Pt;EMJsPBg(>R9y#h-PTd(UkGr; z`?!ck*4pGZKpQ!UOpbrvIUr8o?B~HgzK@G&f?G$Cf!6(8PwsjJ6^GwGb9`JxBjZZ1 z+jiX!C>f^JllY%P%hWKeiPX`9V;&xC7XNOn%k^QB=6lmOtOe+UA?V!Jl{z{=)Nh zzW>hxJ_LgDMvHvgxmv*+gL%=W8B40H46XV1k4 z`E0PL&p^3zbLJIg=jP0vJ2NNuVFg=gpKr@<|5wa;HzFh5T# z>!KJ>%f4sX2HT3*Z`xMW3Ob0~Z}}i%1sP1LNNA~s;;i;{hSP#X`};!pAn8H=3t|a= zk~=4-V7^x8GeYn)S+Dk=$$SYn;A{Vx%$IlrzV@HVeEJ*kwg0S@QCi1TE6cQb+`5}> z2xJ=t`r3w|b%)y!$Pxm*ZcX4DKu8V+g@NHzIB#B#e-z~v%r3AMkk_d)Zzavax#PdW8FyJH&+y~#OcgCD6Q_uVjQbcqBcm`UbCDrdmzW!?^BUE-h+v zTfWSi&;6%k6zh+X3PBpHW`W{V*ZJr3{Qt$n7p-f@0};>g25WTw{CmeJV)f$)Ol^`NYt-4KsN+*8f1vpM@RBbA(IRPUAF-;Win13(LDzI?3-Fk>zK}s z{{9W<4&Ex$LVSnv@_>(tkZFA19qFZ}t_R&FeCP8>Sj(IAfd8Z>trNE*jY!H4Nx z7T8~?OWl(~6#l~yrZbE#2&44TeF+t6LhFMC1vsh9Rz?I3wSgC@izYgOnv z=m)ohCZ;W22ll0cCc7r(^(7eD~gZBUHRAqKR?xmj>9B} z5@U?fG)b6gnPD+cykjuFQmiuu2O_6hj8g=wY5L#@a>sdm9Qc?xRZkM0a!2~iqMX8_ z^hKG=ZJFt|g?WY9qfph_mZwk6&RdecG-pY6eqlN)p!A}`EIPNYgt$Anu|2u@99Pfv z=7w`(8K<1Bd0B<|Mfth5h{$QfBc>ME@)qYkn73p>L`weRg1kjJg`}O1a}(sV)*zo} z%V)#m^0~ZPKHuBI&c&sp1rA4juPk;h{p@LW&N*;^&Jh_Kf+phJxKvD_^GkmjxEN={ zx6kWd!g<{-yLNtxbL{QE+!va{6(3JnUM-|>8;+FCid~w*)lONk*!A}mZrq>dok}~A zVp#LevYY?a*O>a_$xlxWyvz8+C)VJP&J}x;D2C>#bIs=Q;=gu2cj2=K$KSC=cXI7=)A%Ppy}hy9 z=$_->d;hbe$5wnX?#b-sCszOV>bRa~MwLAK^!?)=UTR)gHFWH_^-&uiSzj7FuHQYU zU-*~$(Ab?7N1ont==rfvAD%SnmmUkozL|2UVNPMp*f$Stom%JkEqTbqCqg$qzbAR> z`W{{1{^p6~@8 zhjunkzT=U`i|2-|zLfOju??>-KXCBf)8iany1X_eX~Qp*`#BPpzx(W?-?^*a9-1^< z*EM9zw(jr#ux3ecWX)&WJCA$emba!omKgu-kyj_rSdch(+wpBLE}f8=_u9Urx%SK3 zF5Y=!Ptd4$j5YchXI~9oVa|T>)Zc5RiBq&wB0qdt3Yos<-&Ma1A74Lf#TUYR;_4^U zfBtpf=!&BB%yHcwZ~64&!MRx@~X0R`_>>_43l*YhF8f><;afJbTIMzrFGFrkp>| zIlEy<=Frei1MdIZo<*NM+y9GS5(myoy4w4t%RYU}j}PDek7QRu_KV}3uTT16OHR~d zx9u4gGrCFj#BLNq_3$ zF+U%8s%m}D6Zt28K7FZf&4_iI3cI?ymWRZ;daWHi#WA~=qKc{XHI&M6I9Ir z!-HWz{Q>9VnpajiNr@}}!Xra)er(P%Qx=qDzxLMFOs)JZ4l)3^hsh(!>yp zwAYwiY2>HYo5~K^^rF<3Xm;3RLzKwQRrK((! zU)5l7_9es0tzn|%5?zfU<))r86jpBPB}3umrrt6XQEuu3=t2q~_Iwrbfg{q$NA4>( z^_3}f<)(h3t0}SE+Fz6)wB!V+S}qv**?YwbuaXuh8NkR}pk$y7LCH-r1SNxHD6-si zvkXD(Eh+rgQl_-r6vkkRIm~4+MHL1!nBoSL8B8-4jAk%(1sKX;DimNUgF7?0f4MbW zbX|hwx02--_%K|{=EDYZkgFx+0-xUG^AH&?d#FY6P)mgDA<)8j*(WVJS!{pkgVdQ2 zosNh^R*_d+d}Q?ne)d-vOnkZv0Im<G?EbW3ln`3fpiO=XpQ z=?=J%xh6<AIbEcj1xD~D?xyJ?V?Vx{+&4g?+&pw zyy*b40_*>4Fc9ADhfyU+mBwTjKh?!XgP2v15##rpFV^ix19|)TLl8ijFamx>CZr5` z170HU|IdsDQtulL-kivKv^OU**qaj>?9GV`_U1$edvhX#|KH?9Q$NfT*UpJZhin{l zoD*3D_oBf_Ug-Yk5sS2Q6p%MrKq!*u`N$f77;(?n{SN?30XT?2wMucU)Ke-r>FxPvUA@o7gc z@M%D$eTi{X4cB`!+7~RO|CiBjc+#>WHvRd?udiLbP!P{i{el2f3F8|REY66)RUrN= zG5(y7Jc(eQ@D(wL@d-J`auLI)9fx$F(!N2A*{rpPk3<2(M^g2|M^?fzlsJ4(HT4gd zD5Y!XfihIfMj{4(Pc<%4#EOnxhB?(q7$dd#Xt?|FO$ED}`%Zx_D9}{}>Wa=J)AduJ z!3s25f$mVCp-7vujt2nI%0tbaRiG9H(jcYEcf%BDkOD<2P^`vEYe2YBitj*!U|4@S#gH8K$M!u%0m|EvRSG!mJC8lMsC|zi6+Yb}UF4{Wtv)JOW5=JSAcSAPiHiYYr2HdQdVa-_&7bQ!D0`mWd|oz^b{-R za6%2I6Ds;Q9R#Vkon+zZ0ZF!Z_0)+CEn-=f?P7^bg={ERtk9-fDzdd{%lqcJ^1$$H z$w@NJIX1}U>E;Hq0Yie27)T5m>e(Z_+Y2H^=L~IxG3q1HY0(xmk`g#LTU%gsW~eTR z{K);JTVCArkzew&4goo$fmUj$=~#M8-;XP#siQdN}8(Gp&y7oQQF52^Hr z%#zG%kzD46MyuLI9kluU)Z|jeXF(UNFlq|~e&VmzvO3#xfyLCCT)QgKyyK(h>EFD% zepkdg^b~V*ljyqKS!Dfdf~c++^Y+rVizT_vo+4JD*I>)ToLs;9mK5`MuSrbyelb-_11XEBRXuoNu4R;+)<>zQOj* ziV9qyp*w_?w-`Gnx8 z404_6bYE3=RIR#hBEPNlHgqIT+M8RUE<0rZguHT_Ir($G^Z~?8surTEjOt3!v#&<2 z1KR#eQwH!B3B3>nsI6OZvd$hXda4Catxz#ul+Z<~TbnB2I!tB~>d!^mg_yo{LWVGR zZuN6eM)j$Ndkf!t81z2ADc~Be03#!TL1zKgGN?D~qkVogH%ft~C{T_9twMCRGCHGF zg|vn_{h~{4>zBKZ3{5RgT-GWh$Vw+7{a~HEJp6;-eHghoh_W= z9Wj08J+s7;vuU6bB{^s4cZn6HS_5I6Z)%^x*({xtE@Phxffy+waSQ|JSQ@%ID|KAt zM~l;_HHdQhVZ*rTRVdQe(e9V7%tQ1>>6o;~$eWKsccMl5*dpySm3?8uo>;Yr^X;Pa zvC=WxZO9>Eg9i$QsOqWC&@i%HC)G1iq`K_Ts;(uMX`9Z6Kl`C~ObtNVy~Z8pB+88jE)V;J-! zzT+75vx1|i{ZtZZI2sAC)#q$XAc-Q(O~tT4CZHi7p+BUrlXW_FC00i&LJZf9j9F@G z7ZesxUsTBB?St|%#NS9z#(RT;&B>3wx$b{cNHC3fLvj}&IV7oy=Z*oALvl*Nh5AE+ z7*Iqa`-B(P^HNaFWAHnU-k_4Zw=+GhfUdL z=&?xumGGjGgtgZ5YNzm{qz2>^QnB9kF2eEVD{SV3L7M!Z}TpE{PR0%MoEr z-s@N{5H9Xf+lvILzqD7XYHo-dilgKN<%Cfx9Az&1J(Q`H5#)TBGDn$AC%Qa@to~GeQ*o1JuBJdwf zR$;CI)(Fm6M`MHqMMZ%i)eAd8<-stTCrC$(C^E)kV;@RV9W4|1NB@Mj$+;2}Ep{ML z0n;qL<`FuZ)dxM8SN5vh27Cv(@4&al9gFV}_h@_@+>rvm<77w?HXV1I>{iqnr!%2$ zY)$Ss)6E@9rx151I(20R!a5jcge|emI#{r@9CVJoVGN1;veo=nzWCAzdoMwn$(bFy zLs*D$*FC)Wl5WK)eyb~YUGb%)2L|$6E1i9wz#ZqbMrWT?at6P(cC2pY2_}fOx_H89 zv$Wej4>zZ(d@4wMPooqOAYD(sgL{sX79F&Zj$5E(vQzsCI8DxMZQ~>-JgMmUih0y) z^#`3DmD?OG(fp$u;Js@(6oSYlUHpC!iYF|z7x+wb=lUSv7unO`o(LbtZG!5_DzkH{ zYHYl{pHRFyDAqodQ8@OfnHlcEWA*SH?!?%;p^JL4J&8y}QbT!jiK#|N`WyMJY!n&G zS7;NR6F+pcB=C-Isw7nHz zxqD0-RHNJjg^N`hn|u|4k#?~v$kv73ixU2=5=wrhtqNT$gd2a=nSR0L|M^rA>zl4s9Vka2QG`#dcMZkX`@c$KQL_o^wKg! zV1p)z;)Ec{Rqj{_(@f;IYOu9S-Nn{}-^zRp_6y~v^FWEtIp;;E>4G5b$NK9CGAMm62*|3%e&N=-WVk`f8o{uh=NCGEwG}KQQG6aS#bQCy&^=|PUg9JTy@3sDS`hh z6^iQZ3vzRFjp%hkv)kgFxyf}oNUCx*-m0$0p1Va|&u^`&JRXEfE2z#m;;2wutuvJm zMA4~UnrL#S{k9IZtkpTq!^AY7@pA|8xrE|M@CBJ2Zk7Fj5%pWF#c4k$NUjgjqt#K> zG#cQl%~&j$oO$xFV8ftkJN99)_Y`JAAHJDFR(yG~vZys4p}wnhTziPHlRC9K6yDzs z$sD@!adNeX_>J2O_Sr2>VXs9yb5X~ zmLwLsG@>J1S+&rZd~$UbxK|Bk{xBtfyRy4UI$(<0Z={;dt<~2Vr8)-QWJJ9>)|7m} z#7|WS7?-{-rn1JgiSu?%j2XV7FXAkZnKp(%wf+oyt1ITdVHksE}PE40O7?}s`9`IO~RWLH!T zO%Gse34RBr6P zNpM_JKTt~!AInA`3M^yOVuX%jZDlhG8&OUDP$3pyp6DHI7I{&J38OZq(%atU=Q)MrH22Ynr=X)U&~g!d?=NPAH~yP7b)9{l*Yv{!sa^kCZ%*F!4JA2(8t4iU#C=_Ea(lPw2?sDnaO4f4p!TVb8Sw$)QbnO38(+Qi#mcbq(DDqrP+R5xZ*qjs6| zec~-Sc@8=$qqt7?K~fQ-K4pffFH>o~tm&_an?DCqqkEgBIW5JP?KZ5?zgRv@#GDY0 zBBh13TslH`dX-f!@6mijI^rK%fKG<+4hbF>OMbyh-|* zInM0*fgE?IbI>~^wT{vx_t;AiF)34`|Q0S#$CKr7zR1KP(`K=2- z`sDzYG$<5Vvc|Tta})*GC^a}v8_YX@JD6G8^MU<;XS*G_O8>Sx=e8K7YD!|*fi4U; zOS{D8Z$#;H(d8bPS4~L#cEqiwT}+RC%sTW9dFxqdJ}&P&Tb4PAJuz&x4?7Tw+T&gA) zpq9qkgQH@)PAGPvD5gpQlf^dL`%JJV|HPLjp~}HN%>amoToT#?Dj*j^A=-^X1Nb zgLHO~@V=TDL&ix@iSSrhJV60wLq%U{0h~rPuINrFf0EX**uJ5`5=&q6Vk+rm6yC=T zET}eNnT5C$87nHNj6%^wg^$5kw_B)*ULbA2B9^<5!m1o96ze;KM2T&D@G!N z?7%PjBPiF4*qZJj*Nf_(DA$kukOU#s@7WRoNYRslI3!r7Px2o~F=wCIhjO*n`0qZjyeKyOiTwgKc2RY0z?lQ^X@UM42|n zn$Kglad*;J8l~g#9Jc;ft}FY3UrWD3FiOADPHF2P#=luU{k9G_x2HQrXqb$H)o_Jy}B1N9sMf05IiK#`YlBSK332(rIIPKerm= z->30QVqpD(j5f6O>lpGYIaP(7<@Q^$qfqO?0=W~&UW8fj#N!w7^GoJ!HYvHg$tOG} zUx`rwPgCc>v$SH?LH>*mLV>6L(Po#qP5-$4_xlG)B_W7tU>_NF{kCLc;0E>&xQ{R0 z4BG_hK%0;nlN+huMq#0@SrH{Qh^{l(`e;7l3@yQyi0{#)AO)KpHJXZG+8`GlG=HLx z5A@&1`VVEJ(-mZY|JN46iE?IZCTrW>-iER{Mo3ZqnHQ@->7tVgj!a(nu-jxqT- zdgM7%)ORNQ6hKKia;HGKgOqbsvqC3GSAVY?dQ(p92Xeo=NNJ~Li;kt8uLIJ~f4yn@ zF{r39WqLHNc;zOniRQdcQMTPrIh+KyO(>DpO>lIdw)w-?HS}#=Jox%uV-hSN#rDTh zimUiidN@SAm@+oMwgFcNsgXS0+|JW2vZt>Gcv?>Gfu6pxH<_PH-bN@J}I(HqM{rg8qh$<)~L>&?mq6z5~5)usHKXG8W-oc@{?xE5IY1Ced zAa)MAL0j9ZQiX;Fg{ni_92(y>r|J|O)L9)GOo)&!T|+~=5v-y5_9J{W_~Sj_uM4bz zmp*T*NNLV->JlKuBGCQ2Ea)z3%Q1W3kx9qz+%c+x4` zA`bLH_bSjHK(gLpH~D@eFauBuY*BM*fRKs+r30G8pm~6(SE#vcKoc3X5Rky2MSw&G z6#$ydARC}L4B8H83WIh6x{E=TfT(Y&xm|!P45|f0zi2>rzay83keJHyOTT zEC5-S43VrnhEw%calO6TqkZH!k7IX9y9^OWKEn+d7R>d9_8tY@=Y^(ryN33Wt+bC< zWXTZ8vdglP!?+RUBe|i=Msc?-9L?RV%Ha5O-H&&x?^4;hAb4IUohB88+-9^+i?hFV z^gamRF%N*;IvFDQ4>24U-Z@;=JA~^!qdV6-Hk9iA>R+=`6q6wxzQtiG`=%dQqj5?on9BK zi_^vH67bHZq-b4qbaYI#J~}o!E;>FsAv!TSDMl9)9TO9ykBNK_O$0fui z#wEq;;-lkZ;`Q;d@o{+ZPeOcRd{TlgfnE=!Pl!#3ONdWMNJvabO4KDrC&nb|6JrzO z65|sS5)%`Xl3-#I)F(l764;V}lG~$;j?u@)#U~^tWzNsa&dFU?&=xODOu?W1r=@cA zUM!Bi1&d?vyyEcsEDkT$k{Nt|LeH%;$Ox|3cOKF?x9_ll9}axw%<>CPY+u8?dg#(@~P7-e-BTOes1k;JDoSLd^mU4lsji-?)3W9DntT^?50gF~6MJkX6%X^+!|8BNzO9CA{;C=Wc)Q{{4@to*TUT%j5^%``h{8 z{G~yMk8^L|^3NB3xj6dV_<6w({TMgi^jYrg!6Ae_P(E4KQvt3u(WCW4=-z8ac>+yYT(eB);m_j+jq|W^MIDq!_%JL zzwf4=PoE$3;^i@Op4`*;lH`8=k72{+&iX^8O?9dzI`vsq#Ho3QZ@;lu*7`#1Z z^x|yX<2V`9`u$Rr3e>7GK7q=)^}D4oQGkYWVBpdEy%r>0ttzGgi6hBac#90tw-?DQ zkaG!2Ev^zD#)Y#yOBcWxKV~$r5m4>N&;VE$fT3E22>diuSri0dsJ9?5x-7 z+S5?(RjVHJ%Gvl>+S~1E$P%@R@;@cR6DPY2ZcjsZ)GDe)=;)Wf>Ere^D33vd(wKuo zxzEHS_qC^??5kE$)j=)1y8rV%?P*AYT19gZdCtAMPgZ*xl-Qu5+KJ?hUQsoxJq`5; zwTfyrlJo4}4tHQP%{OWlRVh@D-aLX_Nz`=MciU6Y@KIbdSE(+T_Y8-`J6D5eafr?}EV zJ%M4Ob%}az*-gIRtV0eku^g>FSae8ov_1~&6WBx;nM)s!HD@3O6Zqjk3<}ZD12Hi1 zcmO6=hqpEbVxX%F+~C(03tb}uFqmGs{Q(y05@R@8*Z6IY)1yv8F#U4kAUQb@1DnkO zn0VMTD*&TQNaAAAL;aFbZLk%Q9}^D?KMmlDN82ApIwBg`WASMF`T$G<#8d@f5DKmo ziN(*A1PeV#BMK%)2aFpD!Hvx#-1Xiu0tVl=n>hc7hqkK%q>(E69 zqv2Y=iLMv0Y8A^}fG%r4IPK@E^l~v8uC*?h1g>y=6Ui-a_r?ndeY!sNaxt0!U40mr zPgnhzET^CA2QL?+3DDJ-arxRcYs-YR?usrfjo86x0(A8Y(Dlvq1!h0jO^Kvno09{1y_u)TQ{4>PQHQCF>XaaN%U|b{dO-)}f-ZVK((KW}* z#b^R_VKbwZt|=*Z4D)j>^>Q&9Zgi{n;9>BBi)L^-W?u=PB6DSc2E`6L7)^kM7?|Lq zh|uwJWEX1}#lp2-U5qBcLYkHQ-pHA^s~HK6QGLF`58fw*~0>L&0opz4`il ze=-^eqY2P87+AH6Mk|pNkN?2w=hAz*7)^k#A&kp6QhHpHu%+kIHPy?-XaaO;19Vk9 zmK5RVy3fnSXaaN%4bU~K^S`$ExgPa$F`58fw=*tZ-?+EbligXd@MSL-qY2P8EI`-( zVe`lMxvITfj3z)=B;%4t5dJ#s(dw`LTqnI;j3z+W@Bm%<_agAuxIQ1My+eV~1n3&U zxP0-7I1u-gpG)iIVl)A|q5^b{aIeGP`}%a5yj+Y1Z=v)`Hsf?^bQc- zBiGBtXc*2043YXVCBTrSe#{fV91pPZcLE}x@_CXh?VxV%ESC(dfq z{aoQ*!-*!4i>fexuG=~8!qa}P(Oxd1k*zlR9MDbMgh@^V7a+ZcT>7|&Rg zlbM}Sl()cV8Zj)&S(32`uUE9eqh1GPEy`S6kdc+SXwm%4tosyfzI}-;qvLypnR!Jy zOkMs1Ifc>mHuTBU#mptycvWM{!W;<6!28a#?1g!@*yq|d)CxL)+~@fKVg(sUsz_*Uh7zof zZAQ=nMElx8_yFkv@e5!Hypy#sGjEAj=XFBhJ=v~~@5y}8*Wv59lnn5$$a|j z@O6BzjZ@n8sWzTzce`yf+Y!h<^0&1eLE8qmBakKdTiuqxJAjZJ^78$|DSz?eOy4NV z&RdXYE6B_%mgy zwyiwn>1rN3T9$gMlUz*jj<+N)iDf0CMcOeeli&AQYZ&DG&N=V<{`1bqnf+bQ^Q>n* z>;A0E#*Lo@ta~?LZ3oN1fdl);4@?-Sz22|whY54#DUQ^nQ7*@bQE9`6B|U7l*(TD@ z!}0vLKmCrPpIP+tIQ`70pNBbT5y3}&L@x6r1)ml&+Oh86=$myz{EpDDG)s%5cdTeX zHRS)Vv>&!;Mg79=PJdWaV1RbDUqrisgZjlq;gb)Fu;spng>pL&r=BeahFI~qQp zswMP~Hs?x`R5w-2=pSRqoThE>A06NaO5rp~DxRk0#YYD0H%XF);MAE~@Azo*?U|Ak zk;yroAQ+t~Ne@vl+N=P6o24B>98w`YCP{vekzn9*CP^}at7l7^XISTeufhF&wj`Z+ zT7#ktTyQ=IES<*_vmnkv1W(M#v}NAwj^E1(QYH&pE;7`TEycyz{yx7N$)J?@p>bH^2L($^J3zfKSI!$OND4I zhTtb01{?$Rp`|E+W!lyIqs{G?Nz#>Nl#cl?WZyDg=m!B`%tI+J=jo&&xL~;?l`Pj* zKM-v`0N8N_x9vWIBz0RMNn`SP=Hrc$v?d>=RG^s>qRoQ}C2407H>MRVI8daeCB&Fd zJS$0;o}=jfqe3Lyoth4PO)a_6H|GQ7 z^zYmz3xZXDm!#@#ur@Lv3h@HAql~s|8xy0=4*{y%$=bkasD$+hUjK*}Nq_-;Bw+`N zWfxc53K5^*g>JKp7ea$slKz6=`Y*IuL!!;MzL2E3d$iRn0;ih*@&QhALrO$LP~`stvbj{ z1KE`}qEQVyq;+~I+K_fgOL{2AoOD={+8p5xCof2nMjw%+!)LU05LkbfYjGpm`)4I7 z_8iwAh2XGr+?IBLSpqr$mvb0Egk<`hWGfUw>+jJPex#B$14#>h zB!dEvqUDdjEJ@a@q7G8Pdg3Y)yvhsxMFc-X&~=RmlMtM6O_E*~!A}v~gy7_#cwZR` zbLRiVOJEo{AO0*!zx_;YAWTO3J?fFG>!9Nkqy;8-G;c?!%?)1AZ}>yth9p(~u8m8M zHq5=vwUBh1KhYTP@Ju}k{eAC9((8?qb~w4K|4)suRbpD_0i6R5B83$alblAa)6i&h z5$e=x*6e`QW+px7ugx7A?f;@blRo!n+Vc3${-`)4#u#sy*62I)q7iAxt|AjWN*jDljw#yaikWUZ$*V zbVLT^qm+mh%ARb^r1=rhh7Yxh|I|&NMznG5nY6DH)6PH8IUpRvj-fM? z+V;}29nt3c`&3^Y{gKkqF99LDHe&d_ z!83uLZoylN&_?1JJ{`)lZ~%m_h9V1*VFRGyR|I42cWE;ZLuibhYzbZfnBRi=Izn4G z(@<&W`l>;>Was)^&}YDOIg+MKe7JSyxd`PtxW1PG-)+I%i%^w=7uHV>uJ0x&hGCo% zHH=eYhcRiuFe(ef7(sagltsg+8iLmWZpODcy?qEBAI8(GCk74p_y}Vn5$c&jOoNib zwWotJD}`%cDJZXk@~)8CD<~&HsSz@F1f{Kl8dS86;ssLZ*$BHgyuSVZk`8xwFPrGLVI~k!?#Yd!tW+12JLLx zy@sga+^mG*XdA^9LSJ#-uRuW~?&6tyB6R-n zSuL0=5n3~X@?h9Hf+t)8%Apawgsuq6O;8LjPKk1HncglYB?!s{L7554d>7ZVT2MBD zvXxVU4*-6Hug_ldZGK1?9S+m`5?`o>6>Yh#MvJfRa9n zYhENM&w}!jpllbE5>O6};?;FUP_Bb=N9gI4#`Pqmp-R&<*YxP%nSjsY+nnjQ5!wzW zdhZdyZ(1;KBV-xPwa1L+y84X9fHoR=i!{eVNxGosgSvV&l}hjyz%qQBQ>a1c>S&%q zz!(fg_%<^W5VDWqf^riS!&oZe;Ha_a?D#gT z9D~sGu{^yzz|}37TM*hgmY4F$u{^zcP;Qg1$S}%LhjHjp_|k{bXlZsKls=B41TO-7 z$;%Yu!*+x|AIHn~4B(v>%uZM&#E$2d3lzqeo>La3TE4L8Sg zGtCpwJSOmBiJQPF382^~h@umerJy`Jfp?g<1!X%Zp9{(vLHPlc>l4T(L+C`VCu$;- zdQaq(;es+5l&pz7twKRr4a$azJguFAas-q!LZ(4bq;!k`={#1?bgsESC=aFcYMKhT z0N>{PuR-Wl!Q2gas0H&1LO0WS$%RjXvx9GQ%w&W{PU6PQox~F=1ZC|co`t^)$`_y< zn8b~_EGYG$+@8d1zQbf5>;B28>dCygG6ZEVD7lk)td|Albx^hlN~NGwfpTs#WyXHbFP+L0dI^-*r}8Xdtxg_CB`7Dk0>gDdF-&7p$TV(V?`d3S04Pb*xOvk7pT@U2 zk+leIoW?Eq6!1U`=4FI_rI?ZCBt*GqI@dR5I(po6osQ2r=XO9a^w-7g{y+{D=5-Tt|xLP*K_|&w7r?4?Fq_UP;zII!ND&BZo#*? zR4NfVDVWy*&6#&Itq8?s^7KY#3M)aGnaOqK1FmZ!{t-f7Wb)!a2Y9swGhh}R@L9ar z2F&8R6i~*^;{E1nL0JRJtDF+N8}KB)&6ZwA=*}#zz0;!@SnzFT4o7Ihqr4olALZIt zgR((Tb_&W7P|iHc(`yiv@GK@pVbf?ybnrufi|}n$xelRCSvnX-yO3zLJ5!am=gfAS}+R{S}T};2mHdz6j`Z6 z=p;7E&~~l^nxD8^trelTC%D>?fYVzr^AK9~1aF7$KEZ3`BT&A0f@a&`bAY#7hK5n3^aTd@&vyO$|U{1l;mbNDQJi5PQ5Ou-C5sO?-Ha{!>?Wr_mL zLg;D1TnqSi3uYNYM+EaKG3MQEP$WV<=W%Nl!1NZ(MF_1F%uRsXTQH9xbVe{604?+H zRvUv*|M}E53~BRundO7BdOo**3*Z+m#Lppgc|Nzo{3P;;Z*!RqKq%=+YTJhCPjX!^ zgYxE+TvrL;$rj?*5xVmv*VSnOdKbRUx`rb(VFB+s*$cR?wV-TVz`c`C0l#S>ej6dn zQ(RZfQ}BiHZPqmop$stLGp+!9vjwvRp+ndt#T0nuDW1?BPy(I?ML1EhPctbE-)4RD z5nB2*PizC=<`&F-2pw;ZU5{YI!n@1a;rw78-e!{`)uKn-JwFM}fLqv== zV~0!%SiwsxVuhBmI>yjhJi3ZUH}U8p9`}hyKk*nS9)ni!Vz5BdgDZH2IGQQW71}0G zjA68ROcIYrgxKRE{ygz`N<4DJV~Kby7msJeqewi8#ls^WFN(){k!C2Ycx8nawKm4^ zzIgmYJobyn*U0PIX!9yGmf98C<+aX`xrot6Vqthl69;P(U+f=zuT;I9Nv$RR)Lwqk z9#BhM>P(t;>ZOO>7EelJ?Hp|UDa9XKH-R31+*SOxbu*Bn9&{CNwQdKrs~?mgicS4e z-d0ozIi8L{PA!FnB{Gi0QLaCEaNdq9<|GR%19uHZN!`xP zQ!-Oe+SPiO>UQi-MzSm#zvI}wYGvs~i}8Rx@fWgTc{e3Y?tu>*}dv^3dC0ZN!HtqWd+M`^VFfX#HM}) zqcXBb$`ebpRqJ}XE9|nvu~v30-w=NmS#eBT=ZJ4CLRyaH8*5h~X>M~-$&xU;`Xe$m z)vh+G7i#Okq2hIAR*|)oUVu>)A}=`u(k2F_?<-0oIABDUv5JfO%X|9&&bg=pA@1e0 zlJ}h93=6M;D%8mDu=s{e?pdPEULU1-)^}r5wH@pG4!8AcwDmf-o9f#$f*Ft45)aF% z^{U-EPIlR?X~=Dw-P1e4;aSe?iT|vGnCw{zX^$x$yjh7wB_QRsx9v7)zuagWWKaBn zWQbrSf*YF9XpVYYpVB+l`GjwcMqOzU9)U>%-jSf|(=_On9H8Uij_F z(bxE0#*q;_^W+klq}PGow>H_QV5Er=el?ZG~Rm*J3O~57EM2 zX=4chF(I(@TdmJ48!W+KwhJn~s2zEwV=GqzLnliptYy;vU2RW1D6c+xr?FAq88jHY!Hha@r9E-K{K9UKhk8s?j3sKl_U5audk@;= zT?asErEE})`xIlPQ0rCcB9%MBUTe>+qBQ=Aa-PMrTLvUb!#8qn((~_O9mbBcO|VT= z3a-W}>hBJbi9obq zG)Z%S7V$F1g#ZaFKG5jY@iM33(A!JHDXjE5=hCU5Ky48gXs{2tfMTg?!ZrObPqYi_ ziOTKC#F$)}JwWj|jEb>Li+w#ca2`*Bj%;S{$bVfkW=3%RIJlJrDna-~P8*J*Tg%bo zD3W#@J>^5bHX#`Q7F5&&oPz09Y9}mv;jG_|7v6l6#rMIvr%4(H4&$f*=nrm|3MBgO z`##!-MAK%yT^uO-JWchA=6NSZi+pF6mo^WyRM3Wb!-IJEn|J1V!!sz(j`8nqU~Pnw zX&{J!<8z=Vg@Jvxw$i$6PHN@M92V;|R-|TXwtuuwQP9fVsYJ>wqlr!(X0f4{O9uSf zC1c$LyC?huD3O$+v)T8OpiM19bWAtsc@VtK1+_0XPj-vMX*i6a?h{q8q_?F0uBcz< zv@Tc@C*=gkmr#pJLi>rDQEo#k$7r9x8=ZO@PKjF2u_M03u2$Oz4UNl=va9>3GaTd$ zYJmxM^=>6f=Fr~MclN`=7)5PRFdf7x#$}d&l4m0CoQOF+#VBt(g=sOX;CCjkd`=Kd?o{9`qr)-I1>qZAqUlI3o}yC&>h7 zYpT^k*$O2mCBim=${|&)SJYeHEG)LD)oRKBGI}ebEg7v&4E2r(&HXmJKXPsSO56XJ z9&srH>RMH#P?MJ8OW+bXFe>(^LhtYE0?8;c#WT$4G?ry$XpqhgChtsR@=nE2 z`mM!yEb+_=tFy5L-cwL&Vrkw9Q4=D+)Teo!*rt~wf(fork`b}ZPK?GbV<~8U1ZiN! zKjc5owK+tSQbe7^E42^WRMhqK(z4~k;>{`?F6$$AyKOp-O~m%Tf4kvptt?T zB0N}|{kMJEo^AfaY!mJ3=un$ltEiJKj`;l!a_2A(mm=d+JD4cv9sFzsWkI&m?<{s> zb#{DHE!xP-Gug<#gZhF8SzGtLw#E`iVtL*vk>3a!$fBr{V=2=Z#E@lVcQov_1t5#I z(r-iU#wvs?r8N-(1>%vt$EF@vj3?xs$wtUeMyq<-&znAICW>k-GuAuMN!G#fNP_l+ zwL{$=lhffzHak3~e3!8trc>uiYMRb|$r*&8LR~G%$fvl(+MF07Q7)7G1nE{zYa*G6 zUCI+0>>*TzKkylG}uMZqX z&MXF{%R2^sl*Ho2=$D7ogxeH@-YJG&+SwP#10>uga&X_)Ht(3jwrJrWe-yZa_f?wb zuW83Vj!ON1w(qddKJupTGVt)f8`!Yp!B5_0ZkpXp5{=wqg1H1FjP3}IF!}=^Vd`NY zx&kDO4)FPU%Yek}wgHGPRhgvIKqDb*k}d&>G!%8OQk;(AX+h|YnY$LTK#?E~Lwt_t zWniF?}$;z$n{L?4Me+KYRKAm}bTe^MwCJl3@u=NKp#((UiXSADx5y(u8H}RcE~B z%KTEhu(|DyWB(Y$SiTncSs}~P)_yi2@GF~o)29A}b=5lUm(RL{)<5V>kYEv|Uc`MC=wGwYs7VlEY$3Sbl!ecZqm9Bf2N@dy`pDzpeCJ+UbST7fz z(yaeHdJmT5l4n$7e4~wD<&@YxSH1_BBObN?s8mR2*w~41@&&%4iJt=Ih zmQ*s-J^t6MEFWLqlN_RWo(Pfm3=hKM z?ZWO$z9Ub(1er#X1NHn3xo3@6v;jIou?+f=$3tMp$g=1B*eUI+iet>7ZLZwtPT>9y zuFiQ|vL9>_E%_B7(UL#+AzIytmi(I!twdW*;adI*B>KoUAkn%je5e{ocvth`vHcD4 zP0~U)yfNWuS>a&Eay2d>O57y%K`{uyOrVE2cL|VK7UTnckFQB8!mn5s><1EwY{%%= zp2s*3Bnm}DaVfV_eK9~wXtp-`&>s)dF1bm{_BEqtfkXq?R)u^qRMzR7xs0;HvgXdUE`i^lk#kG73yJ1UNiXI8PA=?j8bnLiIC z%DWbbMnq|zmUN=s{pwXXceyV0Tcvok#a?U+jX FDu2Oyuh+S>qDypw0@ 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 delta 59092 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 diff --git a/vendor/stb/lib/stb_vorbis.lib b/vendor/stb/lib/stb_vorbis.lib index bf47eda261e2114f2de6289b4dbc39e577f9e0c1..e879131c5def05dd5561253aff558f1fb3e23524 100644 GIT binary patch literal 153860 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Ð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

*z1_Q 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 B}tkm4Fj-6vi}zAYaw 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‰G7VsXnT;U4MagByh=dXbGD}0YezA)hbU--*C^rj`Ha%}Or3nb zZne2ppSrRX^7lleLD?L>-{m=RG>wjn^Wgpb=i>!mIM`>)&AN9ipHSUKOD1dDM~b zM-+~7UOy29jqs`zUgKuBzLTlO9rbAWe9#E5D&bYxcl~i=omU)D&~J ziGoIWRXZ=ee_c6s;4Y?y5e1F#su5n#wV1w~sR=|uBfM&b*W@lACo%N^QP2plI^k9L z*0s%tNN`?Lh=N9V-5|W~*!J`3O#Oo>XoS~|p!Bg)J@I{fW7hBK&g%`Lpb=g-39s6> z+plG66H(9zubV;H^{_?fz8jd@MHDo`>lWd){rQzknQC;Q9u4&q+*%{NrU6TV6g0x?R^hdMV`4T_0ivK0Ubl&U zZQS?!6-cyYTAs=}lXhnn@Hi!s`xDc3)2HTfCpCCy0VZcuf~xYYxPP%#D|b zf<}1VDZJj5G+1UDZHAs zT{4fU7DPcKyzUZS54EqI%v4vRpb=iPgx9Y(@14n1I#JLFue(9%9Z4TknzVgw9aGm3 z1!M|gGm*Y`IuRZA2!!s}j8`W!%e#jo4ZmZ=#;K_k5G6J9AtI}By&38J78UiX8t z>&E9xW<0~x%S1sVydDrdek&qCq3Po)BKk6COOwR2QP45nfLUub%O<9%8B= zQP2pl1;Xp+U-G_UY8X+_2(N|0>(c5ob~05>6g0wX5h!~dpk`L>IHsl(1}N_aip zeo0rR<`M;s@OoPGYv|VgO_)-bi?Bf>yq*zW&E9`|JX0SK1})=|1z{WryBZr#{H z6g0wXv7_{g-D26hO_(}J6g0wX38;43NNtz5Z_%>Cc{S}~qRNeEG{S2cD0|-fWmVU%9h}!)L_s6G zmJ6?qeR~uz^%POi2(J~O?0Wd^=4+CeT0;~x!fU1Q8uZw0KBm4P3L4?{JSe+v^xin~ z2c`}Z1}L3q9O;=R+EYSGnm0W zMtH3TrH@~Fdt`rZ^<~bhgeYi)*Gs~y-#?2FF*S`SXoT0xpzL{6!L+RnnVLrwG{Wl@ z;WhTP$(@*bohWF8*Q=oHcr8j#OlRr~qM#98uL-Zp!bX#sIzkjQ!s~TM=^WOLns!xh zm&3N*bj*jFu*vU7z2PXmZs@;3V5$#M&vi zH<&6V3L4?{7AU(fH!VN$`BR+N4MagByw(aYeQlYk2Z(}3c>ND3d)~XK%Sm&XdX^|? zgx5OZ_24(FbD3I86g0x?U!d&VSdp8wgQ@LAK_k507GC$>aHuO&2Z(}3c)bIvof<3k z#5d;I#Y<0hIcyfMLTZCXc)csU#=N`lXQsLl1}50pI@eR|u!HZzq=6g0wXz3?jN z^xAf&%87zTc)bs*nQFbBy|5= z&u}?hPZTu5YlHAw_rf(hnEHt*XoS~Cp!6|CZ{x?US$n$kYMfxA&e0yuZ_-2=WzdD3SMVwI8o3DuTO;6&JLR%WNJE5&fL=PQ(qAUjj!v-ni}e`Z!;+T6t)ey|4&XdPoeR3t>)kR`V18Pv4O8& z`jnT|Z(I=9f+($ND5x!V9HVW~+yjhEI)>Kjn>v4n49(v)YJI!ct*Na|ZqD&5#VY}son zQ&W1GsMbj8J5Y4u?z^k+^g5E4?&bh>d zwMJ4u32N=>Gp=IlOQN(!QoBI)Bd>e+53XkFkxNZjYb3QBl+ED>d%pdasUepcN^2yw z2b7(?_pkW(?@YZ&l-5Y;p^>xRP)@<-oCU0X^o_Q0Y#I**Ws>Ji(uwB-rpLdyODUYb13Ll=UiF*Da2z2}Eg)qz-|yUVlA2{|=_^AWCb@xX-1C z&aJHHFzV4~7kWGNZI5>?RfRZiXgH>UE4(i%xM6x5Gr1|Mdsjwr2Z=u^L& zTw7ODTx43UBaf)^Wc4$;iGl9^p8{cGlae;!sQMys0-6j%F_t)iy5Ox^FWvf7`Vn4DZ#SusxiYJ8w3SYB0DTob4nt$tYE z)L5!ZYKj9zBLlU;k!9+>o~k`nsyKkA7mhA299t4BEvr*M*j`gRGCK?E%Y<`nIBxvrZ5E9T8n&t&6OG@;Q4Tlw$l$I5H6ya74RdqF^aZ(z> zP>xHggXJpI9)glG74$5zsB)}ObZAScNc|piW%b0+0<Ip&%@|cXS`D0?39&V5mR1ziglhCCnT)F6 zkq!zAF2d|mChC{U%Zh{J)SeR3k}z3#k)5HaK2{w<7_F9Lw#3!~p|3nRwm2|S-Iif& zAXr@;RO4G*TUQmJTQ!&$xRZlgiK_jjwLbH-PX9`Bu}}SMz1qL9 z%lXhprK+pY3xO|KR1{FVj+$2bcBXZ;#R0uYjIXR#LtrDp!a}uQSF4(e0;B6nO3H)k z=Cmr)sunHLcU35@C@iZ}i;Es)eftQD>K7qY*z)32zXd-eT2-kU>YAxi7zo{^3xid) zYK>8gS*@Bkdg7}oY?ii)$^ex{7CN0?N!0*O99e8;KP|4xe}Y2U@2M~us-{$)Pm@;t;b}f%9UNiYYKy9!D`eNQG~rPEUHo#RzYoXRYb6; zn0Ft&9;>_A>Sh#`7OI@+Jo<`M`_*x!Lfw?OxTdtIPOacLsQ74wqNuO5yht%M$|NbE z?;Q{yP$OL>!|ITtdJwIkCU!xftf;5DAAvoNXgi(D0L>7ZXVfY^IZA_NJ{b);4tkc@ zV2Q%jl5N&Ns-mh+?Sv(z)ity*`PAWc{OC$GWvNz`wiMHb5$Azr%=HMQO z--Y*xM*=t~gdE=^(FjFkCGt!lvWl?s$OZ?)PX0YAiYhhpCn0pF zs);H#Q>mU}Q*+XPQgc1U9&`R!Z5As+bg`*f?Do;cCL8q>dyITUn(2L6eTL6UBdf&` z6>pBsTe-;EA{3_A;)zHXrY52yn=-zn?lNja zxOyH|yNOY49#_^$?o~pNxb{wR86%;d0QP#VzAjJNh;XFbL+Uz*$wSqK=+tK==F+ee zimUzPEn{qKZamBlq}L%6Q7AAOg$7elXhI{Vp6+^L3QcH)8Y4cIpa#hp2_rsn;EyZ_ zi>0tVi={COls=k-eYO$eWa>$XsWJ7$)|h(qsYi4#Q%`J-&GfPB(TA|;UeS__4}YTN z*A#lAcB+P%+QlxSHCFFYVEU*JprZYj@F?(Z5f9 zALUC|S!6mKZ#ygtO|qgC8Zsdk8KuyWZUntNqZAs_jh+`7rBLQI;#&whKjIJ>#Lt4Z0gpZtB9~s zM}&>Kr?)yHY}CEH)e&K%?(MCP2pe@DZ*@f2s1x+nLyvAo#z`NMTS|FEob>u)y;uDa zankGS+FtsIxSZJfEJuCeMowoNG*!D@%Z5$MBf>`Qb|Kr+3{EVWaNlt&RvAb#HHVMA)eNc&j7AMy;lhJ5+^sGcqoRGE_?yn2?l3{qB^U z1JPx&I<=(ISFI!;5+^{vg~mtl{8cPMyh=sn$f#Z=Mkwwb;;Vjf_P{Ev9CBeZ7s0J&Onv-+&{%j5(qC(ky)# zWtSLx{n~|1XY`vjPrXNhOr?`6uozH1m(Pb{VBkG{BMJY#9ip`w0TQ?I_*RNs2*rBz?| zroW^}P7b8`0|}`){`}nR)RgqBY=3fGN=l7>sMQZ6^+P~EjMER5`k`7sprBMggE+an zep;v>^gq9kYEH}drx#=m=wFbLi<*t1kJ0tZ*Z+g(ieX!<3ySmuyz#O^zeFh-0B;nS z2K3Oy$#MPi#Q%uKn@~uzQnUPdsp)wG(z4UhtTL@&m*lwq19W7p0sEUetwS!Nc$K7| zCK^>p_4)q(dHu68Q}Z%W`y>Wb1CNcTrTeq`Wu){=O-%zI)I9Q!XXrUvjF%V*?tpFk zMANFUw%0E^`Tn%5l-&L)=^38cp+uym8VgD}qNpFkih)bh3cT#6pQRfhBvWdB6lCON zrsZXt`C&3{GwspZ|K0>r?Q_$%U%o##CA}a=?Gwnr|IHN?W;UiW=GS=AP_;UwjrT5Rw&We^1-p#N}AqBh;@v4V> znSrx;FxGYjLKMjpgOZxz&r8ow?Vp)jfF>lzncXPb46D*K_H(RyJO-lHv|N97|FoRU zj675tb-{_|!V{9`0r#30#^}p$=)_CU@@MCyXY?<~GJDVey^oaIOtWUj(f^44m;31U zB6V!c$xTm7&riv>1D2(8Z-$l{n3kbKX4)m;XZLA zi3bdv8P)FEFKRLNU`*dSt;6nz2MjLe79@NiK?kv?W7J1$EPPpTSyC+@P>_?6lb;cF z_vV>ZuB*btMt$f5H;AV=2$NLr405aXwB;CSiCQ&h34KO2wcPe}e|BDGenwiZSv8OnUVqK_ z{bzOSLHciYz_nd15(Cl;GII)2%o$r)5|LOm9djLdaP7i4y7`R-B_0h|jdup>Se~Dk zk)6>m+a$+h=3}a1=SE`j!0q74i8+CGfI!=#9`$rXTqDx;PM)1LpdiJ(P5A%U2$u|6 z=tEB_WA7wrK9(wU9g_yj9J-Dqh(7eo@@J)H738JU68ryNJ4Q^6pBYEILSo>}J2%>c z)_U#+5hI?H<5zD0a@A6linSKo zN0un9+gv=U5Hb6@FjB{V$7uh8aYA{ypK3~?{}bu|1o}T-Rj6f2C9*%^uboVGFR4Vn bCRuoI!(Wrkq|~+~K0f?)n9LT3|L^->1DOFM diff --git a/vendor/stb/src/stb_truetype.c b/vendor/stb/src/stb_truetype.c index 05c23f583..ed2415376 100644 --- a/vendor/stb/src/stb_truetype.c +++ b/vendor/stb/src/stb_truetype.c @@ -1,2 +1,4 @@ +#include "stb_rect_pack.h" + #define STB_TRUETYPE_IMPLEMENTATION #include "stb_truetype.h" \ No newline at end of file From f8b56ccd88178a54cae8769d438fbb51b56c0469 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 18 Aug 2025 15:51:11 +0100 Subject: [PATCH 072/105] Update stb_truetype.c again --- vendor/stb/lib/stb_image.lib | Bin 288820 -> 288820 bytes vendor/stb/lib/stb_image_resize.lib | Bin 99126 -> 99126 bytes vendor/stb/lib/stb_image_write.lib | Bin 81326 -> 81326 bytes vendor/stb/lib/stb_rect_pack.lib | Bin 15174 -> 15174 bytes vendor/stb/lib/stb_sprintf.lib | Bin 24726 -> 24726 bytes vendor/stb/lib/stb_truetype.lib | Bin 168724 -> 181362 bytes vendor/stb/lib/stb_vorbis.lib | Bin 153860 -> 153860 bytes vendor/stb/src/stb_truetype.c | 2 ++ 8 files changed, 2 insertions(+) diff --git a/vendor/stb/lib/stb_image.lib b/vendor/stb/lib/stb_image.lib index bed913f617349e638a341ea8552f84b8d6b6d426..b36fef6dc2421dd86c53f26486a51f0040d900d7 100644 GIT binary patch delta 60 zcmdmTL2%0j!3lCK7G|af8bCLm_sZe+v4 Gqyqp(kP#*T delta 60 zcmdmTL2%0j!3lCK#-Lja99!7ItjSCQJ`hHbfEv>&+vX~P?NtJdCb|Ie CFAwPe delta 57 zcmZ4Yn`PZ^mI-n!#-Lja99!7ItjSCQJ`hHbfEp8{R&$lW_9_8J6I}r4 Cjt><8 diff --git a/vendor/stb/lib/stb_rect_pack.lib b/vendor/stb/lib/stb_rect_pack.lib index 862fc292a4b43a328b906fd0dc86290914332cfd..47344b3662163b6a457664a1a0641cd75c3e7f62 100644 GIT binary patch delta 51 xcmX?BcC2iI9E*jSsli620v0f1^E8$S2y5~u4ll6KWCu<)rc<_?GdS-V0sx%94~PH& delta 51 xcmX?BcC2iI9E-83h3Q760v0f1^E8$S2y5~u4lj_9$z%skH6{kF%^95c3;~x~4zd6M diff --git a/vendor/stb/lib/stb_sprintf.lib b/vendor/stb/lib/stb_sprintf.lib index 1d31c0de0148060c5b493c73b504b819a2308f27..892e56c42196a3984b55144a8d97da68db9d0516 100644 GIT binary patch delta 44 vcmbPska5~U#tCvP7G|af8;l delta 44 ucmbPska5~U#tCvP#-UM)tDHxHrFvr!~y^@4-88H diff --git a/vendor/stb/lib/stb_truetype.lib b/vendor/stb/lib/stb_truetype.lib index f1ec8e818a33bd0f8a5257f58a0c3da146f44e5b..f86ddcc5e9fa110a5bbafc99924ab9c33d4f6f19 100644 GIT binary patch delta 50025 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 Ux6Gjx&gzu>na#@x_4@Sx1N@PJqyPW_ diff --git a/vendor/stb/lib/stb_vorbis.lib b/vendor/stb/lib/stb_vorbis.lib index e879131c5def05dd5561253aff558f1fb3e23524..6d6bccb44d2e9ee4dc2ef7cb95061cb6019a0d2d 100644 GIT binary patch delta 52 zcmZqK#M!cmbAlX;g_)_rMx`lyV8-TMd@>N$duyYD^4T%}lcGOtOsInPi!mYygVB B4GRDO diff --git a/vendor/stb/src/stb_truetype.c b/vendor/stb/src/stb_truetype.c index ed2415376..974a0bdce 100644 --- a/vendor/stb/src/stb_truetype.c +++ b/vendor/stb/src/stb_truetype.c @@ -1,3 +1,5 @@ +#define STBRP_STATIC +#define STB_RECT_PACK_IMPLEMENTATION #include "stb_rect_pack.h" #define STB_TRUETYPE_IMPLEMENTATION From 409e3975669eb0d96655c84227d97512db80e72b Mon Sep 17 00:00:00 2001 From: gingerBill Date: Mon, 18 Aug 2025 21:47:09 +0100 Subject: [PATCH 073/105] Fix bug with `$fn: proc()` when passed with a global variable --- src/check_expr.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 7020b4f4b..862dd9278 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -6472,6 +6472,14 @@ gb_internal CallArgumentError check_call_arguments_internal(CheckerContext *c, A } } + if (e && e->kind == Entity_Constant && is_type_proc(e->type)) { + if (o->mode != Addressing_Constant) { + if (show_error) { + error(o->expr, "Expected a constant procedure value for the argument '%.*s'", LIT(e->token.string)); + } + err = CallArgumentError_NoneConstantParameter; + } + } if (!err && is_type_any(param_type)) { add_type_info_type(c, o->type); From 8bab146b2d9d151297391bd8d3a726e23eba1f1c Mon Sep 17 00:00:00 2001 From: Brad Lewis <22850972+BradLewis@users.noreply.github.com> Date: Tue, 19 Aug 2025 07:20:31 -0400 Subject: [PATCH 074/105] Check for EOF when scanning file tags --- core/odin/tokenizer/tokenizer.odin | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/odin/tokenizer/tokenizer.odin b/core/odin/tokenizer/tokenizer.odin index d4da82c56..a9d367a4d 100644 --- a/core/odin/tokenizer/tokenizer.odin +++ b/core/odin/tokenizer/tokenizer.odin @@ -209,14 +209,14 @@ scan_comment :: proc(t: ^Tokenizer) -> string { scan_file_tag :: proc(t: ^Tokenizer) -> string { offset := t.offset - 1 - for t.ch != '\n' { + for t.ch != '\n' && t.ch != utf8.RUNE_EOF { if t.ch == '/' { next := peek_byte(t, 0) if next == '/' || next == '*' { break } - } + } advance_rune(t) } From 24852385929dd48205e2525d4b116d2c27f0b36a Mon Sep 17 00:00:00 2001 From: Damian Tarnawski Date: Wed, 20 Aug 2025 20:18:19 +0200 Subject: [PATCH 075/105] Split SDL_ttf bindings to group with and without require_results --- vendor/sdl3/ttf/sdl3_ttf.odin | 96 ++++++++++++++++++++--------------- 1 file changed, 55 insertions(+), 41 deletions(-) diff --git a/vendor/sdl3/ttf/sdl3_ttf.odin b/vendor/sdl3/ttf/sdl3_ttf.odin index 9f6a9ba4a..ada1de833 100644 --- a/vendor/sdl3/ttf/sdl3_ttf.odin +++ b/vendor/sdl3/ttf/sdl3_ttf.odin @@ -60,7 +60,7 @@ FontStyle :: enum u32 { FontStyleFlags :: distinct bit_set[FontStyle; u32] // NOTE: This is called TTF_HintingFlags but its not a bit_set so -// the "flags" doesnt really make sense, its just the hinting. +// the "flags" doesn't really make sense, its just the hinting. Hinting :: enum c.int { INVALID = -1, NORMAL, @@ -125,11 +125,8 @@ SubString :: struct { @(default_calling_convention="c", link_prefix="TTF_", require_results) foreign lib { - Version :: proc() -> c.int --- - GetFreeTypeVersion :: proc(major, minor, patch: ^c.int) --- - GetHarfBuzzVersion :: proc(major, minor, patch: ^c.int) --- - - Init :: proc() -> bool --- + Version :: proc() -> c.int --- + WasInit :: proc() -> c.int --- OpenFont :: proc(file: cstring, ptsize: f32) -> ^Font --- OpenFontIO :: proc(src: ^SDL.IOStream, closeio: bool, ptsize: f32) -> ^Font --- @@ -140,14 +137,7 @@ foreign lib { GetFontProperties :: proc(font: ^Font) -> SDL.PropertiesID --- GetFontGeneration :: proc(font: ^Font) -> u32 --- - AddFallbackFont :: proc(font: ^Font, fallback: ^Font) -> bool --- - RemoveFallbackFont :: proc(font: ^Font, fallback: ^Font) --- - ClearFallbackFonts :: proc(font: ^Font) --- - - SetFontSize :: proc(font: ^Font, ptsize: f32) -> bool --- - SetFontSizeDPI :: proc(font: ^Font, ptsize: f32, hdpi: c.int, vdpi: c.int) -> bool --- - GetFontSize :: proc(font: ^Font) -> f32 --- - GetFontDPI :: proc(font: ^Font, hdpi: ^c.int, vdpi: ^c.int) -> bool --- + GetFontSize :: proc(font: ^Font) -> f32 --- SetFontStyle :: proc(font: ^Font, style: FontStyleFlags) --- GetFontStyle :: proc(font: ^Font) -> FontStyleFlags --- @@ -184,31 +174,20 @@ foreign lib { GetFontFamilyName :: proc(font: ^Font) -> cstring --- GetFontStyleName :: proc(font: ^Font) -> cstring --- - SetFontDirection :: proc(font: ^Font, direction: Direction) -> bool --- GetFontDirection :: proc(font: ^Font) -> Direction --- StringToTag :: proc(string: cstring) -> u32 --- - TagToString :: proc(tag: u32, string: [^]c.char, size: c.size_t) --- - SetFontScript :: proc(font: ^Font, script: u32) -> bool --- GetFontScript :: proc(font: ^Font) -> u32 --- - SetFontLanguage :: proc(font: ^Font, language_bcp47: cstring) -> bool --- - GetGlyphScript :: proc(ch: u32) -> u32 --- FontHasGlyph :: proc(font: ^Font, ch: u32) -> bool --- GetGlyphImage :: proc(font: ^Font, ch: u32, image_type: ^ImageType) -> ^SDL.Surface --- GetGlyphImageForIndex :: proc(font: ^Font, glyph_index: u32, image_type: ^ImageType) -> ^SDL.Surface --- - GetGlyphMetrics :: proc(font: ^Font, ch: u32, minx, maxx, miny, maxy, advance: ^c.int) -> bool --- - GetGlyphKerning :: proc(font: ^Font, previous_ch: u32, ch: u32, kerning: ^c.int) -> bool --- - - GetStringSize :: proc(font: ^Font, text: cstring, length: c.size_t, w, h: ^c.int) -> bool --- - GetStringSizeWrapped :: proc(font: ^Font, text: cstring, length: c.size_t, wrap_width: c.int, w, h: ^c.int) -> bool --- - MeasureString :: proc(font: ^Font, text: cstring, length: c.size_t, max_width: c.int, measured_width: ^c.int, measured_length: ^c.size_t) -> bool --- RenderText_Solid :: proc(font: ^Font, text: cstring, length: c.size_t, fg: SDL.Color) -> ^SDL.Surface --- RenderText_Solid_Wrapped :: proc(font: ^Font, text: cstring, length: c.size_t, fg: SDL.Color, wrap_Length: c.int) -> ^SDL.Surface --- - RenderGylph_Solid :: proc(font: ^Font, ch: u32, fg: SDL.Color) -> ^SDL.Surface --- + RenderGlyph_Solid :: proc(font: ^Font, ch: u32, fg: SDL.Color) -> ^SDL.Surface --- RenderText_Shaded :: proc(font: ^Font, text: cstring, length: c.size_t, fg, bg: SDL.Color) -> ^SDL.Surface --- RenderText_Shaded_Wrapped :: proc(font: ^Font, text: cstring, length: c.size_t, fg, bg: SDL.Color, wrap_width: c.int) -> ^SDL.Surface --- RenderGlyph_Shaded :: proc(font: ^Font, ch: u32, fg, bg: SDL.Color) -> ^SDL.Surface --- @@ -219,32 +198,70 @@ foreign lib { RenderText_LCD_Wrapped :: proc(font: ^Font, text: cstring, length: c.size_t, fg, bg: SDL.Color, wrap_width: c.int) -> ^SDL.Surface --- RenderGlyph_LCD :: proc(font: ^Font, ch: u32, fg, bg: SDL.Color) -> ^SDL.Surface --- - CreateSurfaceTextEngine :: proc() -> ^TextEngine --- - DrawSurfaceText :: proc(text: ^Text, x, y: c.int, surface: ^SDL.Surface) -> bool --- - DestroySurfaceTextEngine :: proc(engine: ^TextEngine) --- + CreateSurfaceTextEngine :: proc() -> ^TextEngine --- CreateRendererTextEngine :: proc(renderer: ^SDL.Renderer) -> ^TextEngine --- CreateRendererTextEngineWithProperties :: proc(props: SDL.PropertiesID) -> ^TextEngine --- - DrawRendererText :: proc(text: ^Text, x, y: f32) -> bool --- - DestroyRendererTextEngine :: proc(engine: ^TextEngine) --- CreateGPUTextEngine :: proc(device: ^SDL.GPUDevice) -> ^TextEngine --- CreateGPUTextEngineWithProperties :: proc(props: SDL.PropertiesID) -> ^TextEngine --- GetGPUTextDrawData :: proc(text: ^Text) -> ^GPUAtlasDrawSequence --- - DestroyGPUTextEngine :: proc(engine: ^TextEngine) --- SetGPUTextEngineWinding :: proc(engine: ^TextEngine, winding: GPUTextEngineWinding) --- GetGPUTextEngineWinding :: proc(#by_ptr engine: TextEngine) -> GPUTextEngineWinding --- - CreateText :: proc(engine: ^TextEngine, font: ^Font, text: cstring, length: c.size_t) -> ^Text --- - GetTextProperties :: proc(text: ^Text) -> SDL.PropertiesID --- + CreateText :: proc(engine: ^TextEngine, font: ^Font, text: cstring, length: c.size_t) -> ^Text --- + GetTextProperties :: proc(text: ^Text) -> SDL.PropertiesID --- + GetTextEngine :: proc(text: ^Text) -> ^TextEngine --- + GetTextFont :: proc(text: ^Text) -> ^Font --- + GetTextDirection :: proc(text: ^Text) -> Direction --- + GetTextScript :: proc(text: ^Text) -> u32 --- + TextWrapWhitespaceVisible :: proc(text: ^Text) -> bool --- + + GetTextSubStringsForRange :: proc(text: ^Text, offset, length: c.int, count: ^c.int) -> [^]^SubString --- +} + +@(default_calling_convention="c", link_prefix="TTF_") +foreign lib { + GetFreeTypeVersion :: proc(major, minor, patch: ^c.int) --- + GetHarfBuzzVersion :: proc(major, minor, patch: ^c.int) --- + + Init :: proc() -> bool --- + + AddFallbackFont :: proc(font: ^Font, fallback: ^Font) -> bool --- + RemoveFallbackFont :: proc(font: ^Font, fallback: ^Font) --- + ClearFallbackFonts :: proc(font: ^Font) --- + + SetFontSize :: proc(font: ^Font, ptsize: f32) -> bool --- + SetFontSizeDPI :: proc(font: ^Font, ptsize: f32, hdpi: c.int, vdpi: c.int) -> bool --- + GetFontDPI :: proc(font: ^Font, hdpi: ^c.int, vdpi: ^c.int) -> bool --- + + SetFontDirection :: proc(font: ^Font, direction: Direction) -> bool --- + + TagToString :: proc(tag: u32, string: [^]c.char, size: c.size_t) --- + + SetFontScript :: proc(font: ^Font, script: u32) -> bool --- + + SetFontLanguage :: proc(font: ^Font, language_bcp47: cstring) -> bool --- + + GetGlyphMetrics :: proc(font: ^Font, ch: u32, minx, maxx, miny, maxy, advance: ^c.int) -> bool --- + GetGlyphKerning :: proc(font: ^Font, previous_ch: u32, ch: u32, kerning: ^c.int) -> bool --- + + GetStringSize :: proc(font: ^Font, text: cstring, length: c.size_t, w, h: ^c.int) -> bool --- + GetStringSizeWrapped :: proc(font: ^Font, text: cstring, length: c.size_t, wrap_width: c.int, w, h: ^c.int) -> bool --- + MeasureString :: proc(font: ^Font, text: cstring, length: c.size_t, max_width: c.int, measured_width: ^c.int, measured_length: ^c.size_t) -> bool --- + + DrawSurfaceText :: proc(text: ^Text, x, y: c.int, surface: ^SDL.Surface) -> bool --- + DestroySurfaceTextEngine :: proc(engine: ^TextEngine) --- + + DrawRendererText :: proc(text: ^Text, x, y: f32) -> bool --- + DestroyRendererTextEngine :: proc(engine: ^TextEngine) --- + + DestroyGPUTextEngine :: proc(engine: ^TextEngine) --- + SetTextEngine :: proc(text: ^Text, engine: ^TextEngine) -> bool --- - GetTextEngine :: proc(text: ^Text) -> ^TextEngine --- SetTextFont :: proc(text: ^Text, font: ^Font) -> bool --- - GetTextFont :: proc(text: ^Text) -> ^Font --- SetTextDirection :: proc(text: ^Text, direction: Direction) -> bool --- - GetTextDirection :: proc(text: ^Text) -> Direction --- SetTextScript :: proc(text: ^Text, script: u32) -> bool --- - GetTextScript :: proc(text: ^Text) -> u32 --- SetTextColor :: proc(text: ^Text, r, g, b, a: u8) -> bool --- SetTextColorFloat :: proc(text: ^Text, r, g, b, a: f32) -> bool --- GetTextColor :: proc(text: ^Text, r, g, b, a: ^u8) -> bool --- @@ -254,7 +271,6 @@ foreign lib { SetTextWrapWidth :: proc(text: ^Text, wrap_width: c.int) -> bool --- GetTextWrapWidth :: proc(text: ^Text, wrap_width: ^c.int) -> bool --- SetTextWrapWhitespaceVisible :: proc(text: ^Text, visible: bool) -> bool --- - TextWrapWhitespaceVisible :: proc(text: ^Text) -> bool --- SetTextString :: proc(text: ^Text, string: cstring, length: c.size_t) -> bool --- InsertTextString :: proc(text: ^Text, offset: c.int, string: cstring, length: c.size_t) -> bool --- @@ -265,7 +281,6 @@ foreign lib { GetTextSubString :: proc(text: ^Text, offset: c.int, substring: ^SubString) -> bool --- GetTextSubStringForLine :: proc(text: ^Text, line: c.int, substring: ^SubString) -> bool --- - GetTextSubStringsForRange :: proc(text: ^Text, offset, length: c.int, count: ^c.int) -> [^]^SubString --- GetTextSubStringForPoint :: proc(text: ^Text, x, y: c.int, substring: ^SubString) -> bool --- GetPreviousTextSubString :: proc(text: ^Text, #by_ptr substring: SubString, previous: ^SubString) -> bool --- GetNextTextSubString :: proc(text: ^Text, #by_ptr substring: SubString, next: ^SubString) -> bool --- @@ -274,5 +289,4 @@ foreign lib { DestroyText :: proc(text: ^Text) --- CloseFont :: proc(font: ^Font) --- Quit :: proc() --- - WasInit :: proc() -> c.int --- } From f90d7029b405dcdade44d2cf1824586a4631c3a6 Mon Sep 17 00:00:00 2001 From: blob1807 <12388588+blob1807@users.noreply.github.com> Date: Thu, 21 Aug 2025 05:19:16 +1000 Subject: [PATCH 076/105] Fix stride in `memory_equal/compare_zero` giving false positves The previous stride of 8 assumed `uintptr` size is 8 which isn't the case on 32bit & wasm64p32. Skipping every other set of 4 bytes --- base/runtime/internal.odin | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/base/runtime/internal.odin b/base/runtime/internal.odin index 4f9509b23..77fe09ca8 100644 --- a/base/runtime/internal.odin +++ b/base/runtime/internal.odin @@ -268,8 +268,8 @@ memory_equal :: proc "contextless" (x, y: rawptr, n: int) -> bool { } } - m = (n-i) / 8 * 8 - for /**/; i < m; i += 8 { + m = (n-i) / size_of(uintptr) * size_of(uintptr) + for /**/; i < m; i += size_of(uintptr) { if intrinsics.unaligned_load(cast(^uintptr)&a[i]) != intrinsics.unaligned_load(cast(^uintptr)&b[i]) { return false } @@ -389,8 +389,8 @@ memory_compare_zero :: proc "contextless" (a: rawptr, n: int) -> int #no_bounds_ } } - m = (n-i) / 8 * 8 - for /**/; i < m; i += 8 { + m = (n-i) / size_of(uintptr) * size_of(uintptr) + for /**/; i < m; i += size_of(uintptr) { if intrinsics.unaligned_load(cast(^uintptr)&bytes[i]) != 0 { return 1 } From d5b1fc48fbc5f853e8995ca520417a69fbad701a Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 21 Aug 2025 17:14:33 +0100 Subject: [PATCH 077/105] Add `@(raddbg_type_view=)` If no string parameter is provided, then one will be generated from the struct field tags. The attribute must be applied if the automatic struct field tag approach is to be used. --- src/check_decl.cpp | 7 ++ src/checker.cpp | 170 +++++++++++++++++++++++++++++++++++++++++++ src/checker.hpp | 11 +++ src/llvm_backend.cpp | 22 ++++++ 4 files changed, 210 insertions(+) diff --git a/src/check_decl.cpp b/src/check_decl.cpp index b2522f24a..7dd9db105 100644 --- a/src/check_decl.cpp +++ b/src/check_decl.cpp @@ -602,6 +602,13 @@ gb_internal void check_type_decl(CheckerContext *ctx, Entity *e, Ast *init_expr, } else if (ac.objc_is_implementation) { error(e->token, "@(objc_implement) may only be applied when the @(objc_class) attribute is also applied"); } + + if (ac.raddbg_type_view) { + RaddbgTypeView type_view = {}; + type_view.type = e->type; + type_view.view = ac.raddbg_type_view_string; + mpsc_enqueue(&ctx->info->raddbg_type_views_queue, type_view); + } } diff --git a/src/checker.cpp b/src/checker.cpp index 44e63b750..c6dd1643a 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -1451,6 +1451,9 @@ gb_internal void init_checker_info(CheckerInfo *i) { mpsc_init(&i->foreign_decls_to_check, a); // 1<<10); mpsc_init(&i->intrinsics_entry_point_usage, a); // 1<<10); // just waste some memory here, even if it probably never used + mpsc_init(&i->raddbg_type_views_queue, a); + array_init(&i->raddbg_type_views, a); + string_map_init(&i->load_directory_cache); map_init(&i->load_directory_map); } @@ -1479,6 +1482,9 @@ gb_internal void destroy_checker_info(CheckerInfo *i) { mpsc_destroy(&i->foreign_imports_to_check_fullpaths); mpsc_destroy(&i->foreign_decls_to_check); + mpsc_destroy(&i->raddbg_type_views_queue); + array_free(&i->raddbg_type_views); + map_destroy(&i->objc_msgSend_types); string_set_destroy(&i->obcj_class_name_set); mpsc_destroy(&i->objc_class_implementations); @@ -4066,6 +4072,21 @@ gb_internal DECL_ATTRIBUTE_PROC(type_decl_attribute) { return true; } + } else if (name == "raddbg_type_view") { + ExactValue ev = check_decl_attribute_value(c, value); + if (ev.kind == ExactValue_Invalid) { + ac->raddbg_type_view = true; + } else if (ev.kind == ExactValue_String) { + ac->raddbg_type_view = true; + ac->raddbg_type_view_string = ev.value_string; + + if (ev.value_string.len == 0) { + error(elem, "Expected a non-empty string for '%.*s'", LIT(name)); + } + } else { + error(elem, "Expected a string or no value for '%.*s'", LIT(name)); + } + return true; } return false; } @@ -7037,6 +7058,155 @@ gb_internal void check_parsed_files(Checker *c) { } } + TIME_SECTION("collate type info stuff"); + { + auto const struct_tag_lookup = [](String tag, char const *key_c, String *value_) -> bool { + String t = tag; + String key = make_string_c(key_c); + while (t.len != 0) { + isize i = 0; + while (i < t.len && t[i] == ' ') { // Skip whitespace + i += 1; + } + t.text += i; + t.len -= i; + if (t.len == 0) { + break; + } + + i = 0; + + while (i < t.len) { + u8 c = t[i]; + if (c == ':' || c == '"') { + break; + } else if ((0 <= c && c < ' ') || (0x7f <= c && c <= 0x9f)) { + // break if control character is found + break; + } + i += 1; + } + + if (i == 0) { + break; + } + if (i+1 >= t.len) { + break; + } + if (t[i] != ':' || t[i+1] != '"') { + break; + } + String name = {t.text, i}; + t = {t.text+i+1, t.len-(i+1)}; + + i = 1; + while (i < t.len && t[i] != '"') { // find closing quote + if (t[i] == '\\') { + i += 1; // Skip escaped characters + } + i += 1; + } + if (i >= t.len) { + break; + } + + String value = {t.text, i+1}; + t = {t.text+i+1, t.len-(i+1)}; + + if (key == name) { + value = {value.text+1, i-1}; + if (value_) *value_ = value; + return true; + } + } + return false; + }; + + for (RaddbgTypeView type_view; mpsc_dequeue(&c->info.raddbg_type_views_queue, &type_view); /**/) { + + Type *type = type_view.type; + if (type == nullptr || type == t_invalid) { + continue; + } + String view = type_view.view; + if (view.len == 0) { + // NOTE(bill): Generate one automatically from the struct field tags if they exist + // If it cannot be generated, it'll be ignored/err + + Type *bt = base_type(type); + if (is_type_struct(type)) { + GB_ASSERT(bt->kind == Type_Struct); + if (bt->Struct.tags != nullptr) { + bool found_any = false; + + for (isize i = 0; i < bt->Struct.fields.count; i++) { + String tag = bt->Struct.tags[i]; + String value = {}; + if (struct_tag_lookup(tag, "raddbg", &value)) { + found_any = true; + } else if (struct_tag_lookup(tag, "fmt", &value)) { + found_any = true; + } + } + + if (!found_any) { + goto raddbg_type_view_end; + } + + gbString s = gb_string_make(heap_allocator(), ""); + + s = gb_string_appendc(s, "rows($"); + + for (isize i = 0; i < bt->Struct.fields.count; i++) { + Entity *field = bt->Struct.fields[i]; + GB_ASSERT(field != nullptr); + String name = field->token.string; + + s = gb_string_appendc(s, ", "); + + bool custom_rule = false; + + String tag = bt->Struct.tags[i]; + String value = {}; + if (struct_tag_lookup(tag, "raddbg", &value)) { + s = gb_string_append_length(s, value.text, value.len); + custom_rule = true; + } else if (struct_tag_lookup(tag, "fmt", &value)) { + auto p = string_partition(value, make_string_c(",")); + String tail = p.tail; + if (tail.len != 0 && tail != "0") { + s = gb_string_appendc(s, "array("); + s = gb_string_append_length(s, name.text, name.len); + s = gb_string_appendc(s, ", "); + s = gb_string_append_length(s, tail.text, tail.len); + s = gb_string_appendc(s, ")"); + custom_rule = true; + } + } + + if (!custom_rule) { + s = gb_string_append_length(s, name.text, name.len); + } + } + + s = gb_string_appendc(s, ")"); + + view = make_string((u8 const *)s, gb_string_length(s)); + } + } + } + + raddbg_type_view_end:; + + if (view.len == 0) { + // Ignore the type, it didn't anything custom + continue; + } + + array_add(&c->info.raddbg_type_views, RaddbgTypeView{type, view}); + } + } + TIME_SECTION("type check finish"); } diff --git a/src/checker.hpp b/src/checker.hpp index dabb7330a..e32250b2f 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -161,6 +161,9 @@ struct AttributeContext { String require_target_feature; // required by the target micro-architecture String enable_target_feature; // will be enabled for the procedure only + + bool raddbg_type_view; + String raddbg_type_view_string; }; gb_internal gb_inline AttributeContext make_attribute_context(String link_prefix, String link_suffix) { @@ -427,6 +430,11 @@ struct Defineable { String pos_str; }; +struct RaddbgTypeView { + Type * type; + String view; +}; + // CheckerInfo stores all the symbol information for a type-checked program struct CheckerInfo { Checker *checker; @@ -487,6 +495,9 @@ struct CheckerInfo { MPSCQueue foreign_imports_to_check_fullpaths; MPSCQueue foreign_decls_to_check; + MPSCQueue raddbg_type_views_queue; + Array raddbg_type_views; + MPSCQueue intrinsics_entry_point_usage; BlockingMutex objc_objc_msgSend_mutex; diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index fd3701108..ff17e9c10 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -3416,7 +3416,29 @@ gb_internal bool lb_generate_code(lbGenerator *gen) { TEMPORARY_ALLOCATOR_GUARD(); + for (RaddbgTypeView const &type_view : gen->info->raddbg_type_views) { + if (type_view.type == nullptr) { + continue; + } + if (type_view.view.len == 0) { + continue; + } + + String t_str = type_to_canonical_string(temporary_allocator(), type_view.type); + + gbString s = gb_string_make(temporary_allocator(), ""); + + s = gb_string_appendc(s, "type_view: {type: \""); + s = gb_string_append_length(s, t_str.text, t_str.len); + s = gb_string_appendc(s, "\", expr: \""); + s = gb_string_append_length(s, type_view.view.text, type_view.view.len); + s = gb_string_appendc(s, "\"}"); + + lb_add_raddbg_string(m, s); + } + + TEMPORARY_ALLOCATOR_GUARD(); u32 global_name_index = 0; for (String str = {}; mpsc_dequeue(&gen->raddebug_section_strings, &str); /**/) { LLVMValueRef data = LLVMConstStringInContext(ctx, cast(char const *)str.text, cast(unsigned)str.len, false); From 26d066d369de27892de66d3eefb8d2a4a54e5b7c Mon Sep 17 00:00:00 2001 From: Bailey Gibbons Date: Fri, 22 Aug 2025 15:34:50 +1000 Subject: [PATCH 078/105] Add `add/remove_document_event_listener()` to `core:sys/wasm/js` --- core/sys/wasm/js/events.odin | 20 +++++++++++++ core/sys/wasm/js/events_all_targets.odin | 8 ++++++ core/sys/wasm/js/odin.js | 36 ++++++++++++++++++++++++ 3 files changed, 64 insertions(+) diff --git a/core/sys/wasm/js/events.odin b/core/sys/wasm/js/events.odin index 37a6e6c35..f5a47c06b 100644 --- a/core/sys/wasm/js/events.odin +++ b/core/sys/wasm/js/events.odin @@ -373,12 +373,32 @@ remove_window_event_listener :: proc(kind: Event_Kind, user_data: rawptr, callba return _remove_window_event_listener(event_kind_string[kind], user_data, callback, use_capture) } +add_document_event_listener :: proc(kind: Event_Kind, user_data: rawptr, callback: proc(e: Event), use_capture := false) -> bool { + @(default_calling_convention="contextless") + foreign dom_lib { + @(link_name="add_document_event_listener") + _add_document_event_listener :: proc(name: string, name_code: Event_Kind, user_data: rawptr, callback: proc "odin" (Event), use_capture: bool) -> bool --- + } + return _add_document_event_listener(event_kind_string[kind], kind, user_data, callback, use_capture) +} + +remove_document_event_listener :: proc(kind: Event_Kind, user_data: rawptr, callback: proc(e: Event), use_capture := false) -> bool { + @(default_calling_convention="contextless") + foreign dom_lib { + @(link_name="remove_document_event_listener") + _remove_document_event_listener :: proc(name: string, user_data: rawptr, callback: proc "odin" (Event), use_capture: bool) -> bool --- + } + return _remove_document_event_listener(event_kind_string[kind], user_data, callback, use_capture) +} + remove_event_listener_from_event :: proc(e: Event) -> bool { from_use_capture_false: bool from_use_capture_true: bool if e.id == "" { from_use_capture_false = remove_window_event_listener(e.kind, e.user_data, e.callback, false) from_use_capture_true = remove_window_event_listener(e.kind, e.user_data, e.callback, true) + from_use_capture_false |= remove_document_event_listener(e.kind, e.user_data, e.callback, false) + from_use_capture_true |= remove_document_event_listener(e.kind, e.user_data, e.callback, true) } else { from_use_capture_false = remove_event_listener(e.id, e.kind, e.user_data, e.callback, false) from_use_capture_true = remove_event_listener(e.id, e.kind, e.user_data, e.callback, true) diff --git a/core/sys/wasm/js/events_all_targets.odin b/core/sys/wasm/js/events_all_targets.odin index 6439396c5..903252c7a 100644 --- a/core/sys/wasm/js/events_all_targets.odin +++ b/core/sys/wasm/js/events_all_targets.odin @@ -275,6 +275,14 @@ remove_window_event_listener :: proc(kind: Event_Kind, user_data: rawptr, callba panic("vendor:wasm/js not supported on non JS targets") } +add_document_event_listener :: proc(kind: Event_Kind, user_data: rawptr, callback: proc(e: Event), use_capture := false) -> bool { + panic("vendor:wasm/js not supported on non JS targets") +} + +remove_document_event_listener :: proc(kind: Event_Kind, user_data: rawptr, callback: proc(e: Event), use_capture := false) -> bool { + panic("vendor:wasm/js not supported on non JS targets") +} + remove_event_listener_from_event :: proc(e: Event) -> bool { panic("vendor:wasm/js not supported on non JS targets") } diff --git a/core/sys/wasm/js/odin.js b/core/sys/wasm/js/odin.js index 1fbcc886e..2a8ccdd5e 100644 --- a/core/sys/wasm/js/odin.js +++ b/core/sys/wasm/js/odin.js @@ -1738,6 +1738,28 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement, memory) { return true; }, + add_document_event_listener: (name_ptr, name_len, name_code, data, callback, use_capture) => { + let name = wasmMemoryInterface.loadString(name_ptr, name_len); + let element = document; + let key = listener_key('document', name, data, callback, !!use_capture); + if (wasmMemoryInterface.listenerMap.has(key)) { + return false; + } + + let listener = (e) => { + let event_data = {}; + event_data.id_ptr = 0; + event_data.id_len = 0; + event_data.event = e; + event_data.name_code = name_code; + + onEventReceived(event_data, data, callback); + }; + wasmMemoryInterface.listenerMap.set(key, listener); + element.addEventListener(name, listener, !!use_capture); + return true; + }, + remove_event_listener: (id_ptr, id_len, name_ptr, name_len, data, callback, use_capture) => { let id = wasmMemoryInterface.loadString(id_ptr, id_len); let name = wasmMemoryInterface.loadString(name_ptr, name_len); @@ -1770,6 +1792,20 @@ function odinSetupDefaultImports(wasmMemoryInterface, consoleElement, memory) { element.removeEventListener(name, listener, !!use_capture); return true; }, + remove_document_event_listener: (name_ptr, name_len, data, callback, use_capture) => { + let name = wasmMemoryInterface.loadString(name_ptr, name_len); + let element = document; + + let key = listener_key('document', name, data, callback, !!use_capture); + let listener = wasmMemoryInterface.listenerMap.get(key); + if (listener === undefined) { + return false; + } + wasmMemoryInterface.listenerMap.delete(key); + + element.removeEventListener(name, listener, !!use_capture); + return true; + }, event_stop_propagation: () => { if (event_temp.data && event_temp.data.event) { From 23689d0c01895aeb0f0faaee9ff1008732d6fd13 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 22 Aug 2025 09:29:07 +0100 Subject: [PATCH 079/105] Improve the raddbg type views generated from `fmt`-based struct field tags --- src/checker.cpp | 415 +++++++++++++++++++++++++++++++----------------- 1 file changed, 269 insertions(+), 146 deletions(-) diff --git a/src/checker.cpp b/src/checker.cpp index c6dd1643a..a1a668038 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -6581,6 +6581,273 @@ gb_internal void check_deferred_procedures(Checker *c) { } +gb_internal void handle_raddbg_type_view(Checker *c, RaddbgTypeView const &type_view) { + auto const struct_tag_lookup = [](String tag, char const *key_c, String *value_) -> bool { + String t = tag; + String key = make_string_c(key_c); + while (t.len != 0) { + isize i = 0; + while (i < t.len && t[i] == ' ') { // Skip whitespace + i += 1; + } + t.text += i; + t.len -= i; + if (t.len == 0) { + break; + } + + i = 0; + + while (i < t.len) { + u8 c = t[i]; + if (c == ':' || c == '"') { + break; + } else if ((0 <= c && c < ' ') || (0x7f <= c && c <= 0x9f)) { + // break if control character is found + break; + } + i += 1; + } + + if (i == 0) { + break; + } + if (i+1 >= t.len) { + break; + } + if (t[i] != ':' || t[i+1] != '"') { + break; + } + String name = {t.text, i}; + t = {t.text+i+1, t.len-(i+1)}; + + i = 1; + while (i < t.len && t[i] != '"') { // find closing quote + if (t[i] == '\\') { + i += 1; // Skip escaped characters + } + i += 1; + } + if (i >= t.len) { + break; + } + + String value = {t.text, i+1}; + t = {t.text+i+1, t.len-(i+1)}; + + if (key == name) { + value = {value.text+1, i-1}; + value = string_trim_whitespace(value); + if (value_) *value_ = value; + return true; + } + } + return false; + }; + + auto const parse_int = [](String s, isize *offset_, u64 *result_) -> bool { + isize offset = *offset_; + isize new_offset = *offset_; + + u64 result = 0; + + while (new_offset < s.len) { + u8 c = s[new_offset]; + if (!('0' <= c && c <= '9')) { + break; + } + + new_offset += 1; + result *= 10; + result += u64(c)-'0'; + } + + *offset_ = new_offset; + *result_ = result; + return new_offset > offset; + }; + + Type *type = type_view.type; + if (type == nullptr || type == t_invalid) { + return; + } + String view = type_view.view; + if (view.len != 0) { + array_add(&c->info.raddbg_type_views, RaddbgTypeView{type, view}); + return; + } + + // NOTE(bill): Generate one automatically from the struct field tags if they exist + // If it cannot be generated, it'll be ignored/err + + Type *bt = base_type(type); + if (is_type_struct(type)) { + GB_ASSERT(bt->kind == Type_Struct); + if (bt->Struct.tags != nullptr) { + bool found_any = false; + + for (isize i = 0; i < bt->Struct.fields.count; i++) { + String tag = bt->Struct.tags[i]; + String value = {}; + if (struct_tag_lookup(tag, "raddbg", &value)) { + found_any = true; + } else if (struct_tag_lookup(tag, "fmt", &value)) { + found_any = true; + } + } + + if (!found_any) { + return; + } + + gbString s = gb_string_make(heap_allocator(), ""); + + s = gb_string_appendc(s, "rows($"); + + for (isize i = 0; i < bt->Struct.fields.count; i++) { + Entity *field = bt->Struct.fields[i]; + GB_ASSERT(field != nullptr); + String name = field->token.string; + String tag = bt->Struct.tags[i]; + String value = {}; + bool custom_rule = false; + + bool raddbg_seen = false; + if (struct_tag_lookup(tag, "raddbg", &value)) { + raddbg_seen = true; + if (value == "-") { + // Ignore this field entirely; + continue; + } + } + + s = gb_string_appendc(s, ", "); + + if (raddbg_seen) { + if (value == "") { + // ignore + } else { + s = gb_string_append_length(s, value.text, value.len); + custom_rule = true; + } + } else if (struct_tag_lookup(tag, "fmt", &value)) { + if (value == "" || value == "-") { + // ignore + } else { + auto p = string_partition(value, make_string_c(",")); + String head = p.head; + String tail = p.tail; + + isize i = 0; + + for (bool ok = true; ok && i < head.len; i += 1) { + switch (head[i]) { + case '+': + case '-': + case ' ': + case '#': + case '0': + break; + default: + i -= 1; + ok = false; + break; + } + } + + u64 prec = 0; + u64 width = 0; + bool width_ok = parse_int(head, &i, &width); + bool prec_ok = false; + if (i < head.len && head[i] == '.') { + i += 1; + prec_ok = parse_int(head, &i, &prec); + } + + + Rune verb = 0; + if (i >= head.len || head[i] == ' ') { + verb = 'v'; + } else { + utf8_decode(head.text+i, head.len-i, &verb); + } + + isize paren_count = 0; + + + if (width_ok) { + s = gb_string_appendc(s, "digits("); + paren_count += 1; + } + + switch (verb) { + case 'b': + s = gb_string_appendc(s, "bin("); + paren_count += 1; + break; + case 'd': + s = gb_string_appendc(s, "dec("); + paren_count += 1; + break; + case 'x': + case 'X': + s = gb_string_appendc(s, "hex("); + paren_count += 1; + break; + case 'o': + s = gb_string_appendc(s, "oct("); + paren_count += 1; + break; + } + + + if (tail.len != 0 && tail != "0") { + s = gb_string_appendc(s, "array("); + s = gb_string_append_length(s, name.text, name.len); + if (is_type_slice(field->type) || is_type_dynamic_array(field->type)) { + s = gb_string_appendc(s, ".data"); + } + s = gb_string_appendc(s, ", "); + s = gb_string_append_length(s, tail.text, tail.len); + s = gb_string_appendc(s, ")"); + custom_rule = true; + } else { + s = gb_string_append_length(s, name.text, name.len); + custom_rule = true; + } + + if (width_ok) { + s = gb_string_append_fmt(s, ", %llu", cast(unsigned long long)width); + } + + for (isize j = 0; j < paren_count; j++) { + s = gb_string_appendc(s, ")"); + custom_rule = true; + } + } + } + + if (!custom_rule) { + s = gb_string_append_length(s, name.text, name.len); + } + } + + s = gb_string_appendc(s, ")"); + + + gb_printf_err("%s\n", s); + view = make_string((u8 const *)s, gb_string_length(s)); + } + } + + if (view.len == 0) { + // Ignore the type, it didn't anything custom + return; + } + + array_add(&c->info.raddbg_type_views, RaddbgTypeView{type, view}); +} + gb_internal void check_objc_context_provider_procedures(Checker *c) { for (Entity *e = nullptr; mpsc_dequeue(&c->procs_with_objc_context_provider_to_check, &e); /**/) { GB_ASSERT(e->kind == Entity_TypeName); @@ -7059,152 +7326,8 @@ gb_internal void check_parsed_files(Checker *c) { } TIME_SECTION("collate type info stuff"); - { - auto const struct_tag_lookup = [](String tag, char const *key_c, String *value_) -> bool { - String t = tag; - String key = make_string_c(key_c); - while (t.len != 0) { - isize i = 0; - while (i < t.len && t[i] == ' ') { // Skip whitespace - i += 1; - } - t.text += i; - t.len -= i; - if (t.len == 0) { - break; - } - - i = 0; - - while (i < t.len) { - u8 c = t[i]; - if (c == ':' || c == '"') { - break; - } else if ((0 <= c && c < ' ') || (0x7f <= c && c <= 0x9f)) { - // break if control character is found - break; - } - i += 1; - } - - if (i == 0) { - break; - } - if (i+1 >= t.len) { - break; - } - if (t[i] != ':' || t[i+1] != '"') { - break; - } - String name = {t.text, i}; - t = {t.text+i+1, t.len-(i+1)}; - - i = 1; - while (i < t.len && t[i] != '"') { // find closing quote - if (t[i] == '\\') { - i += 1; // Skip escaped characters - } - i += 1; - } - if (i >= t.len) { - break; - } - - String value = {t.text, i+1}; - t = {t.text+i+1, t.len-(i+1)}; - - if (key == name) { - value = {value.text+1, i-1}; - if (value_) *value_ = value; - return true; - } - } - return false; - }; - - for (RaddbgTypeView type_view; mpsc_dequeue(&c->info.raddbg_type_views_queue, &type_view); /**/) { - - Type *type = type_view.type; - if (type == nullptr || type == t_invalid) { - continue; - } - String view = type_view.view; - if (view.len == 0) { - // NOTE(bill): Generate one automatically from the struct field tags if they exist - // If it cannot be generated, it'll be ignored/err - - Type *bt = base_type(type); - if (is_type_struct(type)) { - GB_ASSERT(bt->kind == Type_Struct); - if (bt->Struct.tags != nullptr) { - bool found_any = false; - - for (isize i = 0; i < bt->Struct.fields.count; i++) { - String tag = bt->Struct.tags[i]; - String value = {}; - if (struct_tag_lookup(tag, "raddbg", &value)) { - found_any = true; - } else if (struct_tag_lookup(tag, "fmt", &value)) { - found_any = true; - } - } - - if (!found_any) { - goto raddbg_type_view_end; - } - - gbString s = gb_string_make(heap_allocator(), ""); - - s = gb_string_appendc(s, "rows($"); - - for (isize i = 0; i < bt->Struct.fields.count; i++) { - Entity *field = bt->Struct.fields[i]; - GB_ASSERT(field != nullptr); - String name = field->token.string; - - s = gb_string_appendc(s, ", "); - - bool custom_rule = false; - - String tag = bt->Struct.tags[i]; - String value = {}; - if (struct_tag_lookup(tag, "raddbg", &value)) { - s = gb_string_append_length(s, value.text, value.len); - custom_rule = true; - } else if (struct_tag_lookup(tag, "fmt", &value)) { - auto p = string_partition(value, make_string_c(",")); - String tail = p.tail; - if (tail.len != 0 && tail != "0") { - s = gb_string_appendc(s, "array("); - s = gb_string_append_length(s, name.text, name.len); - s = gb_string_appendc(s, ", "); - s = gb_string_append_length(s, tail.text, tail.len); - s = gb_string_appendc(s, ")"); - custom_rule = true; - } - } - - if (!custom_rule) { - s = gb_string_append_length(s, name.text, name.len); - } - } - - s = gb_string_appendc(s, ")"); - - view = make_string((u8 const *)s, gb_string_length(s)); - } - } - } - - raddbg_type_view_end:; - - if (view.len == 0) { - // Ignore the type, it didn't anything custom - continue; - } - - array_add(&c->info.raddbg_type_views, RaddbgTypeView{type, view}); - } + for (RaddbgTypeView type_view; mpsc_dequeue(&c->info.raddbg_type_views_queue, &type_view); /**/) { + handle_raddbg_type_view(c, type_view); } From 46d4f22ef43a0935e6b6f88091969bd1e3cd4cd2 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 22 Aug 2025 09:29:44 +0100 Subject: [PATCH 080/105] Remove debug print --- src/checker.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/checker.cpp b/src/checker.cpp index a1a668038..3f7c54ac6 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -6834,8 +6834,6 @@ gb_internal void handle_raddbg_type_view(Checker *c, RaddbgTypeView const &type_ s = gb_string_appendc(s, ")"); - - gb_printf_err("%s\n", s); view = make_string((u8 const *)s, gb_string_length(s)); } } From 93810407110178f12a97ea2ba73b481c28bd64ec Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 22 Aug 2025 09:32:17 +0100 Subject: [PATCH 081/105] Fix parentheses for raddbg expression --- src/checker.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/checker.cpp b/src/checker.cpp index 3f7c54ac6..8ea56a4ba 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -6777,7 +6777,7 @@ gb_internal void handle_raddbg_type_view(Checker *c, RaddbgTypeView const &type_ if (width_ok) { s = gb_string_appendc(s, "digits("); - paren_count += 1; + custom_rule = true; } switch (verb) { @@ -6816,14 +6816,14 @@ gb_internal void handle_raddbg_type_view(Checker *c, RaddbgTypeView const &type_ custom_rule = true; } - if (width_ok) { - s = gb_string_append_fmt(s, ", %llu", cast(unsigned long long)width); - } for (isize j = 0; j < paren_count; j++) { s = gb_string_appendc(s, ")"); custom_rule = true; } + if (width_ok) { + s = gb_string_append_fmt(s, ", %llu)", cast(unsigned long long)width); + } } } From 27b59ab7c31339000da34e77903598e2690b89e9 Mon Sep 17 00:00:00 2001 From: Mohit Sethi <29519295+GloriousPtr@users.noreply.github.com> Date: Fri, 22 Aug 2025 16:45:50 +0100 Subject: [PATCH 082/105] Propogate `#caller_location` to core:container/queue procs --- core/container/queue/queue.odin | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/core/container/queue/queue.odin b/core/container/queue/queue.odin index 7f6f55826..8de8d55c0 100644 --- a/core/container/queue/queue.odin +++ b/core/container/queue/queue.odin @@ -22,7 +22,7 @@ DEFAULT_CAPACITY :: 16 /* Initialize a `Queue` with a starting `capacity` and an `allocator`. */ -init :: proc(q: ^$Q/Queue($T), capacity := DEFAULT_CAPACITY, allocator := context.allocator) -> runtime.Allocator_Error { +init :: proc(q: ^$Q/Queue($T), capacity := DEFAULT_CAPACITY, allocator := context.allocator, loc := #caller_location) -> runtime.Allocator_Error { clear(q) q.data = transmute([dynamic]T)runtime.Raw_Dynamic_Array{ data = nil, @@ -30,7 +30,7 @@ init :: proc(q: ^$Q/Queue($T), capacity := DEFAULT_CAPACITY, allocator := contex cap = 0, allocator = allocator, } - return reserve(q, capacity) + return reserve(q, capacity, loc) } /* @@ -114,9 +114,9 @@ Reserve enough space in the queue for at least the specified capacity. This may return an error if allocation failed. */ -reserve :: proc(q: ^$Q/Queue($T), capacity: int) -> runtime.Allocator_Error { +reserve :: proc(q: ^$Q/Queue($T), capacity: int, loc := #caller_location) -> runtime.Allocator_Error { if capacity > space(q^) { - return _grow(q, uint(capacity)) + return _grow(q, uint(capacity), loc) } return nil } @@ -269,9 +269,9 @@ Example: assert(queue.pop_front(&q) == 3) } */ -push_back :: proc(q: ^$Q/Queue($T), elem: T) -> (ok: bool, err: runtime.Allocator_Error) { +push_back :: proc(q: ^$Q/Queue($T), elem: T, loc := #caller_location) -> (ok: bool, err: runtime.Allocator_Error) { if space(q^) == 0 { - _grow(q) or_return + _grow(q, loc = loc) or_return } idx := (q.offset+uint(q.len))%builtin.len(q.data) q.data[idx] = elem @@ -303,9 +303,9 @@ Example: assert(queue.pop_back(&q) == 1) } */ -push_front :: proc(q: ^$Q/Queue($T), elem: T) -> (ok: bool, err: runtime.Allocator_Error) { +push_front :: proc(q: ^$Q/Queue($T), elem: T, loc := #caller_location) -> (ok: bool, err: runtime.Allocator_Error) { if space(q^) == 0 { - _grow(q) or_return + _grow(q, loc = loc) or_return } q.offset = uint(q.offset - 1 + builtin.len(q.data)) % builtin.len(q.data) q.len += 1 @@ -396,10 +396,10 @@ Push many elements at once to the back of the queue. If there is not enough space left and allocation fails to get more, this will return false with an `Allocator_Error`. */ -push_back_elems :: proc(q: ^$Q/Queue($T), elems: ..T) -> (ok: bool, err: runtime.Allocator_Error) { +push_back_elems :: proc(q: ^$Q/Queue($T), elems: ..T, loc := #caller_location) -> (ok: bool, err: runtime.Allocator_Error) { n := uint(builtin.len(elems)) if space(q^) < int(n) { - _grow(q, q.len + n) or_return + _grow(q, q.len + n, loc) or_return } sz := uint(builtin.len(q.data)) @@ -465,10 +465,10 @@ clear :: proc(q: ^$Q/Queue($T)) { // Internal growing procedure -_grow :: proc(q: ^$Q/Queue($T), min_capacity: uint = 0) -> runtime.Allocator_Error { +_grow :: proc(q: ^$Q/Queue($T), min_capacity: uint = 0, loc := #caller_location) -> runtime.Allocator_Error { new_capacity := max(min_capacity, uint(8), uint(builtin.len(q.data))*2) n := uint(builtin.len(q.data)) - builtin.resize(&q.data, int(new_capacity)) or_return + builtin.resize(&q.data, int(new_capacity), loc) or_return if q.offset + q.len > n { diff := n - q.offset copy(q.data[new_capacity-diff:], q.data[q.offset:][:diff]) From 05706864b7cdbd8fabf09dd8cb4d55e1e9174acf Mon Sep 17 00:00:00 2001 From: Damian Tarnawski Date: Sat, 23 Aug 2025 12:55:07 +0200 Subject: [PATCH 083/105] Support using allocator resize in `_reserve_soa` (fixes #5615) --- base/runtime/core_builtin_soa.odin | 60 ++++++++++++++++++++--- tests/core/runtime/test_core_runtime.odin | 26 ++++++++++ 2 files changed, 79 insertions(+), 7 deletions(-) diff --git a/base/runtime/core_builtin_soa.odin b/base/runtime/core_builtin_soa.odin index ff27a4559..5baeb9e24 100644 --- a/base/runtime/core_builtin_soa.odin +++ b/base/runtime/core_builtin_soa.odin @@ -249,17 +249,63 @@ _reserve_soa :: proc(array: ^$T/#soa[dynamic]$E, capacity: int, zero_memory: boo old_data := (^rawptr)(array)^ - new_bytes := array.allocator.procedure( - array.allocator.data, .Alloc if zero_memory else .Alloc_Non_Zeroed, new_size, max_align, - nil, old_size, loc, - ) or_return + new_bytes, resize_err := array.allocator.procedure( + array.allocator.data, .Resize if zero_memory else .Resize_Non_Zeroed, new_size, max_align, + old_data, old_size, loc, + ) new_data := raw_data(new_bytes) - - footer.cap = capacity - old_offset := 0 new_offset := 0 + + if resize_err == .None { + + footer.cap = capacity + + // Adjust layout + // before: |x x y y z z| + // now: |x x y y z z _ _ _| + // after: |x x _ y y _ z z _| + + for i in 0.. Date: Sat, 23 Aug 2025 13:10:19 +0200 Subject: [PATCH 084/105] Only zero memory when requested --- base/runtime/core_builtin_soa.odin | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/base/runtime/core_builtin_soa.odin b/base/runtime/core_builtin_soa.odin index 5baeb9e24..7548f6735 100644 --- a/base/runtime/core_builtin_soa.odin +++ b/base/runtime/core_builtin_soa.odin @@ -262,10 +262,9 @@ _reserve_soa :: proc(array: ^$T/#soa[dynamic]$E, capacity: int, zero_memory: boo footer.cap = capacity - // Adjust layout - // before: |x x y y z z| - // now: |x x y y z z _ _ _| - // after: |x x _ y y _ z z _| + // Correct data memory + // from: |x x y y z z _ _ _| + // to: |x x _ y y _ z z _| for i in 0.. Date: Sat, 23 Aug 2025 14:28:25 +0200 Subject: [PATCH 085/105] Zero existing memory when using resize_soa (fixes #5614) --- base/runtime/core_builtin_soa.odin | 24 ++++++++++++++++ tests/core/runtime/test_core_runtime.odin | 34 +++++++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/base/runtime/core_builtin_soa.odin b/base/runtime/core_builtin_soa.odin index ff27a4559..3cbf82bdc 100644 --- a/base/runtime/core_builtin_soa.odin +++ b/base/runtime/core_builtin_soa.odin @@ -178,9 +178,33 @@ resize_soa :: proc(array: ^$T/#soa[dynamic]$E, #any_int length: int, loc := #cal if array == nil { return nil } + reserve_soa(array, length, loc) or_return footer := raw_soa_footer(array) + old_len := footer.len footer.len = length + + if size_of(E) > 0 && length > old_len { + ti := type_info_of(typeid_of(T)) + ti = type_info_base(ti) + si := &ti.variant.(Type_Info_Struct) + + field_count := len(E) when intrinsics.type_is_array(E) else intrinsics.type_struct_field_count(E) + + data := (^rawptr)(array)^ + + soa_offset := 0 + for i in 0.. Date: Sat, 23 Aug 2025 16:55:12 +0200 Subject: [PATCH 086/105] Avoid overlap issues when correcting memory after resize in _reserve_soa --- base/runtime/core_builtin_soa.odin | 19 ++++++-- tests/core/runtime/test_core_runtime.odin | 58 +++++++++++++++++------ 2 files changed, 58 insertions(+), 19 deletions(-) diff --git a/base/runtime/core_builtin_soa.odin b/base/runtime/core_builtin_soa.odin index 7548f6735..46c767751 100644 --- a/base/runtime/core_builtin_soa.odin +++ b/base/runtime/core_builtin_soa.odin @@ -266,6 +266,12 @@ _reserve_soa :: proc(array: ^$T/#soa[dynamic]$E, capacity: int, zero_memory: boo // from: |x x y y z z _ _ _| // to: |x x _ y y _ z z _| + // move old data to the end of the new allocation to avoid overlap + old_start := uintptr(new_data) + uintptr(new_size - old_size) + mem_copy(rawptr(old_start), old_data, old_size) + + // now: |_ _ _ x x y y z z| + for i in 0.. Date: Sat, 23 Aug 2025 17:07:57 +0200 Subject: [PATCH 087/105] Always use .Resize_Non_Zeroed in _reserve_soa --- base/runtime/core_builtin_soa.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/runtime/core_builtin_soa.odin b/base/runtime/core_builtin_soa.odin index 46c767751..33cb760ed 100644 --- a/base/runtime/core_builtin_soa.odin +++ b/base/runtime/core_builtin_soa.odin @@ -250,7 +250,7 @@ _reserve_soa :: proc(array: ^$T/#soa[dynamic]$E, capacity: int, zero_memory: boo old_data := (^rawptr)(array)^ new_bytes, resize_err := array.allocator.procedure( - array.allocator.data, .Resize if zero_memory else .Resize_Non_Zeroed, new_size, max_align, + array.allocator.data, .Resize_Non_Zeroed, new_size, max_align, old_data, old_size, loc, ) new_data := raw_data(new_bytes) From 66f4c9342098e5d5c0cf10b5aea7b57c5e0dd1d3 Mon Sep 17 00:00:00 2001 From: Damian Tarnawski Date: Sun, 24 Aug 2025 15:04:19 +0200 Subject: [PATCH 088/105] Handle nil old data case --- base/runtime/core_builtin_soa.odin | 89 ++++++++++++++++-------------- 1 file changed, 48 insertions(+), 41 deletions(-) diff --git a/base/runtime/core_builtin_soa.odin b/base/runtime/core_builtin_soa.odin index 33cb760ed..d436b9a3a 100644 --- a/base/runtime/core_builtin_soa.odin +++ b/base/runtime/core_builtin_soa.odin @@ -249,68 +249,73 @@ _reserve_soa :: proc(array: ^$T/#soa[dynamic]$E, capacity: int, zero_memory: boo old_data := (^rawptr)(array)^ - new_bytes, resize_err := array.allocator.procedure( - array.allocator.data, .Resize_Non_Zeroed, new_size, max_align, - old_data, old_size, loc, - ) - new_data := raw_data(new_bytes) + if old_data != nil { + new_bytes, resize_err := array.allocator.procedure( + array.allocator.data, .Resize_Non_Zeroed, new_size, max_align, + old_data, old_size, loc, + ) + new_data := raw_data(new_bytes) - old_offset := 0 - new_offset := 0 + if resize_err == .None { - if resize_err == .None { + footer.cap = capacity - footer.cap = capacity + old_offset := 0 + new_offset := 0 - // Correct data memory - // from: |x x y y z z _ _ _| - // to: |x x _ y y _ z z _| + // Correct data memory + // from: |x x y y z z _ _ _| + // to: |x x _ y y _ z z _| - // move old data to the end of the new allocation to avoid overlap - old_start := uintptr(new_data) + uintptr(new_size - old_size) - mem_copy(rawptr(old_start), old_data, old_size) + // move old data to the end of the new allocation to avoid overlap + old_start := uintptr(new_data) + uintptr(new_size - old_size) + mem_copy(rawptr(old_start), new_data, old_size) - // now: |_ _ _ x x y y z z| + // now: |_ _ _ x x y y z z| - for i in 0.. Date: Sun, 24 Aug 2025 15:09:08 +0200 Subject: [PATCH 089/105] More soa tests --- tests/core/runtime/test_core_runtime.odin | 95 ++++++++++++++--------- 1 file changed, 59 insertions(+), 36 deletions(-) diff --git a/tests/core/runtime/test_core_runtime.odin b/tests/core/runtime/test_core_runtime.odin index 1bc100348..3ed252026 100644 --- a/tests/core/runtime/test_core_runtime.odin +++ b/tests/core/runtime/test_core_runtime.odin @@ -179,6 +179,22 @@ test_map_get :: proc(t: ^testing.T) { } } +@(test) +test_soa_make_len :: proc(t: ^testing.T) { + + array, err := make(#soa[dynamic][2]int, 2) + defer delete(array) + array[0] = [2]int{1, 2} + array[1] = [2]int{3, 4} + + testing.expect_value(t, err, nil) + testing.expect_value(t, len(array), 2) + testing.expect_value(t, cap(array), 2) + + testing.expect_value(t, array[0], [2]int{1, 2}) + testing.expect_value(t, array[1], [2]int{3, 4}) +} + @(test) test_soa_array_allocator_resize :: proc(t: ^testing.T) { @@ -186,53 +202,60 @@ test_soa_array_allocator_resize :: proc(t: ^testing.T) { context.allocator = runtime.arena_allocator(&arena) defer runtime.arena_destroy(&arena) - { - // |1 3 _ 2 4 _| - // |1 3 _ _ 2 4 _ _| + // |1 3 _ 2 4 _| + // |1 3 _ _ 2 4 _ _| - array, err := make(#soa[dynamic][2]int, 2, 3) - array[0] = [2]int{1, 2} - array[1] = [2]int{3, 4} + array, err := make(#soa[dynamic][2]int, 2, 3) + defer delete(array) + array[0] = [2]int{1, 2} + array[1] = [2]int{3, 4} - testing.expect_value(t, err, nil) - testing.expect_value(t, len(array), 2) - testing.expect_value(t, cap(array), 3) + testing.expect_value(t, err, nil) + testing.expect_value(t, len(array), 2) + testing.expect_value(t, cap(array), 3) - err = resize(&array, 4) + err = resize(&array, 4) - testing.expect_value(t, err, nil) - testing.expect_value(t, len(array), 4) - testing.expect_value(t, cap(array), 4) + testing.expect_value(t, err, nil) + testing.expect_value(t, len(array), 4) + testing.expect_value(t, cap(array), 4) - testing.expect_value(t, array[0], [2]int{1, 2}) - testing.expect_value(t, array[1], [2]int{3, 4}) - testing.expect_value(t, array[2], [2]int{0, 0}) - testing.expect_value(t, array[3], [2]int{0, 0}) - } + testing.expect_value(t, array[0], [2]int{1, 2}) + testing.expect_value(t, array[1], [2]int{3, 4}) + testing.expect_value(t, array[2], [2]int{0, 0}) + testing.expect_value(t, array[3], [2]int{0, 0}) +} - { - // |1 4 2 5 3 6| - // |1 4 _ _ 2 5 _ _ 3 6 _ _| - array, err := make(#soa[dynamic][3]int, 2, 2) - array[0] = [3]int{1, 2, 3} - array[1] = [3]int{4, 5, 6} +@(test) +test_soa_array_allocator_resize_overlapping :: proc(t: ^testing.T) { - testing.expect_value(t, err, nil) - testing.expect_value(t, len(array), 2) - testing.expect_value(t, cap(array), 2) + arena: runtime.Arena + context.allocator = runtime.arena_allocator(&arena) + defer runtime.arena_destroy(&arena) - err = resize(&array, 4) + // |1 4 2 5 3 6| + // |1 4 _ _ 2 5 _ _ 3 6 _ _| - testing.expect_value(t, err, nil) - testing.expect_value(t, len(array), 4) - testing.expect_value(t, cap(array), 4) + array, err := make(#soa[dynamic][3]int, 2, 2) + defer delete(array) + array[0] = [3]int{1, 2, 3} + array[1] = [3]int{4, 5, 6} - testing.expect_value(t, array[0], [3]int{1, 2, 3}) - testing.expect_value(t, array[1], [3]int{4, 5, 6}) - testing.expect_value(t, array[2], [3]int{0, 0, 0}) - testing.expect_value(t, array[3], [3]int{0, 0, 0}) - } + testing.expect_value(t, err, nil) + testing.expect_value(t, len(array), 2) + testing.expect_value(t, cap(array), 2) + + err = resize(&array, 4) + + testing.expect_value(t, err, nil) + testing.expect_value(t, len(array), 4) + testing.expect_value(t, cap(array), 4) + + testing.expect_value(t, array[0], [3]int{1, 2, 3}) + testing.expect_value(t, array[1], [3]int{4, 5, 6}) + testing.expect_value(t, array[2], [3]int{0, 0, 0}) + testing.expect_value(t, array[3], [3]int{0, 0, 0}) } @(test) From 95cfad67b776c4d839aa494fa88832a67c0c28cc Mon Sep 17 00:00:00 2001 From: Damian Tarnawski Date: Sun, 24 Aug 2025 15:17:13 +0200 Subject: [PATCH 090/105] =?UTF-8?q?Cleanup=20soa=20resize=20logic=E2=80=94?= =?UTF-8?q?reduce=20nesting?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- base/runtime/core_builtin_soa.odin | 64 +++++++++++++++--------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/base/runtime/core_builtin_soa.odin b/base/runtime/core_builtin_soa.odin index d436b9a3a..9d042267a 100644 --- a/base/runtime/core_builtin_soa.odin +++ b/base/runtime/core_builtin_soa.odin @@ -249,60 +249,60 @@ _reserve_soa :: proc(array: ^$T/#soa[dynamic]$E, capacity: int, zero_memory: boo old_data := (^rawptr)(array)^ - if old_data != nil { + resize: if old_data != nil { + new_bytes, resize_err := array.allocator.procedure( array.allocator.data, .Resize_Non_Zeroed, new_size, max_align, old_data, old_size, loc, ) new_data := raw_data(new_bytes) - if resize_err == .None { + #partial switch resize_err { + case .Mode_Not_Implemented: break resize + case .None: // continue resizing + case: return resize_err + } - footer.cap = capacity + footer.cap = capacity - old_offset := 0 - new_offset := 0 + old_offset := 0 + new_offset := 0 - // Correct data memory - // from: |x x y y z z _ _ _| - // to: |x x _ y y _ z z _| + // Correct data memory + // from: |x x y y z z _ _ _| + // to: |x x _ y y _ z z _| - // move old data to the end of the new allocation to avoid overlap - old_start := uintptr(new_data) + uintptr(new_size - old_size) - mem_copy(rawptr(old_start), new_data, old_size) + // move old data to the end of the new allocation to avoid overlap + old_data = rawptr(uintptr(new_data) + uintptr(new_size - old_size)) + mem_copy(old_data, new_data, old_size) - // now: |_ _ _ x x y y z z| + // now: |_ _ _ x x y y z z| - for i in 0.. Date: Tue, 26 Aug 2025 13:03:26 +0200 Subject: [PATCH 091/105] Add missing test attr and don't zero memory when reserve already did --- base/runtime/core_builtin_soa.odin | 15 +++++++-------- tests/core/runtime/test_core_runtime.odin | 1 + 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/base/runtime/core_builtin_soa.odin b/base/runtime/core_builtin_soa.odin index a27381613..331254ac7 100644 --- a/base/runtime/core_builtin_soa.odin +++ b/base/runtime/core_builtin_soa.odin @@ -179,14 +179,12 @@ resize_soa :: proc(array: ^$T/#soa[dynamic]$E, #any_int length: int, loc := #cal return nil } - reserve_soa(array, length, loc) or_return footer := raw_soa_footer(array) - old_len := footer.len - footer.len = length - if size_of(E) > 0 && length > old_len { - ti := type_info_of(typeid_of(T)) - ti = type_info_base(ti) + if length > footer.cap { + reserve_soa(array, length, loc) or_return + } else if size_of(E) > 0 && length > footer.len { + ti := type_info_base(type_info_of(typeid_of(T))) si := &ti.variant.(Type_Info_Struct) field_count := len(E) when intrinsics.type_is_array(E) else intrinsics.type_struct_field_count(E) @@ -199,12 +197,13 @@ resize_soa :: proc(array: ^$T/#soa[dynamic]$E, #any_int length: int, loc := #cal soa_offset = align_forward_int(soa_offset, align_of(E)) - mem_zero(rawptr(uintptr(data) + uintptr(soa_offset) + uintptr(type.size * old_len)), type.size * (length - old_len)) + mem_zero(rawptr(uintptr(data) + uintptr(soa_offset) + uintptr(type.size * footer.len)), type.size * (length - footer.len)) - soa_offset += type.size * cap(array) + soa_offset += type.size * footer.cap } } + footer.len = length return nil } diff --git a/tests/core/runtime/test_core_runtime.odin b/tests/core/runtime/test_core_runtime.odin index 6c3b489d7..881b5f41a 100644 --- a/tests/core/runtime/test_core_runtime.odin +++ b/tests/core/runtime/test_core_runtime.odin @@ -213,6 +213,7 @@ test_soa_array_resize :: proc(t: ^testing.T) { testing.expect_value(t, array[2], V{0, 0}) } +@(test) test_soa_make_len :: proc(t: ^testing.T) { array, err := make(#soa[dynamic][2]int, 2) From ed389c188c811420263fd587588d0c7bfc4c0b18 Mon Sep 17 00:00:00 2001 From: "Stanislav Ch. Nikolov" Date: Thu, 28 Aug 2025 12:39:15 +0300 Subject: [PATCH 092/105] Fixed and added obj-c methods for NSWindow --- core/sys/darwin/Foundation/NSWindow.odin | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/core/sys/darwin/Foundation/NSWindow.odin b/core/sys/darwin/Foundation/NSWindow.odin index fb280aa79..e1b027a89 100644 --- a/core/sys/darwin/Foundation/NSWindow.odin +++ b/core/sys/darwin/Foundation/NSWindow.odin @@ -568,6 +568,7 @@ window_delegate_register_and_alloc :: proc(template: WindowDelegateTemplate, cla @(objc_class="CALayer") Layer :: struct { using _: Object } + @(objc_type=Layer, objc_name="contents") Layer_contents :: proc "c" (self: ^Layer) -> rawptr { return msgSend(rawptr, self, "contents") @@ -662,8 +663,12 @@ Window_frame :: proc "c" (self: ^Window) -> Rect { return msgSend(Rect, self, "frame") } @(objc_type=Window, objc_name="setFrame") -Window_setFrame :: proc "c" (self: ^Window, frame: Rect) { - msgSend(nil, self, "setFrame:", frame) +Window_setFrame :: proc "c" (self: ^Window, frame: Rect, display: BOOL) { + msgSend(nil, self, "setFrame:display:", frame, display) +} +@(objc_type=Window, objc_name="setFrameOrigin") +Window_setFrameOrigin :: proc "c" (self: ^Window, origin: Point) { + msgSend(nil, self, "setFrameOrigin:", origin) } @(objc_type=Window, objc_name="opaque") Window_opaque :: proc "c" (self: ^Window) -> BOOL { @@ -701,6 +706,10 @@ Window_setMovable :: proc "c" (self: ^Window, ok: BOOL) { Window_setMovableByWindowBackground :: proc "c" (self: ^Window, ok: BOOL) { msgSend(nil, self, "setMovableByWindowBackground:", ok) } +@(objc_type=Window, objc_name="setAcceptsMouseMovedEvents") +Window_setAcceptsMouseMovedEvents :: proc "c" (self: ^Window, ok: BOOL) { + msgSend(nil, self, "setAcceptsMouseMovedEvents:", ok) +} @(objc_type=Window, objc_name="setStyleMask") Window_setStyleMask :: proc "c" (self: ^Window, style_mask: WindowStyleMask) { msgSend(nil, self, "setStyleMask:", style_mask) From 3074146784e253bd536b494aca2d7ce987ead20d Mon Sep 17 00:00:00 2001 From: A1029384756 Date: Thu, 28 Aug 2025 11:30:47 -0400 Subject: [PATCH 093/105] skip errors on polymorphic procs when in a proc group with other options --- src/check_expr.cpp | 2 ++ src/check_type.cpp | 4 +++- src/checker.hpp | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 862dd9278..80ec4f78e 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -7126,6 +7126,7 @@ gb_internal CallArgumentData check_call_arguments_proc_group(CheckerContext *c, gbString expr_name = expr_to_string(operand->expr); defer (gb_string_free(expr_name)); + c->in_proc_group = true; for_array(i, procs) { Entity *p = procs[i]; if (p->flags & EntityFlag_Disabled) { @@ -7168,6 +7169,7 @@ gb_internal CallArgumentData check_call_arguments_proc_group(CheckerContext *c, array_add(&valids, item); } } + c->in_proc_group = false; if (max_matched_features > 0) { for_array(i, valids) { diff --git a/src/check_type.cpp b/src/check_type.cpp index a427a1927..a104d6fc0 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -2085,7 +2085,9 @@ gb_internal Type *check_get_params(CheckerContext *ctx, Scope *scope, Ast *_para if (op.mode == Addressing_Constant) { poly_const = op.value; } else { - error(op.expr, "Expected a constant value for this polymorphic name parameter, got %s", expr_to_string(op.expr)); + if (!ctx->in_proc_group) { + error(op.expr, "Expected a constant value for this polymorphic name parameter, got %s", expr_to_string(op.expr)); + } success = false; } } diff --git a/src/checker.hpp b/src/checker.hpp index e32250b2f..58ac8beb5 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -563,6 +563,7 @@ struct CheckerContext { u32 stmt_flags; bool in_enum_type; + bool in_proc_group; bool collect_delayed_decls; bool allow_polymorphic_types; bool disallow_polymorphic_return_types; // NOTE(zen3ger): no poly type decl in return types From 94e1f30ebbf144831f66bc6531dfa78f3a9d9f74 Mon Sep 17 00:00:00 2001 From: Jon Lipstate Date: Fri, 29 Aug 2025 14:35:34 -0700 Subject: [PATCH 094/105] fix typo in CLSIDFromProgIDEx signature --- core/sys/windows/ole32.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/sys/windows/ole32.odin b/core/sys/windows/ole32.odin index 2e59949e3..32cb6fd60 100644 --- a/core/sys/windows/ole32.odin +++ b/core/sys/windows/ole32.odin @@ -58,7 +58,7 @@ foreign Ole32 { CoTaskMemFree :: proc(pv: rawptr) --- CLSIDFromProgID :: proc(lpszProgID: LPCOLESTR, lpclsid: LPCLSID) -> HRESULT --- - CLSIDFromProgIDEx :: proc(lpszProgID, LPCOLESTR, lpclsid: LPCLSID) -> HRESULT --- + CLSIDFromProgIDEx :: proc(lpszProgID: LPCOLESTR, lpclsid: LPCLSID) -> HRESULT --- CLSIDFromString :: proc(lpsz: LPOLESTR, pclsid: LPCLSID) -> HRESULT --- IIDFromString :: proc(lpsz: LPOLESTR, lpiid: LPIID) -> HRESULT --- ProgIDFromCLSID :: proc(clsid: REFCLSID, lplpszProgID: ^LPOLESTR) -> HRESULT --- From ba279ec4ea4b512c93685691506bea382e7bfea0 Mon Sep 17 00:00:00 2001 From: puugz <33222334+puugz@users.noreply.github.com> Date: Sat, 30 Aug 2025 18:31:46 +0200 Subject: [PATCH 095/105] Fix broken wglUseFontBitmaps binding --- core/sys/windows/wgl.odin | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/sys/windows/wgl.odin b/core/sys/windows/wgl.odin index 8fea55c3d..f50f06939 100644 --- a/core/sys/windows/wgl.odin +++ b/core/sys/windows/wgl.odin @@ -82,7 +82,8 @@ foreign Opengl32 { wglSetLayerPaletteEntries :: proc(hdc: HDC, layer_plane, start, entries: c.int, cr: ^COLORREF) -> c.int --- wglShareLists :: proc(HGLRC1, HGLRC2: HGLRC) -> BOOL --- wglSwapLayerBuffers :: proc(hdc: HDC, planes: DWORD) -> BOOL --- - wglUseFontBitmaps :: proc(hdc: HDC, first, count, list_base: DWORD) -> BOOL --- + wglUseFontBitmapsA :: proc(hdc: HDC, first, count, list_base: DWORD) -> BOOL --- + wglUseFontBitmapsW :: proc(hdc: HDC, first, count, list_base: DWORD) -> BOOL --- wglUseFontOutlines :: proc(hdc: HDC, first, count, list_base: DWORD, deviation, extrusion: f32, format: c.int, gmf: LPGLYPHMETRICSFLOAT) -> BOOL --- } From 10b7bba25daa7f3998472ea351cf63620bef3e08 Mon Sep 17 00:00:00 2001 From: FourteenBrush <74827262+FourteenBrush@users.noreply.github.com> Date: Sun, 31 Aug 2025 23:52:00 +0200 Subject: [PATCH 096/105] Add `LPFN_GETACCEPTEXSOCKADDRS` to ws2_32.odin --- core/sys/windows/ws2_32.odin | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/core/sys/windows/ws2_32.odin b/core/sys/windows/ws2_32.odin index cb1071d9e..0d1f477c3 100644 --- a/core/sys/windows/ws2_32.odin +++ b/core/sys/windows/ws2_32.odin @@ -82,6 +82,17 @@ Example Load: } */ +LPFN_GETACCEPTEXSOCKADDRS :: #type proc "system" ( + lpOutputBuffer: PVOID, + dwReceiveDataLength: DWORD, + dwLocalAddressLength: DWORD, + dwRemoteAddressLength: DWORD, + LocalSockaddr: ^^sockaddr, + LocalSockaddrLength: LPINT, + RemoteSockaddr: ^^sockaddr, + RemoteSockaddrLength: LPINT, +) + foreign import ws2_32 "system:Ws2_32.lib" @(default_calling_convention="system") foreign ws2_32 { @@ -248,4 +259,4 @@ foreign ws2_32 { // [MS-Docs](https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-htons) // Prefer using endian-specific integers instead, https://odin-lang.org/docs/overview/#basic-types htons :: proc(hostshort: c_ushort) -> c_ushort --- -} \ No newline at end of file +} From 8bb597b9dea6bc0297df26753cff024f9f68ff5d Mon Sep 17 00:00:00 2001 From: AmedeoAlf <142008331+AmedeoAlf@users.noreply.github.com> Date: Mon, 1 Sep 2025 22:44:24 +0200 Subject: [PATCH 097/105] Specify %m and %M as verbs for integer formatting --- core/fmt/doc.odin | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/fmt/doc.odin b/core/fmt/doc.odin index d45e6c796..eeebd33f7 100644 --- a/core/fmt/doc.odin +++ b/core/fmt/doc.odin @@ -29,6 +29,8 @@ Integer: %x base 16, with lower-case letters for a-f %X base 16, with upper-case letters for A-F %U Unicode format: U+1234; same as "U+%04X" + %m number of bytes in the best unit of measurement, e.g. 123.45mib + %M number of bytes in the best unit of measurement, e.g. 123.45MiB Floating-point, complex numbers, and quaternions: %e scientific notation, e.g. -1.23456e+78 %E scientific notation, e.g. -1.23456E+78 @@ -38,8 +40,6 @@ Floating-point, complex numbers, and quaternions: %G synonym for %g %h hexadecimal (lower-case) representation with 0h prefix (0h01234abcd) %H hexadecimal (upper-case) representation with 0H prefix (0h01234ABCD) - %m number of bytes in the best unit of measurement, e.g. 123.45mib - %M number of bytes in the best unit of measurement, e.g. 123.45MiB String and slice of bytes %s the uninterpreted bytes of the string or slice %q a double-quoted string safely escaped with Odin syntax From 21fd7c200e95dbbf3e6f5ba3d203c3056db9df65 Mon Sep 17 00:00:00 2001 From: Damian Tarnawski Date: Tue, 2 Sep 2025 13:03:15 +0200 Subject: [PATCH 098/105] Add require_results attr to procs returning an allocator --- base/runtime/default_allocators_nil.odin | 2 ++ base/runtime/default_temp_allocator_arena.odin | 1 + base/runtime/default_temporary_allocator.odin | 2 +- base/runtime/heap_allocator.odin | 1 + base/runtime/wasm_allocator.odin | 2 ++ core/mem/allocators.odin | 1 + 6 files changed, 8 insertions(+), 1 deletion(-) diff --git a/base/runtime/default_allocators_nil.odin b/base/runtime/default_allocators_nil.odin index 14edd11dd..f5ebad28f 100644 --- a/base/runtime/default_allocators_nil.odin +++ b/base/runtime/default_allocators_nil.odin @@ -23,6 +23,7 @@ nil_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, return nil, .None } +@(require_results) nil_allocator :: proc "contextless" () -> Allocator { return Allocator{ procedure = nil_allocator_proc, @@ -72,6 +73,7 @@ panic_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, return nil, nil } +@(require_results) panic_allocator :: proc() -> Allocator { return Allocator{ procedure = panic_allocator_proc, diff --git a/base/runtime/default_temp_allocator_arena.odin b/base/runtime/default_temp_allocator_arena.odin index 525f81825..8f4821b4a 100644 --- a/base/runtime/default_temp_allocator_arena.odin +++ b/base/runtime/default_temp_allocator_arena.odin @@ -187,6 +187,7 @@ arena_destroy :: proc "contextless" (arena: ^Arena, loc := #caller_location) { arena.total_capacity = 0 } +@(require_results) arena_allocator :: proc(arena: ^Arena) -> Allocator { return Allocator{arena_allocator_proc, arena} } diff --git a/base/runtime/default_temporary_allocator.odin b/base/runtime/default_temporary_allocator.odin index 671728be8..ec3c6ad8c 100644 --- a/base/runtime/default_temporary_allocator.odin +++ b/base/runtime/default_temporary_allocator.odin @@ -70,7 +70,7 @@ DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD :: #force_inline proc(ignore := false, loc := } } - +@(require_results) default_temp_allocator :: proc(allocator: ^Default_Temp_Allocator) -> Allocator { return Allocator{ procedure = default_temp_allocator_proc, diff --git a/base/runtime/heap_allocator.odin b/base/runtime/heap_allocator.odin index 4b04dffef..f2c887759 100644 --- a/base/runtime/heap_allocator.odin +++ b/base/runtime/heap_allocator.odin @@ -2,6 +2,7 @@ package runtime import "base:intrinsics" +@(require_results) heap_allocator :: proc() -> Allocator { return Allocator{ procedure = heap_allocator_proc, diff --git a/base/runtime/wasm_allocator.odin b/base/runtime/wasm_allocator.odin index 574f3dd06..325b1d4fa 100644 --- a/base/runtime/wasm_allocator.odin +++ b/base/runtime/wasm_allocator.odin @@ -89,10 +89,12 @@ wasm_allocator_init :: proc(a: ^WASM_Allocator, alignment: uint = 8) { global_default_wasm_allocator_data: WASM_Allocator +@(require_results) default_wasm_allocator :: proc() -> Allocator { return wasm_allocator(&global_default_wasm_allocator_data) } +@(require_results) wasm_allocator :: proc(a: ^WASM_Allocator) -> Allocator { return { data = a, diff --git a/core/mem/allocators.odin b/core/mem/allocators.odin index 2d7e7b3ea..59fe72fbb 100644 --- a/core/mem/allocators.odin +++ b/core/mem/allocators.odin @@ -2436,6 +2436,7 @@ compat_allocator_init :: proc(rra: ^Compat_Allocator, allocator := context.alloc rra.parent = allocator } +@(require_results) compat_allocator :: proc(rra: ^Compat_Allocator) -> Allocator { return Allocator{ data = rra, From cdca345d7424c77e151a65e84c638b258f216d50 Mon Sep 17 00:00:00 2001 From: Damian Tarnawski Date: Tue, 2 Sep 2025 13:42:25 +0200 Subject: [PATCH 099/105] Handle optional allocator error when appending read bytes in read_entire_file_from_file --- core/os/os2/file_util.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/os/os2/file_util.odin b/core/os/os2/file_util.odin index 407c38f88..13d6db661 100644 --- a/core/os/os2/file_util.odin +++ b/core/os/os2/file_util.odin @@ -151,7 +151,7 @@ read_entire_file_from_file :: proc(f: ^File, allocator: runtime.Allocator) -> (d n: int n, err = read(f, buffer[:]) total += n - append_elems(&out_buffer, ..buffer[:n]) + append_elems(&out_buffer, ..buffer[:n]) or_return if err != nil { if err == .EOF || err == .Broken_Pipe { err = nil From c01ba419558026fdf11d6029011a530c3e26a4b0 Mon Sep 17 00:00:00 2001 From: smoke-y Date: Fri, 5 Sep 2025 11:02:01 +0530 Subject: [PATCH 100/105] fix empty parentheses seg fault --- src/checker.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/checker.cpp b/src/checker.cpp index 8ea56a4ba..1200af284 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -1797,6 +1797,7 @@ gb_internal void add_type_and_value(CheckerContext *ctx, Ast *expr, AddressingMo } expr = unparen_expr(expr); + if(!expr) break; } mutex_unlock(mutex); } From 5161731ce0bde10695e4186c2530e030403b4d05 Mon Sep 17 00:00:00 2001 From: smoke-y Date: Fri, 5 Sep 2025 11:27:28 +0530 Subject: [PATCH 101/105] proc at type lvl seg fault --- src/check_expr.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 80ec4f78e..b74b0958d 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -7947,10 +7947,12 @@ gb_internal CallArgumentError check_polymorphic_record_type(CheckerContext *c, O s = gb_string_append_fmt(s, "$%.*s", LIT(name)); if (v->kind == Entity_TypeName) { - if (v->type->kind != Type_Generic) { - s = gb_string_append_fmt(s, "="); - s = write_type_to_string(s, v->type, false); - } + if(v->type){ + if (v->type->kind != Type_Generic) { + s = gb_string_append_fmt(s, "="); + s = write_type_to_string(s, v->type, false); + } + }; } else if (v->kind == Entity_Constant) { if (v->Constant.value.kind != ExactValue_Invalid) { s = gb_string_append_fmt(s, "="); From 906eddd1d4ad77cce1a24004a866f3fd736e018e Mon Sep 17 00:00:00 2001 From: smoke-y Date: Fri, 5 Sep 2025 21:28:00 +0530 Subject: [PATCH 102/105] formatting --- src/check_expr.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/check_expr.cpp b/src/check_expr.cpp index b74b0958d..542a2afa1 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -7947,12 +7947,10 @@ gb_internal CallArgumentError check_polymorphic_record_type(CheckerContext *c, O s = gb_string_append_fmt(s, "$%.*s", LIT(name)); if (v->kind == Entity_TypeName) { - if(v->type){ - if (v->type->kind != Type_Generic) { - s = gb_string_append_fmt(s, "="); - s = write_type_to_string(s, v->type, false); - } - }; + if (v->type != nullptr && v->type->kind != Type_Generic) { + s = gb_string_append_fmt(s, "="); + s = write_type_to_string(s, v->type, false); + } } else if (v->kind == Entity_Constant) { if (v->Constant.value.kind != ExactValue_Invalid) { s = gb_string_append_fmt(s, "="); From 5f60e7cdc0f4488e544ecc55e5f306b590c91da7 Mon Sep 17 00:00:00 2001 From: smoke-y Date: Fri, 5 Sep 2025 21:28:49 +0530 Subject: [PATCH 103/105] formatting --- src/checker.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/checker.cpp b/src/checker.cpp index 1200af284..e5dda2aa7 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -1797,7 +1797,9 @@ gb_internal void add_type_and_value(CheckerContext *ctx, Ast *expr, AddressingMo } expr = unparen_expr(expr); - if(!expr) break; + if (expr == nullptr) { + break; + }; } mutex_unlock(mutex); } From a6cd6dc265b8663080a337c2b31b418d72178c86 Mon Sep 17 00:00:00 2001 From: ekliot Date: Fri, 5 Sep 2025 18:45:49 +0100 Subject: [PATCH 104/105] fix CreateMotorJoint param type --- vendor/box2d/box2d.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/box2d/box2d.odin b/vendor/box2d/box2d.odin index 640f430b8..8b0a57a4e 100644 --- a/vendor/box2d/box2d.odin +++ b/vendor/box2d/box2d.odin @@ -1370,7 +1370,7 @@ foreign lib { // Create a motor joint // @see b2MotorJointDef for details - CreateMotorJoint :: proc(worldId: WorldId, def: MotorJointDef) -> JointId --- + CreateMotorJoint :: proc(worldId: WorldId, #by_ptr def: MotorJointDef) -> JointId --- // Set the motor joint linear offset target MotorJoint_SetLinearOffset :: proc(jointId: JointId, linearOffset: Vec2) --- From fe531c18886b1c03d4ddc9d5ee5b1796dbb95436 Mon Sep 17 00:00:00 2001 From: FourteenBrush <74827262+FourteenBrush@users.noreply.github.com> Date: Sun, 7 Sep 2025 20:39:27 +0200 Subject: [PATCH 105/105] Add build tags to `posix/spawn.odin` --- core/sys/posix/spawn.odin | 1 + 1 file changed, 1 insertion(+) diff --git a/core/sys/posix/spawn.odin b/core/sys/posix/spawn.odin index 584201bcf..4eacb3b4b 100644 --- a/core/sys/posix/spawn.odin +++ b/core/sys/posix/spawn.odin @@ -1,3 +1,4 @@ +#+build linux, darwin, openbsd, freebsd, netbsd, haiku package posix when ODIN_OS == .Darwin {