diff --git a/core/crypto/poly1305/poly1305.odin b/core/crypto/poly1305/poly1305.odin index fa57c6c06..4ca4f75e1 100644 --- a/core/crypto/poly1305/poly1305.odin +++ b/core/crypto/poly1305/poly1305.odin @@ -9,6 +9,7 @@ package poly1305 import "core:crypto" import field "core:crypto/_fiat/field_poly1305" import "core:encoding/endian" +import "core:math/bits" import "core:mem" // KEY_SIZE is the Poly1305 key size in bytes. @@ -50,7 +51,7 @@ verify :: proc(tag, msg, key: []byte) -> bool { Context :: struct { _r: field.Tight_Field_Element, _a: field.Tight_Field_Element, - _s: field.Tight_Field_Element, + _s: [2]u64, _buffer: [_BLOCK_SIZE]byte, _leftover: int, _is_initialized: bool, @@ -66,11 +67,12 @@ init :: proc(ctx: ^Context, key: []byte) { // r = le_bytes_to_num(key[0..15]) // r = clamp(r) (r &= 0xffffffc0ffffffc0ffffffc0fffffff) tmp_lo := endian.unchecked_get_u64le(key[0:]) & 0x0ffffffc0fffffff - tmp_hi := endian.unchecked_get_u64le(key[8:]) & 0xffffffc0ffffffc + tmp_hi := endian.unchecked_get_u64le(key[8:]) & 0x0ffffffc0ffffffc field.fe_from_u64s(&ctx._r, tmp_lo, tmp_hi) // s = le_bytes_to_num(key[16..31]) - field.fe_from_bytes(&ctx._s, key[16:32], 0) + ctx._s[0] = endian.unchecked_get_u64le(key[16:]) + ctx._s[1] = endian.unchecked_get_u64le(key[24:]) // a = 0 field.fe_zero(&ctx._a) @@ -138,14 +140,20 @@ final :: proc(ctx: ^Context, dst: []byte) { _blocks(ctx, ctx._buffer[:], true) } - // a += s - field.fe_add(field.fe_relax_cast(&ctx._a), &ctx._a, &ctx._s) // _a unreduced - field.fe_carry(&ctx._a, field.fe_relax_cast(&ctx._a)) // _a reduced - - // return num_to_16_le_bytes(a) + // a += s (NOT mod p) tmp: [32]byte = --- field.fe_to_bytes(&tmp, &ctx._a) - copy_slice(dst, tmp[0:16]) + + c: u64 + lo := endian.unchecked_get_u64le(tmp[0:]) + hi := endian.unchecked_get_u64le(tmp[8:]) + + lo, c = bits.add_u64(lo, ctx._s[0], 0) + hi, _ = bits.add_u64(hi, ctx._s[1], c) + + // return num_to_16_le_bytes(a) + endian.unchecked_put_u64le(dst[0:], lo) + endian.unchecked_put_u64le(dst[8:], hi) } // reset sanitizes the Context. The Context must be re-initialized to diff --git a/core/encoding/hxa/read.odin b/core/encoding/hxa/read.odin index 8a8636f19..f37dc3193 100644 --- a/core/encoding/hxa/read.odin +++ b/core/encoding/hxa/read.odin @@ -177,7 +177,7 @@ read :: proc(data: []byte, filename := "", print_error := false, allocato } defer file.nodes = file.nodes[:node_count] - for node_idx in 0.. max(Node_Type) { diff --git a/core/encoding/json/marshal.odin b/core/encoding/json/marshal.odin index 985de6880..68d087a6e 100644 --- a/core/encoding/json/marshal.odin +++ b/core/encoding/json/marshal.odin @@ -246,7 +246,6 @@ marshal_to_writer :: proc(w: io.Writer, v: any, opt: ^Marshal_Options) -> (err: opt_write_end(w, opt, ']') or_return case runtime.Type_Info_Enumerated_Array: - index := runtime.type_info_base(info.index).variant.(runtime.Type_Info_Enum) opt_write_start(w, opt, '[') or_return for i in 0.. (err: // check for string type { - v := any{key, info.key.id} - ti := runtime.type_info_base(type_info_of(v.id)) - a := any{v.data, ti.id} + kv := any{key, info.key.id} + kti := runtime.type_info_base(type_info_of(kv.id)) + ka := any{kv.data, kti.id} name: string - #partial switch info in ti.variant { + #partial switch info in kti.variant { case runtime.Type_Info_String: - switch s in a { + switch s in ka { case string: name = s case cstring: name = string(s) } @@ -336,13 +335,13 @@ marshal_to_writer :: proc(w: io.Writer, v: any, opt: ^Marshal_Options) -> (err: // check for string type { - v := any{key, info.key.id} - ti := runtime.type_info_base(type_info_of(v.id)) - a := any{v.data, ti.id} + kv := any{key, info.key.id} + kti := runtime.type_info_base(type_info_of(kv.id)) + ka := any{kv.data, kti.id} - #partial switch info in ti.variant { + #partial switch info in kti.variant { case runtime.Type_Info_String: - switch s in a { + switch s in ka { case string: name = s case cstring: name = string(s) } diff --git a/core/encoding/json/unmarshal.odin b/core/encoding/json/unmarshal.odin index 8c21098fb..edc4903a1 100644 --- a/core/encoding/json/unmarshal.odin +++ b/core/encoding/json/unmarshal.odin @@ -483,9 +483,9 @@ unmarshal_object :: proc(p: ^Parser, v: any, end_token: Token_Kind) -> (err: Unm mem.zero_slice(elem_backing) - if err := unmarshal_value(p, map_backing_value); err != nil { + if uerr := unmarshal_value(p, map_backing_value); uerr != nil { delete(key, p.allocator) - return err + return uerr } key_ptr := rawptr(&key) diff --git a/core/image/netpbm/netpbm.odin b/core/image/netpbm/netpbm.odin index 079c5b4be..ab3945ad7 100644 --- a/core/image/netpbm/netpbm.odin +++ b/core/image/netpbm/netpbm.odin @@ -199,8 +199,8 @@ save_to_buffer :: proc(img: ^Image, custom_info: Info = {}, allocator := context for x in 0 ..< img.width { i := y * img.width + x for c in 0 ..< img.channels { - i := i * img.channels + c - fmt.sbprintf(&data, "%i ", pixels[i]) + j := i * img.channels + c + fmt.sbprintf(&data, "%i ", pixels[j]) } fmt.sbprint(&data, "\n") } @@ -213,8 +213,8 @@ save_to_buffer :: proc(img: ^Image, custom_info: Info = {}, allocator := context for x in 0 ..< img.width { i := y * img.width + x for c in 0 ..< img.channels { - i := i * img.channels + c - fmt.sbprintf(&data, "%i ", pixels[i]) + j := i * img.channels + c + fmt.sbprintf(&data, "%i ", pixels[j]) } fmt.sbprint(&data, "\n") } @@ -283,7 +283,7 @@ _parse_header_pnm :: proc(data: []byte) -> (header: Header, length: int, err: Er current_field := 0 current_value := header_fields[0] - parse_loop: for d, i in data[SIG_LENGTH:] { + parse_loop: for d in data[SIG_LENGTH:] { length += 1 // handle comments @@ -728,4 +728,4 @@ _register :: proc() { _ = destroy(img) } image.register(.NetPBM, loader, destroyer) -} \ No newline at end of file +} diff --git a/core/math/fixed/fixed.odin b/core/math/fixed/fixed.odin index b8000a5c6..21fab5faf 100644 --- a/core/math/fixed/fixed.odin +++ b/core/math/fixed/fixed.odin @@ -39,7 +39,6 @@ init_from_f64 :: proc(x: ^$T/Fixed($Backing, $Fraction_Width), val: f64) { } init_from_parts :: proc(x: ^$T/Fixed($Backing, $Fraction_Width), integer, fraction: Backing) { - i, f := math.modf(val) x.i = fraction x.i &= 1< Allocator_Error { - if ptr == nil || allocator.procedure == nil { - return nil - } - _, err := allocator.procedure(allocator.data, .Free, 0, 0, ptr, byte_count, loc) - return err + return runtime.mem_free_with_size(ptr, byte_count, allocator, loc) } free_bytes :: proc(bytes: []byte, allocator := context.allocator, loc := #caller_location) -> Allocator_Error { @@ -130,19 +126,19 @@ query_info :: proc(pointer: rawptr, allocator: Allocator, loc := #caller_locatio delete_string :: proc(str: string, allocator := context.allocator, loc := #caller_location) -> Allocator_Error { - return free_with_size(raw_data(str), len(str), allocator, loc) + return runtime.delete_string(str, allocator, loc) } delete_cstring :: proc(str: cstring, allocator := context.allocator, loc := #caller_location) -> Allocator_Error { - return free((^byte)(str), allocator, loc) + return runtime.delete_cstring(str, allocator, loc) } delete_dynamic_array :: proc(array: $T/[dynamic]$E, loc := #caller_location) -> Allocator_Error { - return free_with_size(raw_data(array), cap(array)*size_of(E), array.allocator, loc) + return runtime.delete_dynamic_array(array, loc) } delete_slice :: proc(array: $T/[]$E, allocator := context.allocator, loc := #caller_location) -> Allocator_Error { - return free_with_size(raw_data(array), len(array)*size_of(E), allocator, loc) + return runtime.delete_slice(array, allocator, loc) } delete_map :: proc(m: $T/map[$K]$V, loc := #caller_location) -> Allocator_Error { - return runtime.map_free_dynamic(transmute(Raw_Map)m, runtime.map_info(T), loc) + return runtime.delete_map(m, loc) } @@ -161,71 +157,40 @@ new :: proc($T: typeid, allocator := context.allocator, loc := #caller_location) } @(require_results) new_aligned :: proc($T: typeid, alignment: int, allocator := context.allocator, loc := #caller_location) -> (t: ^T, err: Allocator_Error) { - data := alloc_bytes(size_of(T), alignment, allocator, loc) or_return - t = (^T)(raw_data(data)) - return + return runtime.new_aligned(T, alignment, allocator, loc) } @(require_results) new_clone :: proc(data: $T, allocator := context.allocator, loc := #caller_location) -> (t: ^T, err: Allocator_Error) { - backing := alloc_bytes(size_of(T), align_of(T), allocator, loc) or_return - t = (^T)(raw_data(backing)) - if t != nil { - t^ = data - return t, nil - } - return nil, .Out_Of_Memory + return runtime.new_clone(data, allocator, loc) } @(require_results) make_aligned :: proc($T: typeid/[]$E, #any_int len: int, alignment: int, allocator := context.allocator, loc := #caller_location) -> (slice: T, err: Allocator_Error) { - runtime.make_slice_error_loc(loc, len) - data := alloc_bytes(size_of(E)*len, alignment, allocator, loc) or_return - if data == nil && size_of(E) != 0 { - return - } - slice = transmute(T)Raw_Slice{raw_data(data), len} - return + return runtime.make_aligned(T, len, alignment, allocator, loc) } @(require_results) make_slice :: proc($T: typeid/[]$E, #any_int len: int, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) { - return make_aligned(T, len, align_of(E), allocator, loc) + return runtime.make_slice(T, len, allocator, loc) } @(require_results) make_dynamic_array :: proc($T: typeid/[dynamic]$E, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) { - return make_dynamic_array_len_cap(T, 0, 16, allocator, loc) + return runtime.make_dynamic_array(T, allocator, loc) } @(require_results) make_dynamic_array_len :: proc($T: typeid/[dynamic]$E, #any_int len: int, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) { - return make_dynamic_array_len_cap(T, len, len, allocator, loc) + return runtime.make_dynamic_array(T, len, allocator, loc) } @(require_results) make_dynamic_array_len_cap :: proc($T: typeid/[dynamic]$E, #any_int len: int, #any_int cap: int, allocator := context.allocator, loc := #caller_location) -> (array: T, err: Allocator_Error) { - runtime.make_dynamic_array_error_loc(loc, len, cap) - data := alloc_bytes(size_of(E)*cap, align_of(E), allocator, loc) or_return - s := Raw_Dynamic_Array{raw_data(data), len, cap, allocator} - if data == nil && size_of(E) != 0 { - s.len, s.cap = 0, 0 - } - array = transmute(T)s - return + return runtime.make_dynamic_array(T, len, cap, allocator, loc) } @(require_results) make_map :: proc($T: typeid/map[$K]$E, #any_int cap: int = 1< (m: T, err: Allocator_Error) { - runtime.make_map_expr_error_loc(loc, cap) - context.allocator = allocator - - err = reserve_map(&m, cap, loc) - return + return runtime.make_map(T, cap, allocator, loc) } @(require_results) make_multi_pointer :: proc($T: typeid/[^]$E, #any_int len: int, allocator := context.allocator, loc := #caller_location) -> (mp: T, err: Allocator_Error) { - runtime.make_slice_error_loc(loc, len) - data := alloc_bytes(size_of(E)*len, align_of(E), allocator, loc) or_return - if data == nil && size_of(E) != 0 { - return - } - mp = cast(T)raw_data(data) - return + return runtime.make_multi_pointer(T, len, allocator, loc) } make :: proc{ diff --git a/core/mem/mem.odin b/core/mem/mem.odin index 0ea9d5b79..d423cc1eb 100644 --- a/core/mem/mem.odin +++ b/core/mem/mem.odin @@ -45,6 +45,8 @@ copy_non_overlapping :: proc "contextless" (dst, src: rawptr, len: int) -> rawpt intrinsics.mem_copy_non_overlapping(dst, src, len) return dst } + +@(require_results) compare :: proc "contextless" (a, b: []byte) -> int { res := compare_byte_ptrs(raw_data(a), raw_data(b), min(len(a), len(b))) if res == 0 && len(a) != len(b) { diff --git a/core/net/addr.odin b/core/net/addr.odin index 508399bf4..c01724d99 100644 --- a/core/net/addr.odin +++ b/core/net/addr.odin @@ -119,9 +119,9 @@ aton :: proc(address_and_maybe_port: string, family: Address_Family, allow_decim } a: [4]u8 = --- - for v, i in buf { + for v, j in buf { if v > 255 { return {}, false } - a[i] = u8(v) + a[j] = u8(v) } return IP4_Address(a), true diff --git a/core/net/dns.odin b/core/net/dns.odin index c556450c6..48cd8bf29 100644 --- a/core/net/dns.odin +++ b/core/net/dns.odin @@ -816,7 +816,6 @@ parse_response :: proc(response: []u8, filter: DNS_Record_Type = nil, allocator dq_sz :: 4 hn_sz := skip_hostname(response, cur_idx) or_return - dns_query := mem.slice_data_cast([]u16be, response[cur_idx+hn_sz:cur_idx+hn_sz+dq_sz]) cur_idx += hn_sz + dq_sz } diff --git a/core/net/dns_windows.odin b/core/net/dns_windows.odin index e54b067b6..ccec7ea4b 100644 --- a/core/net/dns_windows.odin +++ b/core/net/dns_windows.odin @@ -85,11 +85,9 @@ _get_dns_records_os :: proc(hostname: string, type: DNS_Record_Type, allocator : append(&recs, record) case .CNAME: - - hostname := strings.clone(string(r.Data.CNAME)) record := DNS_Record_CNAME{ base = base_record, - host_name = hostname, + host_name = strings.clone(string(r.Data.CNAME)), } append(&recs, record) @@ -107,10 +105,9 @@ _get_dns_records_os :: proc(hostname: string, type: DNS_Record_Type, allocator : } case .NS: - hostname := strings.clone(string(r.Data.NS)) record := DNS_Record_NS{ base = base_record, - host_name = hostname, + host_name = strings.clone(string(r.Data.NS)), } append(&recs, record) diff --git a/core/net/socket.odin b/core/net/socket.odin index 1bfa52257..5f137401e 100644 --- a/core/net/socket.odin +++ b/core/net/socket.odin @@ -161,11 +161,10 @@ recv_any :: proc(socket: Any_Socket, buf: []byte) -> ( ) { switch socktype in socket { case TCP_Socket: - bytes_read, err := recv_tcp(socktype, buf) - return bytes_read, nil, err + bytes_read, err = recv_tcp(socktype, buf) + return case UDP_Socket: - bytes_read, endpoint, err := recv_udp(socktype, buf) - return bytes_read, endpoint, err + return recv_udp(socktype, buf) case: panic("Not supported") } } diff --git a/core/odin/doc-format/doc_format.odin b/core/odin/doc-format/doc_format.odin index f8e23d53a..c2d86a0ba 100644 --- a/core/odin/doc-format/doc_format.odin +++ b/core/odin/doc-format/doc_format.odin @@ -249,7 +249,6 @@ Type :: struct { // .Bit_Set - <=2 types: 0=element type, 1=underlying type (Underlying_Type flag will be set) // .Simd_Vector - 1 type: 0=element // .Relative_Pointer - 2 types: 0=pointer type, 1=base integer - // .Relative_Slice - 2 types: 0=slice type, 1=base integer // .Multi_Pointer - 1 type: 0=element // .Matrix - 1 type: 0=element // .Soa_Pointer - 1 type: 0=element diff --git a/core/odin/printer/printer.odin b/core/odin/printer/printer.odin index 63a3b543d..ce75352bd 100644 --- a/core/odin/printer/printer.odin +++ b/core/odin/printer/printer.odin @@ -643,7 +643,7 @@ align_switch_stmt :: proc(p: ^Printer, index: int) { format_tokens := make([dynamic]TokenAndLength, 0, brace_token.parameter_count, context.temp_allocator) //find all the switch cases that are one lined - for line, line_index in p.lines[brace_line + 1:] { + for line in p.lines[brace_line + 1:] { case_found := false colon_found := false @@ -716,7 +716,7 @@ align_enum :: proc(p: ^Printer, index: int) { format_tokens := make([dynamic]TokenAndLength, 0, brace_token.parameter_count, context.temp_allocator) - for line, line_index in p.lines[brace_line + 1:] { + for line in p.lines[brace_line + 1:] { length := 0 for format_token, i in line.format_tokens { @@ -880,7 +880,7 @@ align_comments :: proc(p: ^Printer) { length := 0 - for format_token, i in line.format_tokens { + for format_token in line.format_tokens { if format_token.kind == .Comment { current_info.length = max(current_info.length, length) current_info.end = line_index diff --git a/core/odin/printer/visit.odin b/core/odin/printer/visit.odin index 1aefcf967..7dd208a49 100644 --- a/core/odin/printer/visit.odin +++ b/core/odin/printer/visit.odin @@ -1462,9 +1462,9 @@ visit_binary_expr :: proc(p: ^Printer, binary: ^ast.Binary_Expr) { } either_implicit_selector := false - if _, ok := binary.left.derived.(^ast.Implicit_Selector_Expr); ok { + if _, lok := binary.left.derived.(^ast.Implicit_Selector_Expr); lok { either_implicit_selector = true - } else if _, ok := binary.right.derived.(^ast.Implicit_Selector_Expr); ok { + } else if _, rok := binary.right.derived.(^ast.Implicit_Selector_Expr); rok { either_implicit_selector = true } diff --git a/core/os/os2/errors.odin b/core/os/os2/errors.odin index 426375a5a..d76b2d549 100644 --- a/core/os/os2/errors.odin +++ b/core/os/os2/errors.odin @@ -13,6 +13,12 @@ General_Error :: enum u32 { Timeout, + Broken_Pipe, + + // Indicates that an attempt to retrieve a file's size was made, but the + // file doesn't have a size. + No_Size, + Invalid_File, Invalid_Dir, Invalid_Path, @@ -51,6 +57,8 @@ error_string :: proc(ferr: Error) -> string { case .Not_Exist: return "file does not exist" case .Closed: return "file already closed" case .Timeout: return "i/o timeout" + case .Broken_Pipe: return "Broken pipe" + case .No_Size: return "file has no definite size" case .Invalid_File: return "invalid file" case .Invalid_Dir: return "invalid directory" case .Invalid_Path: return "invalid path" diff --git a/core/os/os2/file_util.odin b/core/os/os2/file_util.odin index 459544fc0..0708f708e 100644 --- a/core/os/os2/file_util.odin +++ b/core/os/os2/file_util.odin @@ -87,26 +87,50 @@ read_entire_file_from_path :: proc(name: string, allocator: runtime.Allocator) - read_entire_file_from_file :: proc(f: ^File, allocator: runtime.Allocator) -> (data: []byte, err: Error) { size: int + has_size := true if size64, err := file_size(f); err == nil { if i64(int(size64)) != size64 { size = int(size64) } + } else if err == .No_Size { + has_size = false + } else { + return } size += 1 // for EOF // TODO(bill): Is this correct logic? - total: int - data = make([]byte, size, allocator) or_return - for { - n: int - n, err = read(f, data[total:]) - total += n - if err != nil { - if err == .EOF { - err = nil + if has_size { + total: int + data = make([]byte, size, allocator) or_return + for { + n: int + n, err = read(f, data[total:]) + total += n + if err != nil { + if err == .EOF { + err = nil + } + data = data[:total] + return + } + } + } else { + buffer: [1024]u8 + out_buffer := make([dynamic]u8, 0, 0, allocator) + total := 0 + for { + n: int = --- + n, err = read(f, buffer[:]) + total += n + append_elems(&out_buffer, ..buffer[:total]) + if err != nil { + if err == .EOF || err == .Broken_Pipe { + err = nil + } + data = out_buffer[:total] + return } - data = data[:total] - return } } } diff --git a/core/os/os2/file_windows.odin b/core/os/os2/file_windows.odin index 8cb040a0a..fc3cebaea 100644 --- a/core/os/os2/file_windows.odin +++ b/core/os/os2/file_windows.odin @@ -434,6 +434,9 @@ _write_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: i64, err: Error) { _file_size :: proc(f: ^File) -> (n: i64, err: Error) { length: win32.LARGE_INTEGER + if f.impl.kind == .Pipe { + return 0, .No_Size + } handle := _handle(f) if !win32.GetFileSizeEx(handle, &length) { err = _get_platform_error() @@ -766,7 +769,6 @@ _is_dir :: proc(path: string) -> bool { _file_stream_proc :: proc(stream_data: rawptr, mode: io.Stream_Mode, p: []byte, offset: i64, whence: io.Seek_From) -> (n: i64, err: io.Error) { f := (^File)(stream_data) ferr: Error - i: int switch mode { case .Read: n, ferr = _read(f, p) diff --git a/core/os/os_darwin.odin b/core/os/os_darwin.odin index 43e0efc0a..716397475 100644 --- a/core/os/os_darwin.odin +++ b/core/os/os_darwin.odin @@ -456,6 +456,7 @@ foreign libc { @(link_name="fstat64") _unix_fstat :: proc(fd: Handle, stat: ^OS_Stat) -> c.int --- @(link_name="readlink") _unix_readlink :: proc(path: cstring, buf: ^byte, bufsiz: c.size_t) -> c.ssize_t --- @(link_name="access") _unix_access :: proc(path: cstring, mask: int) -> int --- + @(link_name="fsync") _unix_fsync :: proc(handle: Handle) -> c.int --- @(link_name="fdopendir$INODE64") _unix_fdopendir_amd64 :: proc(fd: Handle) -> Dir --- @(link_name="readdir_r$INODE64") _unix_readdir_r_amd64 :: proc(dirp: Dir, entry: ^Dirent, result: ^^Dirent) -> c.int --- @@ -565,8 +566,8 @@ fchmod :: proc(fd: Handle, mode: u16) -> Errno { return cast(Errno)_unix_fchmod(fd, mode) } -close :: proc(fd: Handle) -> bool { - return _unix_close(fd) == 0 +close :: proc(fd: Handle) -> Errno { + return cast(Errno)_unix_close(fd) } // If you read or write more than `SSIZE_MAX` bytes, most darwin implementations will return `EINVAL` @@ -894,6 +895,10 @@ access :: proc(path: string, mask: int) -> bool { return _unix_access(cstr, mask) == 0 } +flush :: proc(fd: Handle) -> Errno { + return cast(Errno)_unix_fsync(fd) +} + lookup_env :: proc(key: string, allocator := context.allocator) -> (value: string, found: bool) { runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD(ignore = context.temp_allocator == allocator) path_str := strings.clone_to_cstring(key, context.temp_allocator) diff --git a/core/strconv/strconv.odin b/core/strconv/strconv.odin index eae9f9504..f23e619dc 100644 --- a/core/strconv/strconv.odin +++ b/core/strconv/strconv.odin @@ -878,7 +878,7 @@ parse_f64_prefix :: proc(str: string) -> (value: f64, nr: int, ok: bool) { s = s[1:] fallthrough case 'i', 'I': - n := common_prefix_len_ignore_case(s, "infinity") + n = common_prefix_len_ignore_case(s, "infinity") if 3 < n && n < 8 { // "inf" or "infinity" n = 3 } diff --git a/core/strings/strings.odin b/core/strings/strings.odin index 5cee25a66..13c53f48e 100644 --- a/core/strings/strings.odin +++ b/core/strings/strings.odin @@ -809,7 +809,7 @@ _split :: proc(s_, sep: string, sep_save, n_: int, allocator := context.allocato n = l } - res := make([]string, n, allocator, loc) or_return + res = make([]string, n, allocator, loc) or_return for i := 0; i < n-1; i += 1 { _, w := utf8.decode_rune_in_string(s) res[i] = s[:w] diff --git a/core/sys/info/platform_linux.odin b/core/sys/info/platform_linux.odin index 93770a460..89b1204a7 100644 --- a/core/sys/info/platform_linux.odin +++ b/core/sys/info/platform_linux.odin @@ -18,8 +18,8 @@ init_os_version :: proc () { fd, errno := linux.open("/etc/os-release", {.RDONLY}, {}) assert(errno == .NONE, "Failed to read /etc/os-release") defer { - errno := linux.close(fd) - assert(errno == .NONE, "Failed to close the file descriptor") + cerrno := linux.close(fd) + assert(cerrno == .NONE, "Failed to close the file descriptor") } os_release_buf: [2048]u8 n, read_errno := linux.read(fd, os_release_buf[:]) diff --git a/core/sys/linux/constants.odin b/core/sys/linux/constants.odin index 6294602e9..51f7db68f 100644 --- a/core/sys/linux/constants.odin +++ b/core/sys/linux/constants.odin @@ -1,4 +1,3 @@ - package linux /* diff --git a/core/sys/windows/kernel32.odin b/core/sys/windows/kernel32.odin index 952d5bb31..10cc80041 100644 --- a/core/sys/windows/kernel32.odin +++ b/core/sys/windows/kernel32.odin @@ -324,6 +324,7 @@ foreign kernel32 { lpName: LPCWSTR, ) -> HANDLE --- ResetEvent :: proc(hEvent: HANDLE) -> BOOL --- + SetEvent :: proc(hEvent: HANDLE) -> BOOL --- WaitForMultipleObjects :: proc( nCount: DWORD, lpHandles: ^HANDLE, @@ -545,6 +546,10 @@ FILE_MAP_RESERVE :: DWORD(0x80000000) FILE_MAP_TARGETS_INVALID :: DWORD(0x40000000) FILE_MAP_LARGE_PAGES :: DWORD(0x20000000) +// Flags for `SetFileCompletionNotificationModes`. +FILE_SKIP_COMPLETION_PORT_ON_SUCCESS :: 0x1 +FILE_SKIP_SET_EVENT_ON_HANDLE :: 0x2 + PAGE_NOACCESS :: 0x01 PAGE_READONLY :: 0x02 PAGE_READWRITE :: 0x04 diff --git a/core/sys/windows/ole32.odin b/core/sys/windows/ole32.odin index 6fa398d46..d344db5f0 100644 --- a/core/sys/windows/ole32.odin +++ b/core/sys/windows/ole32.odin @@ -3,9 +3,24 @@ package sys_windows foreign import "system:Ole32.lib" //objbase.h +// Note(Dragos): https://learn.microsoft.com/en-us/windows/win32/api/objbase/ne-objbase-coinit makes you believe that MULTITHREADED == 3. That is wrong. See definition of objbase.h +/* +typedef enum tagCOINIT +{ + COINIT_APARTMENTTHREADED = 0x2, // Apartment model + +#if (_WIN32_WINNT >= 0x0400 ) || defined(_WIN32_DCOM) // DCOM + // These constants are only valid on Windows NT 4.0 + COINIT_MULTITHREADED = COINITBASE_MULTITHREADED, + COINIT_DISABLE_OLE1DDE = 0x4, // Don't use DDE for Ole1 support. + COINIT_SPEED_OVER_MEMORY = 0x8, // Trade memory for speed. +#endif // DCOM +} COINIT; +*/ +// Where COINITBASE_MULTITHREADED == 0x00 COINIT :: enum DWORD { APARTMENTTHREADED = 0x2, - MULTITHREADED, + MULTITHREADED = 0, DISABLE_OLE1DDE = 0x4, SPEED_OVER_MEMORY = 0x8, } diff --git a/core/sys/windows/ws2_32.odin b/core/sys/windows/ws2_32.odin index c60a21a36..e9bf8abc9 100644 --- a/core/sys/windows/ws2_32.odin +++ b/core/sys/windows/ws2_32.odin @@ -2,12 +2,12 @@ package sys_windows // Define flags to be used with the WSAAsyncSelect() call. -FD_READ :: 0x01 -FD_WRITE :: 0x02 -FD_OOB :: 0x04 -FD_ACCEPT :: 0x08 -FD_CONNECT :: 0x10 -FD_CLOSE :: 0x20 +FD_READ :: 0x01 +FD_WRITE :: 0x02 +FD_OOB :: 0x04 +FD_ACCEPT :: 0x08 +FD_CONNECT :: 0x10 +FD_CLOSE :: 0x20 FD_MAX_EVENTS :: 10 INADDR_LOOPBACK :: 0x7f000001 @@ -24,10 +24,10 @@ POLLERR :: 0x0001 POLLHUP :: 0x0002 POLLNVAL :: 0x0004 -WSA_POLLFD::struct{ - fd:SOCKET, - events:c_short, - revents:c_short, +WSA_POLLFD :: struct{ + fd: SOCKET, + events: c_short, + revents: c_short, } WSANETWORKEVENTS :: struct { @@ -37,16 +37,43 @@ WSANETWORKEVENTS :: struct { WSAEVENT :: HANDLE -WSAID_ACCEPTEX :: GUID{0xb5367df1, 0xcbac, 0x11cf, {0x95, 0xca, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}} +WSAID_ACCEPTEX :: GUID{0xb5367df1, 0xcbac, 0x11cf, {0x95, 0xca, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}} WSAID_GETACCEPTEXSOCKADDRS :: GUID{0xb5367df2, 0xcbac, 0x11cf, {0x95, 0xca, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92}} +WSAID_CONNECTX :: GUID{0x25a207b9, 0xddf3, 0x4660, {0x8e, 0xe9, 0x76, 0xe5, 0x8c, 0x74, 0x06, 0x3e}} + SIO_GET_EXTENSION_FUNCTION_POINTER :: IOC_INOUT | IOC_WS2 | 6 -IOC_OUT :: 0x40000000 -IOC_IN :: 0x80000000 + +IOC_OUT :: 0x40000000 +IOC_IN :: 0x80000000 IOC_INOUT :: (IOC_IN | IOC_OUT) -IOC_WS2 :: 0x08000000 +IOC_WS2 :: 0x08000000 + +SO_UPDATE_ACCEPT_CONTEXT :: 28683 + +LPFN_CONNECTEX :: #type proc "system" ( + s: SOCKET, + sockaddr: ^SOCKADDR_STORAGE_LH, + namelen: c_int, + lpSendBuffer: PVOID, + dwSendDataLength: DWORD, + lpdwBytesSent: LPDWORD, + lpOverlapped: LPOVERLAPPED, +) -> BOOL + +LPFN_ACCEPTEX :: #type proc "system" ( + sListenSocket: SOCKET, + sAcceptSocket: SOCKET, + lpOutputBuffer: PVOID, + dwReceiveDataLength: DWORD, + dwLocalAddressLength: DWORD, + dwRemoteAddressLength: DWORD, + lpdwBytesReceived: LPDWORD, + lpOverlapped: LPOVERLAPPED, +) -> BOOL + /* Example Load: - load_accept_ex :: proc(listener: SOCKET, fn_acceptex: rawptr) { + load_accept_ex :: proc(listener: SOCKET, fn_acceptex: ^LPFN_ACCEPTEX) { bytes: u32 guid_accept_ex := WSAID_ACCEPTEX rc := WSAIoctl(listener, SIO_GET_EXTENSION_FUNCTION_POINTER, &guid_accept_ex, size_of(guid_accept_ex), diff --git a/core/text/i18n/qt_linguist.odin b/core/text/i18n/qt_linguist.odin index fa05a6dc1..0e75df873 100644 --- a/core/text/i18n/qt_linguist.odin +++ b/core/text/i18n/qt_linguist.odin @@ -128,7 +128,7 @@ parse_qt_linguist_from_bytes :: proc(data: []byte, options := DEFAULT_PARSE_OPTI num_plurals: int for { - numerus_id := xml.find_child_by_ident(ts, translation_id, "numerusform", num_plurals) or_break + xml.find_child_by_ident(ts, translation_id, "numerusform", num_plurals) or_break num_plurals += 1 } diff --git a/core/unicode/utf8/utf8.odin b/core/unicode/utf8/utf8.odin index 3642b8078..67f8a8be9 100644 --- a/core/unicode/utf8/utf8.odin +++ b/core/unicode/utf8/utf8.odin @@ -45,18 +45,18 @@ accept_ranges := [5]Accept_Range{ {0x80, 0x8f}, } -accept_sizes := [256]u8{ - 0x00..=0x7f = 0xf0, - 0x80..=0xc1 = 0xf1, - 0xc2..=0xdf = 0x02, - 0xe0 = 0x13, - 0xe1..=0xec = 0x03, - 0xed = 0x23, - 0xee..=0xef = 0x03, - 0xf0 = 0x34, - 0xf1..=0xf3 = 0x04, - 0xf4 = 0x44, - 0xf5..=0xff = 0xf1, +accept_sizes := [256]u8{ + 0x00..=0x7f = 0xf0, // ascii, size 1 + 0x80..=0xc1 = 0xf1, // invalid, size 1 + 0xc2..=0xdf = 0x02, // accept 1, size 2 + 0xe0 = 0x13, // accept 1, size 3 + 0xe1..=0xec = 0x03, // accept 0, size 3 + 0xed = 0x23, // accept 2, size 3 + 0xee..=0xef = 0x03, // accept 0, size 3 + 0xf0 = 0x34, // accept 3, size 4 + 0xf1..=0xf3 = 0x04, // accept 0, size 4 + 0xf4 = 0x44, // accept 4, size 4 + 0xf5..=0xff = 0xf1, // ascii, size 1 } encode_rune :: proc "contextless" (c: rune) -> ([4]u8, int) { @@ -385,7 +385,7 @@ full_rune_in_bytes :: proc "contextless" (b: []byte) -> bool { if n == 0 { return false } - x := _first[b[0]] + x := accept_sizes[b[0]] if n >= int(x & 7) { return true } @@ -403,18 +403,3 @@ full_rune_in_bytes :: proc "contextless" (b: []byte) -> bool { full_rune_in_string :: proc "contextless" (s: string) -> bool { return full_rune_in_bytes(transmute([]byte)s) } - - -_first := [256]u8{ - 0x00..=0x7f = 0xf0, // ascii, size 1 - 0x80..=0xc1 = 0xf1, // invalid, size 1 - 0xc2..=0xdf = 0x02, // accept 1, size 2 - 0xe0 = 0x13, // accept 1, size 3 - 0xe1..=0xec = 0x03, // accept 0, size 3 - 0xed = 0x23, // accept 2, size 3 - 0xee..=0xef = 0x03, // accept 0, size 3 - 0xf0 = 0x34, // accept 3, size 4 - 0xf1..=0xf3 = 0x04, // accept 0, size 4 - 0xf4 = 0x44, // accept 4, size 4 - 0xf5..=0xff = 0xf1, // ascii, size 1 -} diff --git a/src/build_settings.cpp b/src/build_settings.cpp index 1ac9e451f..30d6f0b3c 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -412,7 +412,9 @@ struct BuildContext { bool dynamic_map_calls; - bool obfuscate_source_code_locations; + bool obfuscate_source_code_locations; + + bool min_link_libs; RelocMode reloc_mode; bool disable_red_zone; @@ -519,7 +521,7 @@ gb_global TargetMetrics target_darwin_amd64 = { gb_global TargetMetrics target_darwin_arm64 = { TargetOs_darwin, TargetArch_arm64, - 8, 8, 8, 16, + 8, 8, 16, 16, str_lit("arm64-apple-macosx"), // NOTE: Changes during initialization based on build flags. str_lit("e-m:o-i64:64-i128:128-n32:64-S128"), }; diff --git a/src/check_expr.cpp b/src/check_expr.cpp index c7a1b460a..c80b08695 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -2428,7 +2428,7 @@ gb_internal void check_old_for_or_switch_value_usage(Ast *expr) { if ((e->flags & EntityFlag_ForValue) != 0) { Type *parent_type = type_deref(e->Variable.for_loop_parent_type); - error(expr, "Assuming a for-in defined value is addressable as the iterable is passed by value has been disallowed with '-strict-style'."); + error(expr, "Assuming a for-in defined value is addressable as the iterable is passed by value has been disallowed."); if (is_type_map(parent_type)) { error_line("\tSuggestion: Prefer doing 'for key, &%.*s in ...'\n", LIT(e->token.string)); @@ -2438,7 +2438,7 @@ gb_internal void check_old_for_or_switch_value_usage(Ast *expr) { } else { GB_ASSERT((e->flags & EntityFlag_SwitchValue) != 0); - error(expr, "Assuming a switch-in defined value is addressable as the iterable is passed by value has been disallowed with '-strict-style'."); + error(expr, "Assuming a switch-in defined value is addressable as the iterable is passed by value has been disallowed."); error_line("\tSuggestion: Prefer doing 'switch &%.*s in ...'\n", LIT(e->token.string)); } } @@ -4129,7 +4129,7 @@ gb_internal void update_untyped_expr_value(CheckerContext *c, Ast *e, ExactValue } } -gb_internal void convert_untyped_error(CheckerContext *c, Operand *operand, Type *target_type) { +gb_internal void convert_untyped_error(CheckerContext *c, Operand *operand, Type *target_type, bool ignore_error_block=false) { gbString expr_str = expr_to_string(operand->expr); gbString type_str = type_to_string(target_type); gbString from_type_str = type_to_string(operand->type); @@ -4143,7 +4143,9 @@ gb_internal void convert_untyped_error(CheckerContext *c, Operand *operand, Type } } } - ERROR_BLOCK(); + if (!ignore_error_block) { + begin_error_block(); + } error(operand->expr, "Cannot convert untyped value '%s' to '%s' from '%s'%s", expr_str, type_str, from_type_str, extra_text); if (operand->value.kind == ExactValue_String) { @@ -4158,6 +4160,11 @@ gb_internal void convert_untyped_error(CheckerContext *c, Operand *operand, Type gb_string_free(type_str); gb_string_free(expr_str); operand->mode = Addressing_Invalid; + + if (!ignore_error_block) { + end_error_block(); + } + } gb_internal ExactValue convert_exact_value_for_type(ExactValue v, Type *type) { @@ -4287,7 +4294,7 @@ gb_internal void convert_to_typed(CheckerContext *c, Operand *operand, Type *tar operand->mode = Addressing_Invalid; ERROR_BLOCK(); - convert_untyped_error(c, operand, target_type); + convert_untyped_error(c, operand, target_type, true); error_line("\tNote: Only a square matrix types can be initialized with a scalar value\n"); return; } else { @@ -4350,7 +4357,7 @@ gb_internal void convert_to_typed(CheckerContext *c, Operand *operand, Type *tar GB_ASSERT(first_success_index >= 0); operand->mode = Addressing_Invalid; - convert_untyped_error(c, operand, target_type); + convert_untyped_error(c, operand, target_type, true); error_line("Ambiguous type conversion to '%s', which variant did you mean:\n\t", type_str); i32 j = 0; @@ -4375,9 +4382,10 @@ gb_internal void convert_to_typed(CheckerContext *c, Operand *operand, Type *tar ERROR_BLOCK(); operand->mode = Addressing_Invalid; - convert_untyped_error(c, operand, target_type); + convert_untyped_error(c, operand, target_type, true); if (count > 0) { error_line("'%s' is a union which only excepts the following types:\n", type_str); + error_line("\t"); for (i32 i = 0; i < count; i++) { Type *v = t->Union.variants[i]; diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index 1d7e7d4e9..fc3b9aa43 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -740,6 +740,25 @@ gb_internal bool check_using_stmt_entity(CheckerContext *ctx, AstUsingStmt *us, return true; } +gb_internal void error_var_decl_identifier(Ast *name) { + GB_ASSERT(name != nullptr); + GB_ASSERT(name->kind != Ast_Ident); + + ERROR_BLOCK(); + gbString s = expr_to_string(name); + defer (gb_string_free(s)); + + error(name, "A variable declaration must be an identifier, got '%s'", s); + if (name->kind == Ast_Implicit) { + String imp = name->Implicit.string; + if (imp == "context") { + error_line("\tSuggestion: '%.*s' is a reserved keyword, would 'ctx' suffice?\n", LIT(imp)); + } else { + error_line("\tNote: '%.*s' is a reserved keyword\n", LIT(imp)); + } + } +} + gb_internal void check_inline_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) { ast_node(irs, UnrollRangeStmt, node); check_open_scope(ctx, node); @@ -851,7 +870,7 @@ gb_internal void check_inline_range_stmt(CheckerContext *ctx, Ast *node, u32 mod entity = found; } } else { - error(name, "A variable declaration must be an identifier"); + error_var_decl_identifier(name); } if (entity == nullptr) { @@ -1479,6 +1498,7 @@ gb_internal void check_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) auto vals = array_make(temporary_allocator(), 0, 2); auto entities = array_make(temporary_allocator(), 0, 2); bool is_map = false; + bool is_bit_set = false; bool use_by_reference_for_value = false; bool is_soa = false; bool is_reverse = rs->reverse; @@ -1524,6 +1544,9 @@ gb_internal void check_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) array_add(&vals, operand.type); array_add(&vals, t_int); add_type_info_type(ctx, operand.type); + if (build_context.no_rtti) { + error(node, "Iteration over an enum type is not allowed runtime type information (RTTI) has been disallowed"); + } goto skip_expr_range_stmt; } } else if (operand.mode != Addressing_Invalid) { @@ -1554,6 +1577,17 @@ gb_internal void check_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) } break; + case Type_BitSet: + array_add(&vals, t->BitSet.elem); + max_val_count = 1; + is_bit_set = true; + is_possibly_addressable = false; + add_type_info_type(ctx, operand.type); + if (build_context.no_rtti && is_type_enum(t->BitSet.elem)) { + error(node, "Iteration over a bit_set of an enum is not allowed runtime type information (RTTI) has been disallowed"); + } + break; + case Type_EnumeratedArray: if (is_ptr) use_by_reference_for_value = true; array_add(&vals, t->EnumeratedArray.elem); @@ -1709,7 +1743,7 @@ gb_internal void check_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) if (is_possibly_addressable && i == addressable_index) { entity->flags &= ~EntityFlag_Value; } else { - char const *idx_name = is_map ? "key" : "index"; + char const *idx_name = is_map ? "key" : is_bit_set ? "element" : "index"; error(token, "The %s variable '%.*s' cannot be made addressable", idx_name, LIT(str)); } } else if (i == addressable_index && use_by_reference_for_value) { @@ -1732,9 +1766,7 @@ gb_internal void check_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) entity = found; } } else { - gbString s = expr_to_string(lhs[i]); - error(name, "A variable declaration must be an identifier, got %s", s); - gb_string_free(s); + error_var_decl_identifier(name); } if (entity == nullptr) { @@ -1786,7 +1818,7 @@ gb_internal void check_value_decl_stmt(CheckerContext *ctx, Ast *node, u32 mod_f for (Ast *name : vd->names) { Entity *entity = nullptr; if (name->kind != Ast_Ident) { - error(name, "A variable declaration must be an identifier"); + error_var_decl_identifier(name); } else { Token token = name->Ident.token; String str = token.string; @@ -2043,13 +2075,13 @@ gb_internal void check_expr_stmt(CheckerContext *ctx, Ast *node) { } Ast *expr = strip_or_return_expr(operand.expr); - if (expr->kind == Ast_CallExpr) { + if (expr && expr->kind == Ast_CallExpr) { BuiltinProcId builtin_id = BuiltinProc_Invalid; bool do_require = false; AstCallExpr *ce = &expr->CallExpr; Type *t = base_type(type_of_expr(ce->proc)); - if (t->kind == Type_Proc) { + if (t && t->kind == Type_Proc) { do_require = t->Proc.require_results; } else if (check_stmt_internal_builtin_proc_id(ce->proc, &builtin_id)) { auto const &bp = builtin_procs[builtin_id]; @@ -2061,7 +2093,7 @@ gb_internal void check_expr_stmt(CheckerContext *ctx, Ast *node) { gb_string_free(expr_str); } return; - } else if (expr->kind == Ast_SelectorCallExpr) { + } else if (expr && expr->kind == Ast_SelectorCallExpr) { BuiltinProcId builtin_id = BuiltinProc_Invalid; bool do_require = false; diff --git a/src/check_type.cpp b/src/check_type.cpp index 609b73229..81e67f261 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -790,6 +790,9 @@ gb_internal void check_enum_type(CheckerContext *ctx, Type *enum_type, Type *nam ast_node(et, EnumType, node); GB_ASSERT(is_type_enum(enum_type)); + enum_type->Enum.base_type = t_int; + enum_type->Enum.scope = ctx->scope; + Type *base_type = t_int; if (et->base_type != nullptr) { base_type = check_type(ctx, et->base_type); @@ -811,7 +814,6 @@ gb_internal void check_enum_type(CheckerContext *ctx, Type *enum_type, Type *nam // NOTE(bill): Must be up here for the 'check_init_constant' system enum_type->Enum.base_type = base_type; - enum_type->Enum.scope = ctx->scope; auto fields = array_make(permanent_allocator(), 0, et->fields.count); diff --git a/src/checker.cpp b/src/checker.cpp index 100b53315..244e7efbd 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -224,7 +224,7 @@ gb_internal Scope *create_scope(CheckerInfo *info, Scope *parent) { if (parent != nullptr && parent != builtin_pkg->scope) { Scope *prev_head_child = parent->head_child.exchange(s, std::memory_order_acq_rel); if (prev_head_child) { - prev_head_child->next.store(s, std::memory_order_release); + s->next.store(prev_head_child, std::memory_order_release); } } @@ -703,6 +703,15 @@ gb_internal void check_scope_usage(Checker *c, Scope *scope, u64 vet_flags) { array_add(&vetted_entities, ve_unused); } else if (is_shadowed) { array_add(&vetted_entities, ve_shadowed); + } else if (e->kind == Entity_Variable && (e->flags & (EntityFlag_Param|EntityFlag_Using)) == 0) { + i64 sz = type_size_of(e->type); + // TODO(bill): When is a good size warn? + // Is 128 KiB good enough? + if (sz >= 1ll<<17) { + gbString type_str = type_to_string(e->type); + warning(e->token, "Declaration of '%.*s' may cause a stack overflow due to its type '%s' having a size of %lld bytes", LIT(e->token.string), type_str, cast(long long)sz); + gb_string_free(type_str); + } } } rw_mutex_shared_unlock(&scope->mutex); @@ -734,17 +743,6 @@ gb_internal void check_scope_usage(Checker *c, Scope *scope, u64 vet_flags) { break; } } - - if (e->kind == Entity_Variable && (e->flags & (EntityFlag_Param|EntityFlag_Using)) == 0) { - i64 sz = type_size_of(e->type); - // TODO(bill): When is a good size warn? - // Is 128 KiB good enough? - if (sz >= 1ll<<17) { - gbString type_str = type_to_string(e->type); - warning(e->token, "Declaration of '%.*s' may cause a stack overflow due to its type '%s' having a size of %lld bytes", LIT(name), type_str, cast(long long)sz); - gb_string_free(type_str); - } - } } array_free(&vetted_entities); diff --git a/src/error.cpp b/src/error.cpp index b18df79b7..c92392dce 100644 --- a/src/error.cpp +++ b/src/error.cpp @@ -62,7 +62,9 @@ gb_internal ErrorValue *get_error_value(void) { gb_internal bool any_errors(void) { return global_error_collector.count.load() != 0; } - +gb_internal bool any_warnings(void) { + return global_error_collector.warning_count.load() != 0; +} gb_internal void init_global_error_collector(void) { @@ -600,7 +602,7 @@ gb_internal void syntax_error_with_verbose(TokenPos pos, TokenPos end, char cons gb_internal void compiler_error(char const *fmt, ...) { - if (any_errors()) { + if (any_errors() || any_warnings()) { print_all_errors(); } @@ -616,7 +618,7 @@ gb_internal void compiler_error(char const *fmt, ...) { gb_internal void exit_with_errors(void) { - if (any_errors()) { + if (any_errors() || any_warnings()) { print_all_errors(); } gb_exit(1); @@ -650,7 +652,7 @@ gb_internal void print_all_errors(void) { } }; - GB_ASSERT(any_errors()); + GB_ASSERT(any_errors() || any_warnings()); gbFile *f = gb_file_get_standard(gbFileStandard_Error); array_sort(global_error_collector.error_values, error_value_cmp); diff --git a/src/linker.cpp b/src/linker.cpp index 0e3169b22..aa36b3278 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -139,9 +139,11 @@ gb_internal i32 linker_stage(LinkerData *gen) { } - StringSet libs = {}; - string_set_init(&libs, 64); - defer (string_set_destroy(&libs)); + StringSet min_libs_set = {}; + string_set_init(&min_libs_set, 64); + defer (string_set_destroy(&min_libs_set)); + + String prev_lib = {}; StringSet asm_files = {}; string_set_init(&asm_files, 64); @@ -149,6 +151,11 @@ gb_internal i32 linker_stage(LinkerData *gen) { for (Entity *e : gen->foreign_libraries) { GB_ASSERT(e->kind == Entity_LibraryName); + // NOTE(bill): Add these before the linking values + String extra_linker_flags = string_trim_whitespace(e->LibraryName.extra_linker_flags); + if (extra_linker_flags.len != 0) { + lib_str = gb_string_append_fmt(lib_str, " %.*s", LIT(extra_linker_flags)); + } for_array(i, e->LibraryName.paths) { String lib = string_trim_whitespace(e->LibraryName.paths[i]); // IMPORTANT NOTE(bill): calling `string_to_lower` here is not an issue because @@ -162,12 +169,11 @@ gb_internal i32 linker_stage(LinkerData *gen) { if (!string_set_update(&asm_files, lib)) { String asm_file = asm_files.entries[i].value; String obj_file = concatenate_strings(permanent_allocator(), asm_file, str_lit(".obj")); - String obj_format; -#if defined(GB_ARCH_64_BIT) - obj_format = str_lit("win64"); -#elif defined(GB_ARCH_32_BIT) + String obj_format = str_lit("win64"); + #if defined(GB_ARCH_32_BIT) obj_format = str_lit("win32"); -#endif // GB_ARCH_*_BIT + #endif + result = system_exec_command_line_app("nasm", "\"%.*s\\bin\\nasm\\windows\\nasm.exe\" \"%.*s\" " "-f \"%.*s\" " @@ -185,21 +191,16 @@ gb_internal i32 linker_stage(LinkerData *gen) { } array_add(&gen->output_object_paths, obj_file); } - } else { - if (!string_set_update(&libs, lib)) { + } else if (!string_set_update(&min_libs_set, lib) || + !build_context.min_link_libs) { + if (prev_lib != lib) { lib_str = gb_string_append_fmt(lib_str, " \"%.*s\"", LIT(lib)); } + prev_lib = lib; } } } - for (Entity *e : gen->foreign_libraries) { - GB_ASSERT(e->kind == Entity_LibraryName); - if (e->LibraryName.extra_linker_flags.len != 0) { - lib_str = gb_string_append_fmt(lib_str, " %.*s", LIT(e->LibraryName.extra_linker_flags)); - } - } - if (build_context.build_mode == BuildMode_DynamicLibrary) { link_settings = gb_string_append_fmt(link_settings, " /DLL"); } else { @@ -318,12 +319,19 @@ gb_internal i32 linker_stage(LinkerData *gen) { string_set_init(&asm_files, 64); defer (string_set_destroy(&asm_files)); - StringSet libs = {}; - string_set_init(&libs, 64); - defer (string_set_destroy(&libs)); + StringSet min_libs_set = {}; + string_set_init(&min_libs_set, 64); + defer (string_set_destroy(&min_libs_set)); + + String prev_lib = {}; for (Entity *e : gen->foreign_libraries) { GB_ASSERT(e->kind == Entity_LibraryName); + // NOTE(bill): Add these before the linking values + String extra_linker_flags = string_trim_whitespace(e->LibraryName.extra_linker_flags); + if (extra_linker_flags.len != 0) { + lib_str = gb_string_append_fmt(lib_str, " %.*s", LIT(extra_linker_flags)); + } for (String lib : e->LibraryName.paths) { lib = string_trim_whitespace(lib); if (lib.len == 0) { @@ -336,19 +344,19 @@ gb_internal i32 linker_stage(LinkerData *gen) { String asm_file = lib; String obj_file = concatenate_strings(permanent_allocator(), asm_file, str_lit(".o")); String obj_format; -#if defined(GB_ARCH_64_BIT) + #if defined(GB_ARCH_64_BIT) if (is_osx) { obj_format = str_lit("macho64"); } else { obj_format = str_lit("elf64"); } -#elif defined(GB_ARCH_32_BIT) + #elif defined(GB_ARCH_32_BIT) if (is_osx) { obj_format = str_lit("macho32"); } else { obj_format = str_lit("elf32"); } -#endif // GB_ARCH_*_BIT + #endif // GB_ARCH_*_BIT if (is_osx) { // `as` comes with MacOS. @@ -383,10 +391,15 @@ gb_internal i32 linker_stage(LinkerData *gen) { } array_add(&gen->output_object_paths, obj_file); } else { - if (string_set_update(&libs, lib)) { + if (string_set_update(&min_libs_set, lib) && build_context.min_link_libs) { continue; } + if (prev_lib == lib) { + continue; + } + prev_lib = lib; + // Do not add libc again, this is added later already, and omitted with // the `-no-crt` flag, not skipping here would cause duplicate library // warnings when linking on darwin and might link libc silently even with `-no-crt`. @@ -433,13 +446,6 @@ gb_internal i32 linker_stage(LinkerData *gen) { } } - for (Entity *e : gen->foreign_libraries) { - GB_ASSERT(e->kind == Entity_LibraryName); - if (e->LibraryName.extra_linker_flags.len != 0) { - lib_str = gb_string_append_fmt(lib_str, " %.*s", LIT(e->LibraryName.extra_linker_flags)); - } - } - gbString object_files = gb_string_make(heap_allocator(), ""); defer (gb_string_free(object_files)); for (String object_path : gen->output_object_paths) { diff --git a/src/llvm_abi.cpp b/src/llvm_abi.cpp index 724e4e35a..88bb58c55 100644 --- a/src/llvm_abi.cpp +++ b/src/llvm_abi.cpp @@ -192,7 +192,7 @@ gb_internal void lb_add_function_type_attributes(LLVMValueRef fn, lbFunctionType // } LLVMSetFunctionCallConv(fn, cc_kind); if (calling_convention == ProcCC_Odin) { - unsigned context_index = offset+arg_count; + unsigned context_index = arg_index; LLVMAddAttributeAtIndex(fn, context_index, noalias_attr); LLVMAddAttributeAtIndex(fn, context_index, nonnull_attr); LLVMAddAttributeAtIndex(fn, context_index, nocapture_attr); @@ -275,7 +275,7 @@ gb_internal i64 lb_alignof(LLVMTypeRef type) { case LLVMIntegerTypeKind: { unsigned w = LLVMGetIntTypeWidth(type); - return gb_clamp((w + 7)/8, 1, build_context.ptr_size); + return gb_clamp((w + 7)/8, 1, build_context.max_align); } case LLVMHalfTypeKind: return 2; @@ -558,7 +558,6 @@ namespace lbAbiAmd64SysV { Amd64TypeAttribute_StructRect, }; - gb_internal LB_ABI_COMPUTE_RETURN_TYPE(compute_return_type); gb_internal void classify_with(LLVMTypeRef t, Array *cls, i64 ix, i64 off); gb_internal void fixup(LLVMTypeRef t, Array *cls); gb_internal lbArgType amd64_type(LLVMContextRef c, LLVMTypeRef type, Amd64TypeAttributeKind attribute_kind, ProcCallingConvention calling_convention); @@ -796,10 +795,10 @@ namespace lbAbiAmd64SysV { } } + i64 sz = lb_sizeof(type); if (all_ints) { - i64 sz = lb_sizeof(type); for_array(i, reg_classes) { - GB_ASSERT(sz != 0); + GB_ASSERT(sz > 0); // TODO(bill): is this even correct? BECAUSE LLVM DOES NOT DOCUMENT ANY OF THIS!!! if (sz >= 8) { array_add(&types, LLVMIntTypeInContext(c, 64)); @@ -811,12 +810,16 @@ namespace lbAbiAmd64SysV { } } else { for (isize i = 0; i < reg_classes.count; /**/) { + GB_ASSERT(sz > 0); RegClass reg_class = reg_classes[i]; switch (reg_class) { case RegClass_Int: - // TODO(bill): is this even correct? BECAUSE LLVM DOES NOT DOCUMENT ANY OF THIS!!! - array_add(&types, LLVMIntTypeInContext(c, 64)); - break; + { + i64 rs = gb_min(sz, 8); + array_add(&types, LLVMIntTypeInContext(c, cast(unsigned)(rs*8))); + sz -= rs; + break; + } case RegClass_SSEFv: case RegClass_SSEDv: case RegClass_SSEInt8: @@ -856,15 +859,18 @@ namespace lbAbiAmd64SysV { unsigned vec_len = llvec_len(reg_classes, i+1); LLVMTypeRef vec_type = LLVMVectorType(elem_type, vec_len * elems_per_word); array_add(&types, vec_type); + sz -= lb_sizeof(vec_type); i += vec_len; continue; } break; case RegClass_SSEFs: array_add(&types, LLVMFloatTypeInContext(c)); + sz -= 4; break; case RegClass_SSEDs: array_add(&types, LLVMDoubleTypeInContext(c)); + sz -= 8; break; default: GB_PANIC("Unhandled RegClass"); @@ -876,8 +882,8 @@ namespace lbAbiAmd64SysV { if (types.count == 1) { return types[0]; } - // TODO(bill): this should be packed but it causes code generation issues - return LLVMStructTypeInContext(c, types.data, cast(unsigned)types.count, false); + + return LLVMStructTypeInContext(c, types.data, cast(unsigned)types.count, sz == 0); } gb_internal void classify_with(LLVMTypeRef t, Array *cls, i64 ix, i64 off) { @@ -980,28 +986,6 @@ namespace lbAbiAmd64SysV { break; } } - - gb_internal LB_ABI_COMPUTE_RETURN_TYPE(compute_return_type) { - if (!return_is_defined) { - return lb_arg_type_direct(LLVMVoidTypeInContext(c)); - } else if (lb_is_type_kind(return_type, LLVMStructTypeKind)) { - i64 sz = lb_sizeof(return_type); - switch (sz) { - case 1: return lb_arg_type_direct(return_type, LLVMIntTypeInContext(c, 8), nullptr, nullptr); - case 2: return lb_arg_type_direct(return_type, LLVMIntTypeInContext(c, 16), nullptr, nullptr); - case 4: return lb_arg_type_direct(return_type, LLVMIntTypeInContext(c, 32), nullptr, nullptr); - case 8: return lb_arg_type_direct(return_type, LLVMIntTypeInContext(c, 64), nullptr, nullptr); - } - - LB_ABI_MODIFY_RETURN_IF_TUPLE_MACRO(); - - LLVMAttributeRef attr = lb_create_enum_attribute_with_type(c, "sret", return_type); - return lb_arg_type_indirect(return_type, attr); - } else if (build_context.metrics.os == TargetOs_windows && lb_is_type_kind(return_type, LLVMIntegerTypeKind) && lb_sizeof(return_type) == 16) { - return lb_arg_type_direct(return_type, LLVMIntTypeInContext(c, 128), nullptr, nullptr); - } - return non_struct(c, return_type); - } }; @@ -1166,8 +1150,7 @@ namespace lbAbiArm64 { size_copy -= 8; } GB_ASSERT(size_copy <= 0); - // TODO(bill): this should be packed but it causes code generation issues - cast_type = LLVMStructTypeInContext(c, types, count, false); + cast_type = LLVMStructTypeInContext(c, types, count, true); } return lb_arg_type_direct(return_type, cast_type, nullptr, nullptr); } else { diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index cc9b3ac5d..645a091b0 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -1975,12 +1975,6 @@ gb_internal void lb_generate_missing_procedures(lbGenerator *gen, bool do_thread } gb_internal void lb_debug_info_complete_types_and_finalize(lbGenerator *gen) { - for (auto const &entry : gen->modules) { - lbModule *m = entry.value; - if (m->debug_builder != nullptr) { - lb_debug_complete_types(m); - } - } for (auto const &entry : gen->modules) { lbModule *m = entry.value; if (m->debug_builder != nullptr) { diff --git a/src/llvm_backend.hpp b/src/llvm_backend.hpp index 6000be32d..c4bf2691d 100644 --- a/src/llvm_backend.hpp +++ b/src/llvm_backend.hpp @@ -199,8 +199,6 @@ struct lbModule { RecursiveMutex debug_values_mutex; PtrMap debug_values; - Array debug_incomplete_types; - StringMap objc_classes; StringMap objc_selectors; diff --git a/src/llvm_backend_debug.cpp b/src/llvm_backend_debug.cpp index 048f5f933..511ff0475 100644 --- a/src/llvm_backend_debug.cpp +++ b/src/llvm_backend_debug.cpp @@ -114,6 +114,415 @@ gb_internal LLVMMetadataRef lb_debug_basic_struct(lbModule *m, String const &nam return LLVMDIBuilderCreateStructType(m->debug_builder, scope, cast(char const *)name.text, name.len, file, 1, size_in_bits, align_in_bits, LLVMDIFlagZero, nullptr, elements, element_count, 0, nullptr, "", 0); } +gb_internal LLVMMetadataRef lb_debug_struct(lbModule *m, Type *type, Type *bt, String name, LLVMMetadataRef scope, LLVMMetadataRef file, unsigned line) { + GB_ASSERT(bt->kind == Type_Struct); + + unsigned tag = DW_TAG_structure_type; + if (is_type_raw_union(bt)) { + tag = DW_TAG_union_type; + } + + u64 size_in_bits = 8*type_size_of(bt); + u32 align_in_bits = 8*cast(u32)type_align_of(bt); + + LLVMMetadataRef temp_forward_decl = LLVMDIBuilderCreateReplaceableCompositeType( + m->debug_builder, tag, + cast(char const *)name.text, cast(size_t)name.len, + scope, file, line, 0, size_in_bits, align_in_bits, LLVMDIFlagZero, "", 0 + ); + + lb_set_llvm_metadata(m, type, temp_forward_decl); + + type_set_offsets(bt); + + unsigned element_count = cast(unsigned)(bt->Struct.fields.count); + LLVMMetadataRef *elements = gb_alloc_array(temporary_allocator(), LLVMMetadataRef, element_count); + + LLVMMetadataRef member_scope = lb_get_llvm_metadata(m, bt->Struct.scope); + + for_array(j, bt->Struct.fields) { + Entity *f = bt->Struct.fields[j]; + String fname = f->token.string; + + unsigned field_line = 0; + LLVMDIFlags field_flags = LLVMDIFlagZero; + GB_ASSERT(bt->Struct.offsets != nullptr); + u64 offset_in_bits = 8*cast(u64)bt->Struct.offsets[j]; + + elements[j] = LLVMDIBuilderCreateMemberType( + m->debug_builder, + member_scope, + cast(char const *)fname.text, cast(size_t)fname.len, + file, field_line, + 8*cast(u64)type_size_of(f->type), 8*cast(u32)type_align_of(f->type), + offset_in_bits, + field_flags, + lb_debug_type(m, f->type) + ); + } + + LLVMMetadataRef final_decl = nullptr; + if (tag == DW_TAG_union_type) { + final_decl = LLVMDIBuilderCreateUnionType( + m->debug_builder, scope, + cast(char const*)name.text, cast(size_t)name.len, + file, line, + size_in_bits, align_in_bits, + LLVMDIFlagZero, + elements, element_count, + 0, + "", 0 + ); + } else { + final_decl = LLVMDIBuilderCreateStructType( + m->debug_builder, scope, + cast(char const *)name.text, cast(size_t)name.len, + file, line, + size_in_bits, align_in_bits, + LLVMDIFlagZero, + nullptr, + elements, element_count, + 0, + nullptr, + "", 0 + ); + } + + LLVMMetadataReplaceAllUsesWith(temp_forward_decl, final_decl); + lb_set_llvm_metadata(m, type, final_decl); + return final_decl; +} + +gb_internal LLVMMetadataRef lb_debug_slice(lbModule *m, Type *type, String name, LLVMMetadataRef scope, LLVMMetadataRef file, unsigned line) { + Type *bt = base_type(type); + GB_ASSERT(bt->kind == Type_Slice); + + unsigned const ptr_bits = cast(unsigned)(8*build_context.ptr_size); + + u64 size_in_bits = 8*type_size_of(bt); + u32 align_in_bits = 8*cast(u32)type_align_of(bt); + + LLVMMetadataRef temp_forward_decl = LLVMDIBuilderCreateReplaceableCompositeType( + m->debug_builder, DW_TAG_structure_type, + cast(char const *)name.text, cast(size_t)name.len, + scope, file, line, 0, size_in_bits, align_in_bits, LLVMDIFlagZero, "", 0 + ); + + lb_set_llvm_metadata(m, type, temp_forward_decl); + + unsigned element_count = 2; + LLVMMetadataRef elements[2]; + + // LLVMMetadataRef member_scope = lb_get_llvm_metadata(m, bt->Slice.scope); + LLVMMetadataRef member_scope = nullptr; + + Type *elem_type = alloc_type_pointer(bt->Slice.elem); + elements[0] = LLVMDIBuilderCreateMemberType( + m->debug_builder, member_scope, + "data", 4, + file, line, + 8*cast(u64)type_size_of(elem_type), 8*cast(u32)type_align_of(elem_type), + 0, + LLVMDIFlagZero, lb_debug_type(m, elem_type) + ); + + elements[1] = LLVMDIBuilderCreateMemberType( + m->debug_builder, member_scope, + "len", 3, + file, line, + 8*cast(u64)type_size_of(t_int), 8*cast(u32)type_align_of(t_int), + ptr_bits, + LLVMDIFlagZero, lb_debug_type(m, t_int) + ); + + LLVMMetadataRef final_decl = LLVMDIBuilderCreateStructType( + m->debug_builder, scope, + cast(char const *)name.text, cast(size_t)name.len, + file, line, + size_in_bits, align_in_bits, + LLVMDIFlagZero, + nullptr, + elements, element_count, + 0, + nullptr, + "", 0 + ); + + LLVMMetadataReplaceAllUsesWith(temp_forward_decl, final_decl); + lb_set_llvm_metadata(m, type, final_decl); + return final_decl; +} + +gb_internal LLVMMetadataRef lb_debug_dynamic_array(lbModule *m, Type *type, String name, LLVMMetadataRef scope, LLVMMetadataRef file, unsigned line) { + Type *bt = base_type(type); + GB_ASSERT(bt->kind == Type_DynamicArray); + + unsigned const ptr_bits = cast(unsigned)(8*build_context.ptr_size); + unsigned const int_bits = cast(unsigned)(8*build_context.int_size); + + u64 size_in_bits = 8*type_size_of(bt); + u32 align_in_bits = 8*cast(u32)type_align_of(bt); + + LLVMMetadataRef temp_forward_decl = LLVMDIBuilderCreateReplaceableCompositeType( + m->debug_builder, DW_TAG_structure_type, + cast(char const *)name.text, cast(size_t)name.len, + scope, file, line, 0, size_in_bits, align_in_bits, LLVMDIFlagZero, "", 0 + ); + + lb_set_llvm_metadata(m, type, temp_forward_decl); + + unsigned element_count = 4; + LLVMMetadataRef elements[4]; + + // LLVMMetadataRef member_scope = lb_get_llvm_metadata(m, bt->DynamicArray.scope); + LLVMMetadataRef member_scope = nullptr; + + Type *elem_type = alloc_type_pointer(bt->DynamicArray.elem); + elements[0] = LLVMDIBuilderCreateMemberType( + m->debug_builder, member_scope, + "data", 4, + file, line, + 8*cast(u64)type_size_of(elem_type), 8*cast(u32)type_align_of(elem_type), + 0, + LLVMDIFlagZero, lb_debug_type(m, elem_type) + ); + + elements[1] = LLVMDIBuilderCreateMemberType( + m->debug_builder, member_scope, + "len", 3, + file, line, + 8*cast(u64)type_size_of(t_int), 8*cast(u32)type_align_of(t_int), + ptr_bits, + LLVMDIFlagZero, lb_debug_type(m, t_int) + ); + + elements[2] = LLVMDIBuilderCreateMemberType( + m->debug_builder, member_scope, + "cap", 3, + file, line, + 8*cast(u64)type_size_of(t_int), 8*cast(u32)type_align_of(t_int), + ptr_bits+int_bits, + LLVMDIFlagZero, lb_debug_type(m, t_int) + ); + + elements[3] = LLVMDIBuilderCreateMemberType( + m->debug_builder, member_scope, + "allocator", 9, + file, line, + 8*cast(u64)type_size_of(t_allocator), 8*cast(u32)type_align_of(t_allocator), + ptr_bits+int_bits+int_bits, + LLVMDIFlagZero, lb_debug_type(m, t_allocator) + ); + + LLVMMetadataRef final_decl = LLVMDIBuilderCreateStructType( + m->debug_builder, scope, + cast(char const *)name.text, cast(size_t)name.len, + file, line, + size_in_bits, align_in_bits, + LLVMDIFlagZero, + nullptr, + elements, element_count, + 0, + nullptr, + "", 0 + ); + + LLVMMetadataReplaceAllUsesWith(temp_forward_decl, final_decl); + lb_set_llvm_metadata(m, type, final_decl); + return final_decl; +} + +gb_internal LLVMMetadataRef lb_debug_union(lbModule *m, Type *type, String name, LLVMMetadataRef scope, LLVMMetadataRef file, unsigned line) { + Type *bt = base_type(type); + GB_ASSERT(bt->kind == Type_Union); + + u64 size_in_bits = 8*type_size_of(bt); + u32 align_in_bits = 8*cast(u32)type_align_of(bt); + + LLVMMetadataRef temp_forward_decl = LLVMDIBuilderCreateReplaceableCompositeType( + m->debug_builder, DW_TAG_union_type, + cast(char const *)name.text, cast(size_t)name.len, + scope, file, line, 0, size_in_bits, align_in_bits, LLVMDIFlagZero, "", 0 + ); + + lb_set_llvm_metadata(m, type, temp_forward_decl); + + isize index_offset = 1; + if (is_type_union_maybe_pointer(bt)) { + index_offset = 0; + } + + LLVMMetadataRef member_scope = lb_get_llvm_metadata(m, bt->Union.scope); + unsigned element_count = cast(unsigned)bt->Union.variants.count; + if (index_offset > 0) { + element_count += 1; + } + + LLVMMetadataRef *elements = gb_alloc_array(temporary_allocator(), LLVMMetadataRef, element_count); + + if (index_offset > 0) { + Type *tag_type = union_tag_type(bt); + u64 offset_in_bits = 8*cast(u64)bt->Union.variant_block_size; + + elements[0] = LLVMDIBuilderCreateMemberType( + m->debug_builder, member_scope, + "tag", 3, + file, line, + 8*cast(u64)type_size_of(tag_type), 8*cast(u32)type_align_of(tag_type), + offset_in_bits, + LLVMDIFlagZero, lb_debug_type(m, tag_type) + ); + } + + for_array(j, bt->Union.variants) { + Type *variant = bt->Union.variants[j]; + + unsigned field_index = cast(unsigned)(index_offset+j); + + char name[16] = {}; + gb_snprintf(name, gb_size_of(name), "v%u", field_index); + isize name_len = gb_strlen(name); + + elements[field_index] = LLVMDIBuilderCreateMemberType( + m->debug_builder, member_scope, + name, name_len, + file, line, + 8*cast(u64)type_size_of(variant), 8*cast(u32)type_align_of(variant), + 0, + LLVMDIFlagZero, lb_debug_type(m, variant) + ); + } + + LLVMMetadataRef final_decl = LLVMDIBuilderCreateUnionType( + m->debug_builder, + scope, + cast(char const *)name.text, cast(size_t)name.len, + file, line, + size_in_bits, align_in_bits, + LLVMDIFlagZero, + elements, + element_count, + 0, + "", 0 + ); + + LLVMMetadataReplaceAllUsesWith(temp_forward_decl, final_decl); + lb_set_llvm_metadata(m, type, final_decl); + return final_decl; +} + +gb_internal LLVMMetadataRef lb_debug_bitset(lbModule *m, Type *type, String name, LLVMMetadataRef scope, LLVMMetadataRef file, unsigned line) { + Type *bt = base_type(type); + GB_ASSERT(bt->kind == Type_BitSet); + + u64 size_in_bits = 8*type_size_of(bt); + u32 align_in_bits = 8*cast(u32)type_align_of(bt); + + LLVMMetadataRef bit_set_field_type = lb_debug_type(m, t_bool); + + unsigned element_count = 0; + LLVMMetadataRef *elements = nullptr; + + Type *elem = base_type(bt->BitSet.elem); + if (elem->kind == Type_Enum) { + element_count = cast(unsigned)elem->Enum.fields.count; + elements = gb_alloc_array(temporary_allocator(), LLVMMetadataRef, element_count); + + for_array(i, elem->Enum.fields) { + Entity *f = elem->Enum.fields[i]; + GB_ASSERT(f->kind == Entity_Constant); + i64 val = exact_value_to_i64(f->Constant.value); + String field_name = f->token.string; + u64 offset_in_bits = cast(u64)(val - bt->BitSet.lower); + elements[i] = LLVMDIBuilderCreateBitFieldMemberType( + m->debug_builder, + scope, + cast(char const *)field_name.text, field_name.len, + file, line, + 1, + offset_in_bits, + 0, + LLVMDIFlagZero, + bit_set_field_type + ); + } + } else { + char name[32] = {}; + + GB_ASSERT(is_type_integer(elem)); + i64 count = bt->BitSet.upper - bt->BitSet.lower + 1; + GB_ASSERT(0 <= count); + + element_count = cast(unsigned)count; + elements = gb_alloc_array(temporary_allocator(), LLVMMetadataRef, element_count); + + for (unsigned i = 0; i < element_count; i++) { + u64 offset_in_bits = i; + i64 val = bt->BitSet.lower + cast(i64)i; + gb_snprintf(name, gb_count_of(name), "%lld", cast(long long)val); + elements[i] = LLVMDIBuilderCreateBitFieldMemberType( + m->debug_builder, + scope, + name, gb_strlen(name), + file, line, + 1, + offset_in_bits, + 0, + LLVMDIFlagZero, + bit_set_field_type + ); + } + } + + LLVMMetadataRef final_decl = LLVMDIBuilderCreateUnionType( + m->debug_builder, + scope, + cast(char const *)name.text, cast(size_t)name.len, + file, line, + size_in_bits, align_in_bits, + LLVMDIFlagZero, + elements, + element_count, + 0, + "", 0 + ); + lb_set_llvm_metadata(m, type, final_decl); + return final_decl; +} + +gb_internal LLVMMetadataRef lb_debug_enum(lbModule *m, Type *type, String name, LLVMMetadataRef scope, LLVMMetadataRef file, unsigned line) { + Type *bt = base_type(type); + GB_ASSERT(bt->kind == Type_Enum); + + u64 size_in_bits = 8*type_size_of(bt); + u32 align_in_bits = 8*cast(u32)type_align_of(bt); + + unsigned element_count = cast(unsigned)bt->Enum.fields.count; + LLVMMetadataRef *elements = gb_alloc_array(temporary_allocator(), LLVMMetadataRef, element_count); + + Type *bt_enum = base_enum_type(bt); + LLVMBool is_unsigned = is_type_unsigned(bt_enum); + for (unsigned i = 0; i < element_count; i++) { + Entity *f = bt->Enum.fields[i]; + GB_ASSERT(f->kind == Entity_Constant); + String enum_name = f->token.string; + i64 value = exact_value_to_i64(f->Constant.value); + elements[i] = LLVMDIBuilderCreateEnumerator(m->debug_builder, cast(char const *)enum_name.text, cast(size_t)enum_name.len, value, is_unsigned); + } + + LLVMMetadataRef class_type = lb_debug_type(m, bt_enum); + LLVMMetadataRef final_decl = LLVMDIBuilderCreateEnumerationType( + m->debug_builder, + scope, + cast(char const *)name.text, cast(size_t)name.len, + file, line, + size_in_bits, align_in_bits, + elements, element_count, + class_type + ); + lb_set_llvm_metadata(m, type, final_decl); + return final_decl; +} gb_internal LLVMMetadataRef lb_debug_type_basic_type(lbModule *m, String const &name, u64 size_in_bits, LLVMDWARFTypeEncoding encoding, LLVMDIFlags flags = LLVMDIFlagZero) { LLVMMetadataRef basic_type = LLVMDIBuilderCreateBasicType(m->debug_builder, cast(char const *)name.text, name.len, size_in_bits, encoding, flags); @@ -329,53 +738,19 @@ gb_internal LLVMMetadataRef lb_debug_type_internal(lbModule *m, Type *type) { return LLVMDIBuilderCreateTypedef(m->debug_builder, array_type, name, gb_string_length(name), nullptr, 0, nullptr, cast(u32)(8*type_align_of(type))); } + case Type_Map: { + Type *bt = base_type(type->Map.debug_metadata_type); + GB_ASSERT(bt->kind == Type_Struct); - case Type_Struct: - case Type_Union: - case Type_Slice: - case Type_DynamicArray: - case Type_Map: - case Type_BitSet: - { - unsigned tag = DW_TAG_structure_type; - if (is_type_raw_union(type) || is_type_union(type)) { - tag = DW_TAG_union_type; - } - u64 size_in_bits = cast(u64)(8*type_size_of(type)); - u32 align_in_bits = cast(u32)(8*type_size_of(type)); - LLVMDIFlags flags = LLVMDIFlagZero; + return lb_debug_struct(m, type, bt, make_string_c(type_to_string(type, temporary_allocator())), nullptr, nullptr, 0); + } - LLVMMetadataRef temp_forward_decl = LLVMDIBuilderCreateReplaceableCompositeType( - m->debug_builder, tag, "", 0, nullptr, nullptr, 0, 0, size_in_bits, align_in_bits, flags, "", 0 - ); - lbIncompleteDebugType idt = {}; - idt.type = type; - idt.metadata = temp_forward_decl; - - array_add(&m->debug_incomplete_types, idt); - lb_set_llvm_metadata(m, type, temp_forward_decl); - return temp_forward_decl; - } - - case Type_Enum: - { - LLVMMetadataRef scope = nullptr; - LLVMMetadataRef file = nullptr; - unsigned line = 0; - unsigned element_count = cast(unsigned)type->Enum.fields.count; - LLVMMetadataRef *elements = gb_alloc_array(permanent_allocator(), LLVMMetadataRef, element_count); - Type *bt = base_enum_type(type); - LLVMBool is_unsigned = is_type_unsigned(bt); - for (unsigned i = 0; i < element_count; i++) { - Entity *f = type->Enum.fields[i]; - GB_ASSERT(f->kind == Entity_Constant); - String name = f->token.string; - i64 value = exact_value_to_i64(f->Constant.value); - elements[i] = LLVMDIBuilderCreateEnumerator(m->debug_builder, cast(char const *)name.text, cast(size_t)name.len, value, is_unsigned); - } - LLVMMetadataRef class_type = lb_debug_type(m, bt); - return LLVMDIBuilderCreateEnumerationType(m->debug_builder, scope, "", 0, file, line, 8*type_size_of(type), 8*cast(unsigned)type_align_of(type), elements, element_count, class_type); - } + case Type_Struct: return lb_debug_struct( m, type, type, make_string_c(type_to_string(type, temporary_allocator())), nullptr, nullptr, 0); + case Type_Slice: return lb_debug_slice( m, type, make_string_c(type_to_string(type, temporary_allocator())), nullptr, nullptr, 0); + case Type_DynamicArray: return lb_debug_dynamic_array(m, type, make_string_c(type_to_string(type, temporary_allocator())), nullptr, nullptr, 0); + case Type_Union: return lb_debug_union( m, type, make_string_c(type_to_string(type, temporary_allocator())), nullptr, nullptr, 0); + case Type_BitSet: return lb_debug_bitset( m, type, make_string_c(type_to_string(type, temporary_allocator())), nullptr, nullptr, 0); + case Type_Enum: return lb_debug_enum( m, type, make_string_c(type_to_string(type, temporary_allocator())), nullptr, nullptr, 0); case Type_Tuple: if (type->Tuple.variables.count == 1) { @@ -539,7 +914,6 @@ gb_internal LLVMMetadataRef lb_debug_type(lbModule *m, Type *type) { unsigned line = 0; LLVMMetadataRef scope = nullptr; - if (type->Named.type_name != nullptr) { Entity *e = type->Named.type_name; scope = lb_get_base_scope_metadata(m, e->scope); @@ -548,456 +922,48 @@ gb_internal LLVMMetadataRef lb_debug_type(lbModule *m, Type *type) { } line = cast(unsigned)e->token.pos.line; } - // TODO(bill): location data for Type_Named - u64 size_in_bits = 8*type_size_of(type); - u32 align_in_bits = 8*cast(u32)type_align_of(type); String name = type->Named.name; - char const *name_text = cast(char const *)name.text; - size_t name_len = cast(size_t)name.len; - unsigned tag = DW_TAG_structure_type; - if (is_type_raw_union(type) || is_type_union(type)) { - tag = DW_TAG_union_type; + if (type->Named.type_name && type->Named.type_name->pkg && type->Named.type_name->pkg->name.len != 0) { + name = concatenate3_strings(temporary_allocator(), type->Named.type_name->pkg->name, str_lit("."), type->Named.name); } - LLVMDIFlags flags = LLVMDIFlagZero; Type *bt = base_type(type->Named.base); - lbIncompleteDebugType idt = {}; - idt.type = type; - switch (bt->kind) { - case Type_Enum: - { - unsigned line = 0; - unsigned element_count = cast(unsigned)bt->Enum.fields.count; - LLVMMetadataRef *elements = gb_alloc_array(permanent_allocator(), LLVMMetadataRef, element_count); - Type *ct = base_enum_type(type); - LLVMBool is_unsigned = is_type_unsigned(ct); - for (unsigned i = 0; i < element_count; i++) { - Entity *f = bt->Enum.fields[i]; - GB_ASSERT(f->kind == Entity_Constant); - String name = f->token.string; - i64 value = exact_value_to_i64(f->Constant.value); - elements[i] = LLVMDIBuilderCreateEnumerator(m->debug_builder, cast(char const *)name.text, cast(size_t)name.len, value, is_unsigned); - } - LLVMMetadataRef class_type = lb_debug_type(m, ct); - return LLVMDIBuilderCreateEnumerationType(m->debug_builder, scope, name_text, name_len, file, line, 8*type_size_of(type), 8*cast(unsigned)type_align_of(type), elements, element_count, class_type); - } + default: { + u32 align_in_bits = 8*cast(u32)type_align_of(type); + LLVMMetadataRef debug_bt = lb_debug_type(m, bt); + LLVMMetadataRef final_decl = LLVMDIBuilderCreateTypedef( + m->debug_builder, + debug_bt, + cast(char const *)name.text, cast(size_t)name.len, + file, line, scope, align_in_bits + ); + lb_set_llvm_metadata(m, type, final_decl); + return final_decl; + } + case Type_Map: { + bt = base_type(bt->Map.debug_metadata_type); + GB_ASSERT(bt->kind == Type_Struct); + return lb_debug_struct(m, type, bt, name, scope, file, line); + } - default: - { - LLVMMetadataRef debug_bt = lb_debug_type(m, bt); - LLVMMetadataRef final_decl = LLVMDIBuilderCreateTypedef(m->debug_builder, debug_bt, name_text, name_len, file, line, scope, align_in_bits); - lb_set_llvm_metadata(m, type, final_decl); - return final_decl; - } - - case Type_Slice: - case Type_DynamicArray: - case Type_Map: - case Type_Struct: - case Type_Union: - case Type_BitSet: - { - LLVMMetadataRef temp_forward_decl = LLVMDIBuilderCreateReplaceableCompositeType( - m->debug_builder, tag, name_text, name_len, nullptr, nullptr, 0, 0, size_in_bits, align_in_bits, flags, "", 0 - ); - idt.metadata = temp_forward_decl; - - array_add(&m->debug_incomplete_types, idt); - lb_set_llvm_metadata(m, type, temp_forward_decl); - - LLVMMetadataRef dummy = nullptr; - switch (bt->kind) { - case Type_Slice: - dummy = lb_debug_type(m, bt->Slice.elem); - dummy = lb_debug_type(m, alloc_type_pointer(bt->Slice.elem)); - dummy = lb_debug_type(m, t_int); - break; - case Type_DynamicArray: - dummy = lb_debug_type(m, bt->DynamicArray.elem); - dummy = lb_debug_type(m, alloc_type_pointer(bt->DynamicArray.elem)); - dummy = lb_debug_type(m, t_int); - dummy = lb_debug_type(m, t_allocator); - break; - case Type_Map: - dummy = lb_debug_type(m, bt->Map.key); - dummy = lb_debug_type(m, bt->Map.value); - dummy = lb_debug_type(m, t_int); - dummy = lb_debug_type(m, t_allocator); - dummy = lb_debug_type(m, t_uintptr); - break; - case Type_BitSet: - if (bt->BitSet.elem) dummy = lb_debug_type(m, bt->BitSet.elem); - if (bt->BitSet.underlying) dummy = lb_debug_type(m, bt->BitSet.underlying); - break; - } - - return temp_forward_decl; - } + case Type_Struct: return lb_debug_struct(m, type, base_type(type), name, scope, file, line); + case Type_Slice: return lb_debug_slice(m, type, name, scope, file, line); + case Type_DynamicArray: return lb_debug_dynamic_array(m, type, name, scope, file, line); + case Type_Union: return lb_debug_union(m, type, name, scope, file, line); + case Type_BitSet: return lb_debug_bitset(m, type, name, scope, file, line); + case Type_Enum: return lb_debug_enum(m, type, name, scope, file, line); } } - LLVMMetadataRef dt = lb_debug_type_internal(m, type); lb_set_llvm_metadata(m, type, dt); return dt; } -gb_internal void lb_debug_complete_types(lbModule *m) { - unsigned const int_bits = cast(unsigned)(8*build_context.int_size); - - for_array(debug_incomplete_type_index, m->debug_incomplete_types) { - TEMPORARY_ALLOCATOR_GUARD(); - - // NOTE(laytan): don't make this a pointer, the array could resize while in this iteration - // and cause a use-after-free at the end. - auto const idt = m->debug_incomplete_types[debug_incomplete_type_index]; - GB_ASSERT(idt.type != nullptr); - GB_ASSERT(idt.metadata != nullptr); - - Type *t = idt.type; - Type *bt = base_type(t); - - LLVMMetadataRef parent_scope = nullptr; - LLVMMetadataRef file = nullptr; - unsigned line_number = 0; - u64 size_in_bits = 8*type_size_of(t); - u32 align_in_bits = cast(u32)(8*type_align_of(t)); - LLVMDIFlags flags = LLVMDIFlagZero; - - LLVMMetadataRef derived_from = nullptr; - - LLVMMetadataRef *elements = nullptr; - unsigned element_count = 0; - - - unsigned runtime_lang = 0; // Objective-C runtime version - char const *unique_id = ""; - LLVMMetadataRef vtable_holder = nullptr; - size_t unique_id_len = 0; - - - LLVMMetadataRef record_scope = nullptr; - - switch (bt->kind) { - case Type_Slice: - case Type_DynamicArray: - case Type_Map: - case Type_Struct: - case Type_Union: - case Type_BitSet: { - bool is_union = is_type_raw_union(bt) || is_type_union(bt); - - String name = str_lit(""); - if (t->kind == Type_Named) { - name = t->Named.name; - if (t->Named.type_name && t->Named.type_name->pkg && t->Named.type_name->pkg->name.len != 0) { - name = concatenate3_strings(temporary_allocator(), t->Named.type_name->pkg->name, str_lit("."), t->Named.name); - } - - LLVMMetadataRef file = nullptr; - unsigned line = 0; - LLVMMetadataRef file_scope = nullptr; - - if (t->Named.type_name != nullptr) { - Entity *e = t->Named.type_name; - file_scope = lb_get_llvm_metadata(m, e->scope); - if (file_scope != nullptr) { - file = LLVMDIScopeGetFile(file_scope); - } - line = cast(unsigned)e->token.pos.line; - } - // TODO(bill): location data for Type_Named - - } else { - name = make_string_c(type_to_string(t, temporary_allocator())); - } - - - - switch (bt->kind) { - case Type_Slice: - element_count = 2; - elements = gb_alloc_array(temporary_allocator(), LLVMMetadataRef, element_count); - #if defined(GB_SYSTEM_WINDOWS) - elements[0] = lb_debug_struct_field(m, str_lit("data"), alloc_type_pointer(bt->Slice.elem), 0*int_bits); - #else - // FIX HACK TODO(bill): For some reason this causes a crash in *nix systems due to the reference counting - // of the debug type information - elements[0] = lb_debug_struct_field(m, str_lit("data"), t_rawptr, 0*int_bits); - #endif - elements[1] = lb_debug_struct_field(m, str_lit("len"), t_int, 1*int_bits); - break; - case Type_DynamicArray: - element_count = 4; - elements = gb_alloc_array(temporary_allocator(), LLVMMetadataRef, element_count); - #if defined(GB_SYSTEM_WINDOWS) - elements[0] = lb_debug_struct_field(m, str_lit("data"), alloc_type_pointer(bt->DynamicArray.elem), 0*int_bits); - #else - // FIX HACK TODO(bill): For some reason this causes a crash in *nix systems due to the reference counting - // of the debug type information - elements[0] = lb_debug_struct_field(m, str_lit("data"), t_rawptr, 0*int_bits); - #endif - elements[1] = lb_debug_struct_field(m, str_lit("len"), t_int, 1*int_bits); - elements[2] = lb_debug_struct_field(m, str_lit("cap"), t_int, 2*int_bits); - elements[3] = lb_debug_struct_field(m, str_lit("allocator"), t_allocator, 3*int_bits); - break; - - case Type_Map: - GB_ASSERT(t_raw_map != nullptr); - bt = base_type(bt->Map.debug_metadata_type); - // bt = base_type(t_raw_map); - GB_ASSERT(bt->kind == Type_Struct); - /*fallthrough*/ - case Type_Struct: - if (file == nullptr) { - if (bt->Struct.node) { - file = lb_get_llvm_metadata(m, bt->Struct.node->file()); - line_number = cast(unsigned)ast_token(bt->Struct.node).pos.line; - } - } - - type_set_offsets(bt); - { - isize element_offset = 0; - record_scope = lb_get_llvm_metadata(m, bt->Struct.scope); - switch (bt->Struct.soa_kind) { - case StructSoa_Slice: element_offset = 1; break; - case StructSoa_Dynamic: element_offset = 3; break; - } - element_count = cast(unsigned)(bt->Struct.fields.count + element_offset); - elements = gb_alloc_array(temporary_allocator(), LLVMMetadataRef, element_count); - - isize field_size_bits = 8*type_size_of(bt) - element_offset*int_bits; - - switch (bt->Struct.soa_kind) { - case StructSoa_Slice: - elements[0] = LLVMDIBuilderCreateMemberType( - m->debug_builder, record_scope, - ".len", 4, - file, 0, - 8*cast(u64)type_size_of(t_int), 8*cast(u32)type_align_of(t_int), - field_size_bits, - LLVMDIFlagZero, lb_debug_type(m, t_int) - ); - break; - case StructSoa_Dynamic: - elements[0] = LLVMDIBuilderCreateMemberType( - m->debug_builder, record_scope, - ".len", 4, - file, 0, - 8*cast(u64)type_size_of(t_int), 8*cast(u32)type_align_of(t_int), - field_size_bits + 0*int_bits, - LLVMDIFlagZero, lb_debug_type(m, t_int) - ); - elements[1] = LLVMDIBuilderCreateMemberType( - m->debug_builder, record_scope, - ".cap", 4, - file, 0, - 8*cast(u64)type_size_of(t_int), 8*cast(u32)type_align_of(t_int), - field_size_bits + 1*int_bits, - LLVMDIFlagZero, lb_debug_type(m, t_int) - ); - elements[2] = LLVMDIBuilderCreateMemberType( - m->debug_builder, record_scope, - ".allocator", 10, - file, 0, - 8*cast(u64)type_size_of(t_int), 8*cast(u32)type_align_of(t_int), - field_size_bits + 2*int_bits, - LLVMDIFlagZero, lb_debug_type(m, t_allocator) - ); - break; - } - - for_array(j, bt->Struct.fields) { - Entity *f = bt->Struct.fields[j]; - String fname = f->token.string; - - unsigned field_line = 0; - LLVMDIFlags field_flags = LLVMDIFlagZero; - GB_ASSERT(bt->Struct.offsets != nullptr); - u64 offset_in_bits = 8*cast(u64)bt->Struct.offsets[j]; - - elements[element_offset+j] = LLVMDIBuilderCreateMemberType( - m->debug_builder, record_scope, - cast(char const *)fname.text, cast(size_t)fname.len, - file, field_line, - 8*cast(u64)type_size_of(f->type), 8*cast(u32)type_align_of(f->type), - offset_in_bits, - field_flags, lb_debug_type(m, f->type) - ); - } - } - break; - case Type_Union: - { - if (file == nullptr) { - GB_ASSERT(bt->Union.node != nullptr); - file = lb_get_llvm_metadata(m, bt->Union.node->file()); - line_number = cast(unsigned)ast_token(bt->Union.node).pos.line; - } - - isize index_offset = 1; - if (is_type_union_maybe_pointer(bt)) { - index_offset = 0; - } - record_scope = lb_get_llvm_metadata(m, bt->Union.scope); - element_count = cast(unsigned)bt->Union.variants.count; - if (index_offset > 0) { - element_count += 1; - } - - elements = gb_alloc_array(temporary_allocator(), LLVMMetadataRef, element_count); - if (index_offset > 0) { - Type *tag_type = union_tag_type(bt); - unsigned field_line = 0; - u64 offset_in_bits = 8*cast(u64)bt->Union.variant_block_size; - LLVMDIFlags field_flags = LLVMDIFlagZero; - - elements[0] = LLVMDIBuilderCreateMemberType( - m->debug_builder, record_scope, - "tag", 3, - file, field_line, - 8*cast(u64)type_size_of(tag_type), 8*cast(u32)type_align_of(tag_type), - offset_in_bits, - field_flags, lb_debug_type(m, tag_type) - ); - } - - for_array(j, bt->Union.variants) { - Type *variant = bt->Union.variants[j]; - - unsigned field_index = cast(unsigned)(index_offset+j); - - char name[16] = {}; - gb_snprintf(name, gb_size_of(name), "v%u", field_index); - isize name_len = gb_strlen(name); - - unsigned field_line = 0; - LLVMDIFlags field_flags = LLVMDIFlagZero; - u64 offset_in_bits = 0; - - elements[field_index] = LLVMDIBuilderCreateMemberType( - m->debug_builder, record_scope, - name, name_len, - file, field_line, - 8*cast(u64)type_size_of(variant), 8*cast(u32)type_align_of(variant), - offset_in_bits, - field_flags, lb_debug_type(m, variant) - ); - } - } - break; - - case Type_BitSet: - { - if (file == nullptr) { - GB_ASSERT(bt->BitSet.node != nullptr); - file = lb_get_llvm_metadata(m, bt->BitSet.node->file()); - line_number = cast(unsigned)ast_token(bt->BitSet.node).pos.line; - } - - LLVMMetadataRef bit_set_field_type = lb_debug_type(m, t_bool); - LLVMMetadataRef scope = file; - - Type *elem = base_type(bt->BitSet.elem); - if (elem->kind == Type_Enum) { - element_count = cast(unsigned)elem->Enum.fields.count; - elements = gb_alloc_array(temporary_allocator(), LLVMMetadataRef, element_count); - for_array(i, elem->Enum.fields) { - Entity *f = elem->Enum.fields[i]; - GB_ASSERT(f->kind == Entity_Constant); - i64 val = exact_value_to_i64(f->Constant.value); - String name = f->token.string; - u64 offset_in_bits = cast(u64)(val - bt->BitSet.lower); - elements[i] = LLVMDIBuilderCreateBitFieldMemberType( - m->debug_builder, - scope, - cast(char const *)name.text, name.len, - file, line_number, - 1, - offset_in_bits, - 0, - LLVMDIFlagZero, - bit_set_field_type - ); - } - } else { - - char name[32] = {}; - - GB_ASSERT(is_type_integer(elem)); - i64 count = bt->BitSet.upper - bt->BitSet.lower + 1; - GB_ASSERT(0 <= count); - - element_count = cast(unsigned)count; - elements = gb_alloc_array(temporary_allocator(), LLVMMetadataRef, element_count); - for (unsigned i = 0; i < element_count; i++) { - u64 offset_in_bits = i; - i64 val = bt->BitSet.lower + cast(i64)i; - gb_snprintf(name, gb_count_of(name), "%lld", cast(long long)val); - elements[i] = LLVMDIBuilderCreateBitFieldMemberType( - m->debug_builder, - scope, - name, gb_strlen(name), - file, line_number, - 1, - offset_in_bits, - 0, - LLVMDIFlagZero, - bit_set_field_type - ); - } - } - } - } - - - LLVMMetadataRef final_metadata = nullptr; - if (is_union) { - final_metadata = LLVMDIBuilderCreateUnionType( - m->debug_builder, - parent_scope, - cast(char const *)name.text, cast(size_t)name.len, - file, line_number, - size_in_bits, align_in_bits, - flags, - elements, element_count, - runtime_lang, - unique_id, unique_id_len - ); - } else { - final_metadata = LLVMDIBuilderCreateStructType( - m->debug_builder, - parent_scope, - cast(char const *)name.text, cast(size_t)name.len, - file, line_number, - size_in_bits, align_in_bits, - flags, - derived_from, - elements, element_count, - runtime_lang, - vtable_holder, - unique_id, unique_id_len - ); - } - - LLVMMetadataReplaceAllUsesWith(idt.metadata, final_metadata); - lb_set_llvm_metadata(m, idt.type, final_metadata); - } break; - default: - GB_PANIC("invalid incomplete debug type"); - break; - } - } - array_clear(&m->debug_incomplete_types); -} - - - gb_internal void lb_add_debug_local_variable(lbProcedure *p, LLVMValueRef ptr, Type *type, Token const &token) { if (p->debug_info == nullptr) { return; @@ -1267,4 +1233,4 @@ gb_internal void add_debug_info_for_global_constant_from_entity(lbGenerator *gen add_debug_info_for_global_constant_internal_i64(m, e, dtype, v); } } -} \ No newline at end of file +} diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index 12949f0ab..0649150ca 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -1373,6 +1373,57 @@ gb_internal bool lb_is_empty_string_constant(Ast *expr) { return false; } +gb_internal lbValue lb_build_binary_in(lbProcedure *p, lbValue left, lbValue right, TokenKind op) { + Type *rt = base_type(right.type); + if (is_type_pointer(rt)) { + right = lb_emit_load(p, right); + rt = base_type(type_deref(rt)); + } + + switch (rt->kind) { + case Type_Map: + { + lbValue map_ptr = lb_address_from_load_or_generate_local(p, right); + lbValue key = left; + lbValue ptr = lb_internal_dynamic_map_get_ptr(p, map_ptr, key); + if (op == Token_in) { + return lb_emit_conv(p, lb_emit_comp_against_nil(p, Token_NotEq, ptr), t_bool); + } else { + return lb_emit_conv(p, lb_emit_comp_against_nil(p, Token_CmpEq, ptr), t_bool); + } + } + break; + case Type_BitSet: + { + Type *key_type = rt->BitSet.elem; + GB_ASSERT(are_types_identical(left.type, key_type)); + + Type *it = bit_set_to_int(rt); + left = lb_emit_conv(p, left, it); + if (is_type_different_to_arch_endianness(it)) { + left = lb_emit_byte_swap(p, left, integer_endian_type_to_platform_type(it)); + } + + lbValue lower = lb_const_value(p->module, left.type, exact_value_i64(rt->BitSet.lower)); + lbValue key = lb_emit_arith(p, Token_Sub, left, lower, left.type); + lbValue bit = lb_emit_arith(p, Token_Shl, lb_const_int(p->module, left.type, 1), key, left.type); + bit = lb_emit_conv(p, bit, it); + + lbValue old_value = lb_emit_transmute(p, right, it); + lbValue new_value = lb_emit_arith(p, Token_And, old_value, bit, it); + + if (op == Token_in) { + return lb_emit_conv(p, lb_emit_comp(p, Token_NotEq, new_value, lb_const_int(p->module, new_value.type, 0)), t_bool); + } else { + return lb_emit_conv(p, lb_emit_comp(p, Token_CmpEq, new_value, lb_const_int(p->module, new_value.type, 0)), t_bool); + } + } + break; + } + GB_PANIC("Invalid 'in' type"); + return {}; +} + gb_internal lbValue lb_build_binary_expr(lbProcedure *p, Ast *expr) { ast_node(be, BinaryExpr, expr); @@ -1480,57 +1531,8 @@ gb_internal lbValue lb_build_binary_expr(lbProcedure *p, Ast *expr) { { lbValue left = lb_build_expr(p, be->left); lbValue right = lb_build_expr(p, be->right); - Type *rt = base_type(right.type); - if (is_type_pointer(rt)) { - right = lb_emit_load(p, right); - rt = base_type(type_deref(rt)); - } - - switch (rt->kind) { - case Type_Map: - { - lbValue map_ptr = lb_address_from_load_or_generate_local(p, right); - lbValue key = left; - lbValue ptr = lb_internal_dynamic_map_get_ptr(p, map_ptr, key); - if (be->op.kind == Token_in) { - return lb_emit_conv(p, lb_emit_comp_against_nil(p, Token_NotEq, ptr), t_bool); - } else { - return lb_emit_conv(p, lb_emit_comp_against_nil(p, Token_CmpEq, ptr), t_bool); - } - } - break; - case Type_BitSet: - { - Type *key_type = rt->BitSet.elem; - GB_ASSERT(are_types_identical(left.type, key_type)); - - Type *it = bit_set_to_int(rt); - left = lb_emit_conv(p, left, it); - if (is_type_different_to_arch_endianness(it)) { - left = lb_emit_byte_swap(p, left, integer_endian_type_to_platform_type(it)); - } - - lbValue lower = lb_const_value(p->module, left.type, exact_value_i64(rt->BitSet.lower)); - lbValue key = lb_emit_arith(p, Token_Sub, left, lower, left.type); - lbValue bit = lb_emit_arith(p, Token_Shl, lb_const_int(p->module, left.type, 1), key, left.type); - bit = lb_emit_conv(p, bit, it); - - lbValue old_value = lb_emit_transmute(p, right, it); - lbValue new_value = lb_emit_arith(p, Token_And, old_value, bit, it); - - if (be->op.kind == Token_in) { - return lb_emit_conv(p, lb_emit_comp(p, Token_NotEq, new_value, lb_const_int(p->module, new_value.type, 0)), t_bool); - } else { - return lb_emit_conv(p, lb_emit_comp(p, Token_CmpEq, new_value, lb_const_int(p->module, new_value.type, 0)), t_bool); - } - } - break; - default: - GB_PANIC("Invalid 'in' type"); - } - break; + return lb_build_binary_in(p, left, right, be->op.kind); } - break; default: GB_PANIC("Invalid binary expression"); break; @@ -4675,8 +4677,10 @@ gb_internal lbAddr lb_build_addr_internal(lbProcedure *p, Ast *expr) { if (tav.mode == Addressing_Type) { // Addressing_Type Selection sel = lookup_field(tav.type, selector, true); if (sel.pseudo_field) { - GB_ASSERT(sel.entity->kind == Entity_Procedure); - return lb_addr(lb_find_value_from_entity(p->module, sel.entity)); + GB_ASSERT(sel.entity->kind == Entity_Procedure || sel.entity->kind == Entity_ProcGroup); + Entity *e = entity_of_node(sel_node); + GB_ASSERT(e->kind == Entity_Procedure); + return lb_addr(lb_find_value_from_entity(p->module, e)); } GB_PANIC("Unreachable %.*s", LIT(selector)); } diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp index a77e2ad15..889cb8822 100644 --- a/src/llvm_backend_general.cpp +++ b/src/llvm_backend_general.cpp @@ -81,7 +81,6 @@ gb_internal void lb_init_module(lbModule *m, Checker *c) { array_init(&m->global_procedures_and_types_to_create, a, 0, 1024); array_init(&m->missing_procedures_to_check, a, 0, 16); map_init(&m->debug_values); - array_init(&m->debug_incomplete_types, a, 0, 1024); string_map_init(&m->objc_classes); string_map_init(&m->objc_selectors); diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index fba7eb381..8ce116715 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -578,7 +578,10 @@ gb_internal void lb_begin_procedure_body(lbProcedure *p) { defer (param_index += 1); if (arg_type->kind == lbArg_Ignore) { - continue; + // Even though it is an ignored argument, it might still be referenced in the + // body. + lbValue dummy = lb_add_local_generated(p, e->type, false).addr; + lb_add_entity(p->module, e, dummy); } else if (arg_type->kind == lbArg_Direct) { if (e->token.string.len != 0 && !is_blank_ident(e->token.string)) { LLVMTypeRef param_type = lb_type(p->module, e->type); @@ -1051,6 +1054,7 @@ gb_internal lbValue lb_emit_call(lbProcedure *p, lbValue value, Array c Type *original_type = e->type; lbArgType *arg = &ft->args[param_index]; if (arg->kind == lbArg_Ignore) { + param_index += 1; continue; } @@ -3359,6 +3363,9 @@ gb_internal lbValue lb_build_call_expr_internal(lbProcedure *p, Ast *expr) { for (Ast *var_arg : variadic) { lbValue arg = lb_build_expr(p, var_arg); if (is_type_any(elem_type)) { + if (is_type_untyped_nil(arg.type)) { + arg = lb_const_nil(p->module, t_rawptr); + } array_add(&args, lb_emit_conv(p, arg, c_vararg_promote_type(default_type(arg.type)))); } else { array_add(&args, lb_emit_conv(p, arg, c_vararg_promote_type(elem_type))); @@ -3423,6 +3430,30 @@ gb_internal lbValue lb_build_call_expr_internal(lbProcedure *p, Ast *expr) { if (e->kind == Entity_TypeName) { lbValue value = lb_const_nil(p->module, e->type); args[param_index] = value; + } else if (is_c_vararg && pt->variadic && pt->variadic_index == param_index) { + GB_ASSERT(param_index == pt->param_count-1); + Type *slice_type = e->type; + GB_ASSERT(slice_type->kind == Type_Slice); + Type *elem_type = slice_type->Slice.elem; + + if (fv->value->kind == Ast_CompoundLit) { + ast_node(literal, CompoundLit, fv->value); + for (Ast *var_arg : literal->elems) { + lbValue arg = lb_build_expr(p, var_arg); + if (is_type_any(elem_type)) { + if (is_type_untyped_nil(arg.type)) { + arg = lb_const_nil(p->module, t_rawptr); + } + array_add(&args, lb_emit_conv(p, arg, c_vararg_promote_type(default_type(arg.type)))); + } else { + array_add(&args, lb_emit_conv(p, arg, c_vararg_promote_type(elem_type))); + } + } + } else { + lbValue value = lb_build_expr(p, fv->value); + GB_ASSERT(!is_type_tuple(value.type)); + array_add(&args, lb_emit_conv(p, value, c_vararg_promote_type(value.type))); + } } else { lbValue value = lb_build_expr(p, fv->value); GB_ASSERT(!is_type_tuple(value.type)); diff --git a/src/llvm_backend_stmt.cpp b/src/llvm_backend_stmt.cpp index 4ecf70ec4..24dd321f6 100644 --- a/src/llvm_backend_stmt.cpp +++ b/src/llvm_backend_stmt.cpp @@ -737,6 +737,22 @@ gb_internal void lb_build_range_interval(lbProcedure *p, AstBinaryExpr *node, lb_start_block(p, done); } +gb_internal lbValue lb_enum_values_slice(lbProcedure *p, Type *enum_type, i64 *enum_count_) { + Type *t = enum_type; + GB_ASSERT(is_type_enum(t)); + t = base_type(t); + GB_ASSERT(t->kind == Type_Enum); + i64 enum_count = t->Enum.fields.count; + + if (enum_count_) *enum_count_ = enum_count; + + lbValue ti = lb_type_info(p, t); + lbValue variant = lb_emit_struct_ep(p, ti, 4); + lbValue eti_ptr = lb_emit_conv(p, variant, t_type_info_enum_ptr); + lbValue values = lb_emit_load(p, lb_emit_struct_ep(p, eti_ptr, 2)); + return values; +} + gb_internal void lb_build_range_enum(lbProcedure *p, Type *enum_type, Type *val_type, lbValue *val_, lbValue *idx_, lbBlock **loop_, lbBlock **done_) { lbModule *m = p->module; @@ -744,15 +760,11 @@ gb_internal void lb_build_range_enum(lbProcedure *p, Type *enum_type, Type *val_ GB_ASSERT(is_type_enum(t)); t = base_type(t); Type *core_elem = core_type(t); - GB_ASSERT(t->kind == Type_Enum); - i64 enum_count = t->Enum.fields.count; - lbValue max_count = lb_const_int(m, t_int, enum_count); + i64 enum_count = 0; - lbValue ti = lb_type_info(p, t); - lbValue variant = lb_emit_struct_ep(p, ti, 4); - lbValue eti_ptr = lb_emit_conv(p, variant, t_type_info_enum_ptr); - lbValue values = lb_emit_load(p, lb_emit_struct_ep(p, eti_ptr, 2)); + lbValue values = lb_enum_values_slice(p, enum_type, &enum_count); lbValue values_data = lb_slice_elem(p, values); + lbValue max_count = lb_const_int(m, t_int, enum_count); lbAddr offset_ = lb_add_local_generated(p, t_int, false); lb_addr_store(p, offset_, lb_const_int(m, t_int, 0)); @@ -1052,6 +1064,74 @@ gb_internal void lb_build_range_stmt(lbProcedure *p, AstRangeStmt *rs, Scope *sc case Type_Tuple: lb_build_range_tuple(p, expr, val0_type, val1_type, &val, &key, &loop, &done); break; + + case Type_BitSet: { + lbModule *m = p->module; + + lbValue the_set = lb_build_expr(p, expr); + if (is_type_pointer(type_deref(the_set.type))) { + the_set = lb_emit_load(p, the_set); + } + + Type *elem = et->BitSet.elem; + if (is_type_enum(elem)) { + i64 enum_count = 0; + lbValue values = lb_enum_values_slice(p, elem, &enum_count); + lbValue values_data = lb_slice_elem(p, values); + lbValue max_count = lb_const_int(m, t_int, enum_count); + + lbAddr offset_ = lb_add_local_generated(p, t_int, false); + lb_addr_store(p, offset_, lb_const_int(m, t_int, 0)); + + loop = lb_create_block(p, "for.bit_set.enum.loop"); + lb_emit_jump(p, loop); + lb_start_block(p, loop); + + lbBlock *body_check = lb_create_block(p, "for.bit_set.enum.body-check"); + lbBlock *body = lb_create_block(p, "for.bit_set.enum.body"); + done = lb_create_block(p, "for.bit_set.enum.done"); + + lbValue offset = lb_addr_load(p, offset_); + lbValue cond = lb_emit_comp(p, Token_Lt, offset, max_count); + lb_emit_if(p, cond, body_check, done); + lb_start_block(p, body_check); + + lbValue val_ptr = lb_emit_ptr_offset(p, values_data, offset); + lb_emit_increment(p, offset_.addr); + val = lb_emit_load(p, val_ptr); + val = lb_emit_conv(p, val, elem); + + lbValue check = lb_build_binary_in(p, val, the_set, Token_in); + lb_emit_if(p, check, body, loop); + lb_start_block(p, body); + } else { + lbAddr offset_ = lb_add_local_generated(p, t_int, false); + lb_addr_store(p, offset_, lb_const_int(m, t_int, et->BitSet.lower)); + + lbValue max_count = lb_const_int(m, t_int, et->BitSet.upper); + + loop = lb_create_block(p, "for.bit_set.range.loop"); + lb_emit_jump(p, loop); + lb_start_block(p, loop); + + lbBlock *body_check = lb_create_block(p, "for.bit_set.range.body-check"); + lbBlock *body = lb_create_block(p, "for.bit_set.range.body"); + done = lb_create_block(p, "for.bit_set.range.done"); + + lbValue offset = lb_addr_load(p, offset_); + lbValue cond = lb_emit_comp(p, Token_LtEq, offset, max_count); + lb_emit_if(p, cond, body_check, done); + lb_start_block(p, body_check); + + val = lb_emit_conv(p, offset, elem); + lb_emit_increment(p, offset_.addr); + + lbValue check = lb_build_binary_in(p, val, the_set, Token_in); + lb_emit_if(p, check, body, loop); + lb_start_block(p, body); + } + break; + } default: GB_PANIC("Cannot range over %s", type_to_string(expr_type)); break; diff --git a/src/main.cpp b/src/main.cpp index 79c3a1670..2dbb72ca2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -296,6 +296,8 @@ enum BuildFlagKind { BuildFlag_ErrorPosStyle, BuildFlag_MaxErrorCount, + BuildFlag_MinLinkLibs, + // internal use only BuildFlag_InternalIgnoreLazy, BuildFlag_InternalIgnoreLLVMBuild, @@ -485,6 +487,8 @@ gb_internal bool parse_build_flags(Array args) { add_flag(&build_flags, BuildFlag_ErrorPosStyle, str_lit("error-pos-style"), BuildFlagParam_String, Command_all); add_flag(&build_flags, BuildFlag_MaxErrorCount, str_lit("max-error-count"), BuildFlagParam_Integer, Command_all); + add_flag(&build_flags, BuildFlag_MinLinkLibs, str_lit("min-link-libs"), BuildFlagParam_None, Command__does_build); + 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); @@ -1215,6 +1219,10 @@ gb_internal bool parse_build_flags(Array args) { break; } + case BuildFlag_MinLinkLibs: + build_context.min_link_libs = true; + break; + case BuildFlag_InternalIgnoreLazy: build_context.ignore_lazy = true; break; @@ -2008,6 +2016,11 @@ gb_internal void print_show_help(String const arg0, String const &command) { print_usage_line(2, "If not set, the default max error count is %d.", DEFAULT_MAX_ERROR_COLLECTOR_COUNT); print_usage_line(0, ""); + print_usage_line(1, "-min-link-libs"); + print_usage_line(2, "If set, the number of linked libraries will be minimized to prevent duplications."); + print_usage_line(2, "This is useful for so called \"dumb\" linkers compared to \"smart\" linkers."); + print_usage_line(0, ""); + print_usage_line(1, "-foreign-error-procedures"); print_usage_line(2, "States that the error procedures used in the runtime are defined in a separate translation unit."); print_usage_line(0, ""); @@ -2694,6 +2707,9 @@ int main(int arg_count, char const **arg_ptr) { print_all_errors(); return 1; } + if (any_warnings()) { + print_all_errors(); + } MAIN_TIME_SECTION("type check"); @@ -2706,6 +2722,10 @@ int main(int arg_count, char const **arg_ptr) { print_all_errors(); return 1; } + if (any_warnings()) { + print_all_errors(); + } + if (build_context.command_kind == Command_strip_semicolon) { return strip_semicolons(parser); diff --git a/src/parser.cpp b/src/parser.cpp index 13225f622..bf16f5c9f 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -1482,7 +1482,16 @@ gb_internal Token expect_token(AstFile *f, TokenKind kind) { if (prev.kind != kind) { String c = token_strings[kind]; String p = token_to_string(prev); + begin_error_block(); syntax_error(f->curr_token, "Expected '%.*s', got '%.*s'", LIT(c), LIT(p)); + if (kind == Token_Ident) switch (prev.kind) { + case Token_context: + error_line("\tSuggestion: 'context' is a reserved keyword, would 'ctx' suffice?\n"); + break; + } + + end_error_block(); + if (prev.kind == Token_EOF) { exit_with_errors(); } @@ -4055,7 +4064,12 @@ gb_internal Array convert_to_ident_list(AstFile *f, Array li case Ast_BadExpr: break; case Ast_Implicit: + begin_error_block(); syntax_error(ident, "Expected an identifier, '%.*s' which is a keyword", LIT(ident->Implicit.string)); + if (ident->Implicit.kind == Token_context) { + error_line("\tSuggestion: Would 'ctx' suffice as an alternative name?\n"); + } + end_error_block(); ident = ast_ident(f, blank_token); break; diff --git a/src/types.cpp b/src/types.cpp index 256c654ac..97512d29b 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -768,6 +768,7 @@ gb_internal i64 type_offset_of (Type *t, i64 index, Type **field_type_=null gb_internal gbString type_to_string (Type *type, bool shorthand=true); gb_internal gbString type_to_string (Type *type, gbAllocator allocator, bool shorthand=true); gb_internal i64 type_size_of_internal(Type *t, TypePath *path); +gb_internal i64 type_align_of_internal(Type *t, TypePath *path); gb_internal void init_map_internal_types(Type *type); gb_internal Type * bit_set_to_int(Type *t); gb_internal bool are_types_identical(Type *x, Type *y); @@ -780,9 +781,6 @@ gb_internal bool is_type_slice(Type *t); gb_internal bool is_type_integer(Type *t); gb_internal bool type_set_offsets(Type *t); -gb_internal i64 type_size_of_internal(Type *t, TypePath *path); -gb_internal i64 type_align_of_internal(Type *t, TypePath *path); - // IMPORTANT TODO(bill): SHould this TypePath code be removed since type cycle checking is handled much earlier on? @@ -3160,7 +3158,7 @@ gb_internal Selection lookup_field_with_selection(Type *type_, String field_name mutex_lock(md->mutex); defer (mutex_unlock(md->mutex)); for (TypeNameObjCMetadataEntry const &entry : md->type_entries) { - GB_ASSERT(entry.entity->kind == Entity_Procedure); + GB_ASSERT(entry.entity->kind == Entity_Procedure || entry.entity->kind == Entity_ProcGroup); if (entry.name == field_name) { sel.entity = entry.entity; sel.pseudo_field = true; @@ -3576,8 +3574,6 @@ gb_internal Slice struct_fields_index_by_increasing_offset(gbAllocator allo -gb_internal i64 type_size_of_internal (Type *t, TypePath *path); -gb_internal i64 type_align_of_internal(Type *t, TypePath *path); gb_internal i64 type_size_of(Type *t); gb_internal i64 type_align_of(Type *t); diff --git a/tests/core/download_assets.py b/tests/core/download_assets.py index 50137f563..7874b7e91 100644 --- a/tests/core/download_assets.py +++ b/tests/core/download_assets.py @@ -4,49 +4,201 @@ import shutil import sys import os import zipfile +import hashlib +import hmac TEST_SUITES = ['PNG', 'XML'] DOWNLOAD_BASE_PATH = "assets/{}" ASSETS_BASE_URL = "https://raw.githubusercontent.com/odin-lang/test-assets/master/{}/{}" -PNG_IMAGES = [ - "basi0g01.png", "basi0g02.png", "basi0g04.png", "basi0g08.png", "basi0g16.png", "basi2c08.png", - "basi2c16.png", "basi3p01.png", "basi3p02.png", "basi3p04.png", "basi3p08.png", "basi4a08.png", - "basi4a16.png", "basi6a08.png", "basi6a16.png", "basn0g01.png", "basn0g02.png", "basn0g04.png", - "basn0g08.png", "basn0g16.png", "basn2c08.png", "basn2c16.png", "basn3p01.png", "basn3p02.png", - "basn3p04.png", "basn3p08.png", "basn4a08.png", "basn4a16.png", "basn6a08.png", "basn6a16.png", - "bgai4a08.png", "bgai4a16.png", "bgan6a08.png", "bgan6a16.png", "bgbn4a08.png", "bggn4a16.png", - "bgwn6a08.png", "bgyn6a16.png", "ccwn2c08.png", "ccwn3p08.png", "cdfn2c08.png", "cdhn2c08.png", - "cdsn2c08.png", "cdun2c08.png", "ch1n3p04.png", "ch2n3p08.png", "cm0n0g04.png", "cm7n0g04.png", - "cm9n0g04.png", "cs3n2c16.png", "cs3n3p08.png", "cs5n2c08.png", "cs5n3p08.png", "cs8n2c08.png", - "cs8n3p08.png", "ct0n0g04.png", "ct1n0g04.png", "cten0g04.png", "ctfn0g04.png", "ctgn0g04.png", - "cthn0g04.png", "ctjn0g04.png", "ctzn0g04.png", "exif2c08.png", "f00n0g08.png", "f00n2c08.png", - "f01n0g08.png", "f01n2c08.png", "f02n0g08.png", "f02n2c08.png", "f03n0g08.png", "f03n2c08.png", - "f04n0g08.png", "f04n2c08.png", "f99n0g04.png", "g03n0g16.png", "g03n2c08.png", "g03n3p04.png", - "g04n0g16.png", "g04n2c08.png", "g04n3p04.png", "g05n0g16.png", "g05n2c08.png", "g05n3p04.png", - "g07n0g16.png", "g07n2c08.png", "g07n3p04.png", "g10n0g16.png", "g10n2c08.png", "g10n3p04.png", - "g25n0g16.png", "g25n2c08.png", "g25n3p04.png", "oi1n0g16.png", "oi1n2c16.png", "oi2n0g16.png", - "oi2n2c16.png", "oi4n0g16.png", "oi4n2c16.png", "oi9n0g16.png", "oi9n2c16.png", "pp0n2c16.png", - "pp0n6a08.png", "ps1n0g08.png", "ps1n2c16.png", "ps2n0g08.png", "ps2n2c16.png", "s01i3p01.png", - "s01n3p01.png", "s02i3p01.png", "s02n3p01.png", "s03i3p01.png", "s03n3p01.png", "s04i3p01.png", - "s04n3p01.png", "s05i3p02.png", "s05n3p02.png", "s06i3p02.png", "s06n3p02.png", "s07i3p02.png", - "s07n3p02.png", "s08i3p02.png", "s08n3p02.png", "s09i3p02.png", "s09n3p02.png", "s32i3p04.png", - "s32n3p04.png", "s33i3p04.png", "s33n3p04.png", "s34i3p04.png", "s34n3p04.png", "s35i3p04.png", - "s35n3p04.png", "s36i3p04.png", "s36n3p04.png", "s37i3p04.png", "s37n3p04.png", "s38i3p04.png", - "s38n3p04.png", "s39i3p04.png", "s39n3p04.png", "s40i3p04.png", "s40n3p04.png", "tbbn0g04.png", - "tbbn2c16.png", "tbbn3p08.png", "tbgn2c16.png", "tbgn3p08.png", "tbrn2c08.png", "tbwn0g16.png", - "tbwn3p08.png", "tbyn3p08.png", "tm3n3p02.png", "tp0n0g08.png", "tp0n2c08.png", "tp0n3p08.png", - "tp1n3p08.png", "xc1n0g08.png", "xc9n2c08.png", "xcrn0g04.png", "xcsn0g01.png", "xd0n2c08.png", - "xd3n2c08.png", "xd9n2c08.png", "xdtn0g01.png", "xhdn0g08.png", "xlfn0g04.png", "xs1n0g01.png", - "xs2n0g01.png", "xs4n0g01.png", "xs7n0g01.png", "z00n2c08.png", "z03n2c08.png", "z06n2c08.png", - "z09n2c08.png", - "PngSuite.png", "logo-slim.png", "emblem-1024.png" -] +HMAC_KEY = "https://odin-lang.org" +HMAC_HASH = hashlib.sha3_512 +HMAC_DIGESTS = { + 'basi0g01.png': "eb26159a783a4dcf27878754e34db6960e992072fc565b12360c894746bc6369101df579e3b9a5c478167f0435e89efb2ab5484056f66c7104f07267f043c82d", + 'basi0g02.png': "f0f74d33ee4b3d3c9f1f4aacf8b0620a33cf1d5c6e9f409e11b4a6e95f2ab1c9159c1bd0bcf6f9553397bf670f4c92712b703d496665d4c6e88fdaf6a0c98620", + 'basi0g04.png': "7b81665f353ff6347304b761d26b4f1baa6118daefc4790f4b0e690150a4e6306514f2aef87e2c39e83e56a0b704df987b10a5366244da58697cda4d5d2745c1", + 'basi0g08.png': "6c809574674494d10eb04c58191c4e0b35813c45962ecafe36a9fe5ba44e5d74ba098e0a524a30c1508eb2dad601f04d5230dceb61a307ef1120f07a8bcbc92f", + 'basi0g16.png': "dd439069fb704b8deff3de822314c012e91a0bd84984d2e79888c6394b78557a0ae6197a7b0a4d64eb4e16fc758946c4f1f13d0d06e512ed9743c4a355b02488", + 'basi2c08.png': "e851fb030f88ead2541a01591882dde5fd9f5dea6bb2b11b374394ed86abc7289e72c4c90808b261aceac13111d3c05b39033168b42ffd1c7ea367314b3a8dc5", + 'basi2c16.png': "e0f81dd459860f7eaf04a2c54932547f41cdc9903a1295a26cc4a2087fd79c98a2e5d5e74f22345dba08b1eb12f3f53c9b904c88b756cbae0c19f9d680e2f1e8", + 'basi3p01.png': "aa21cbcd5d64e6e88056af907509f3b98b00d105198ea2a669fcb25b6966f06d5e4e3afc160b2382935e8ab8e7ccf61733424dfb39b9e864306b82f8355bbb58", + 'basi3p02.png': "d6182370236630d42fd75eed7dc54079ddb7fa9bd601eba22a8dc3331dce31b9a9465027145c29bd56cf778ab0ac029df6aa6481ef65c9464a1ce1d89423faa5", + 'basi3p04.png': "2b35fb98884da370f25833d25f0ab4b188cc26440321e95519131c675818c128b2029d38b3477ef94d88052ec6e9f8b1f7410c5576ce0b47b2fb7a5ba771ce48", + 'basi3p08.png': "7415890831958ca34c73de3e33a9c88980e788d10c983c3a00967886f05053d359499bf0bad386af8ee1bfdb73f666e1d541b0ab682c6092ebdbad3d93e145b1", + 'basi4a08.png': "22ab23a3070d9f1316e8c65b333745e4abf6dcbe63d9d0ada7f6881604b498a92e5b49eb8c1e32f453f4319d94d3d0f48441bac2e79ea528fd7ace0dbbacea9f", + 'basi4a16.png': "2b1436a619f91cf4045e18acf03201b5e9c7774fc77e4c3f38d668984d98543fe64978e80854f30adfecd89b71632945250508bea9eb1ce8e9145e3e55bdeece", + 'basi6a08.png': "aea929866edc5e607d7dc90fcd871f4b6d548abb379b9427fce75a773705e0d8c3ed03bb64e530482b72973eb09844638db5db93666ca1605ff6bbaf194f70e8", + 'basi6a16.png': "29b6ce7c2469e24587b87559f85551334c51bd9d7867f4066c0f7dcb01d710e11e87ee8654c91dc986454cd70f8bd6021e2086ea40e48a28d68a9bdf2283573f", + 'basn0g01.png': "52da610af6f97b03fd8e9f8e52276227f57a97e2bc7e47ae9484b2a37472330f8f5ecef2d6de7fde8f7eb8f144f233bdcf8a3d716c5d193e44d9590af2709cea", + 'basn0g02.png': "676c727faf143af658ed6c6333b15e50387c566c1846a4dda636ed4a2dbb1c0d6d32f0db635479f6851047a32c6d9c52898cfda004ea986853f3ee13750ed90a", + 'basn0g04.png': "123a6652b56f5b858373836509f6b7433221e6ff4eb9ce8a68d0d12bfb27cad0c1bb0cb159523ef1ae5997cb07f994bfbfeabcf0a813aa83495f8269a7a6c4e5", + 'basn0g08.png': "ad5ff30613a462a9b61242d42bb7c854b8247d80a1d03a3919dfdfe8a91c8a962ff51932b2411f714f1be7b803cbd4605c1d4441882cad7e8f44dd8d927198a4", + 'basn0g16.png': "40a96ed10ad5cc58180701e0bb6d6f36c1752c8b8329a80be2960535ad9e168469efbd8f3dc825b57bf65e78a3b61835f19697f2a22511f79c06ce2c6a0034c0", + 'basn2c08.png': "fd92ba13d2038c632fd8bdd3e33971cc69f561bee1eb04ff7920625c6771e0cf7fdda29e48b8a6ca71702c0624ebbca232793f28bb2073b0247d30ce0c549ad5", + 'basn2c16.png': "f6b3cfbc70ae502edbeabde828823dc079dc4e9a586a7fc326c70caec3033124121e3ee2e6481e6ce966efcdef9376cb3ec3edb8e677e91563f510bd6f6e83e6", + 'basn3p01.png': "d262c97549cd1d43e36f5990dac051ead80f1456693c8b1e19a8a48796195831a6ddd5c4a0ac44d22fee51ce4d9392c1c40a0be05571b1b2a961691636d69cd3", + 'basn3p02.png': "a00e375e1fbcc23de38b3b11a0fda4d0204f55473f74e37e0bb5c5f391b37c019293ccddbb99196b9457cd0b7fe5b9e34a55dc6b8167b6909b38813e37a95e46", + 'basn3p04.png': "1a6ab4c567e75b20ee6cdb400dd1f7764a05679c35010e6144fede5a55767dd1861df8e6240e1e59d4166e25d972ff05a41cdfd527818b6ec960a0f9d57d0939", + 'basn3p08.png': "b8f99f6410cc1ac0ceb366e93fc1008f45fb2499e39c489fafa143e8e881f334735e118eec93dde687bf4ea524b4548741c520d770ba6d7071e8fdce576644de", + 'basn4a08.png': "4b7758d4fce3bba95ef3d09cff0ab28c21b8bf568156730fd4e3bcea1c1c2d3ff77f53fe3551f617bd01c8c96e929eb20bf04f5c1a84f37c3cd6bacd4730e6eb", + 'basn4a16.png': "aa0c411f8bb15fc801b072f1048de2fd08761fe245ad267e8503eef8ffe1c39be845e99c04245771afe9b102328129f6375869a4e6cec60eeca641b3e5df3a8b", + 'basn6a08.png': "78d7c811c5463ce53a50874baed840ba70c811513e0ff98fda15a08f01ac6a7c7139a9979cb3688451af6b7e2981699be3c27a386d77af5e60d1acc9e23cb103", + 'basn6a16.png': "e1ad0ed2bf5774b2733d23f2ea9570c6edc933298572933010144ef07bfe6a7878f7367a76f2affbf9845d5b69ea3c84b885f9415e18e752fb1bf21d0dd9d9a2", + 'bgai4a08.png': "22ab23a3070d9f1316e8c65b333745e4abf6dcbe63d9d0ada7f6881604b498a92e5b49eb8c1e32f453f4319d94d3d0f48441bac2e79ea528fd7ace0dbbacea9f", + 'bgai4a16.png': "2b1436a619f91cf4045e18acf03201b5e9c7774fc77e4c3f38d668984d98543fe64978e80854f30adfecd89b71632945250508bea9eb1ce8e9145e3e55bdeece", + 'bgan6a08.png': "78d7c811c5463ce53a50874baed840ba70c811513e0ff98fda15a08f01ac6a7c7139a9979cb3688451af6b7e2981699be3c27a386d77af5e60d1acc9e23cb103", + 'bgan6a16.png': "e1ad0ed2bf5774b2733d23f2ea9570c6edc933298572933010144ef07bfe6a7878f7367a76f2affbf9845d5b69ea3c84b885f9415e18e752fb1bf21d0dd9d9a2", + 'bgbn4a08.png': "4fb9b1023c8c7accb93cf42bd345846c787735df01f7db0df4233737f144e2d5348afaededcdd8c2bcf2e53ce00e2ff095c91de14d7818b4b41c396ab85c9137", + 'bggn4a16.png': "302d7c02ddb0be62aeffeeda46957102c13a2701b841a757486cb3eec7b5456cfabc6ee1954f334ad525badc7c607621a72559b01ce338a0f39e2426d0a03fce", + 'bgwn6a08.png': "d380c477775d102288b43c387dbd7b931f85520f2f6151e3ccc5a25764169312d98fcebf69fb86d3d12520edc3de9bfced559ddf73366f0679e52defb9116424", + 'bgyn6a16.png': "b688d395552eb2a8506fa539ee9159b40a57d02c81860bcf76176213504eb10bdd89de7ce9da452e43f2a46c15290755cdc4816738620b27aed45b3ea7f7ee84", + 'ccwn2c08.png': "c4d58269ef360e42870cce5fb0b1134bfe5706f172c5ff916a338978798fc541a463ab4fdb7c91c424fa385f0ac5d6f576967f178b858d7503f609b2daeacb64", + 'ccwn3p08.png': "d89becf7d24dc57c931a8af1b9dc03ae10302785cc67028cec7255e1aa0ffb0d508d894023a98c10a24cf145aa60b93f977acb8231c8fee9d3f0934484757c30", + 'cdfn2c08.png': "a5faf9cfd284d3750ce2c2f8e15d0ff1bca09da4a9d46b8797c7a1a9f2ebe79d7a7a552bad3c3c049d6186460e81e1e7f9b94e7bb98a3c79d2516f6fb7ac6aa6", + 'cdhn2c08.png': "396eec14e76c00d22ee153171243ac531dcf7adad830948dfd5d6f0a84155734b90407e74f8c1ab8cfb0af5084c03f511530739751f8da070379c826545d0237", + 'cdsn2c08.png': "051b0defa4363ceb3fbc44f460f99a10cdd7c15797ea6d8aa62513b8b6fc5000fe542899db464db30eac56d0c9cd2a5d3778c6962f3aaa85a20881951a7f963a", + 'cdun2c08.png': "946074446fb99f0b790146df0f6e362c68e79b46ec7cbc4ce3d3dc9f75f66e58715caac4b3d7aa8fe8360c32abd2702e7228f9c03b4ba2a0d7f2f970a7ba8f32", + 'ch1n3p04.png': "6680e895195295989850129bcf9d0d0c47efca1c3bc363e4ea822c688707955cdcd07ae92e6e213ee388a62e14b51e036f9a9e075ad7b0f736b0cbc5cc4a108d", + 'ch2n3p08.png': "778ba389d9d0bcbe188e2501c7c1d047f1287179b3760b43da0053f0853e77a0575c7179a02f2442b83efa6cc0951b32d09bd7ea3b6848f261f10b8127e4b0e0", + 'cm0n0g04.png': "9e7e94d201a1222383294bd60e2627207b7b99c0bd80aecd677a1b7d8b372de4981b781fb794811d29a4b2c4db4f5a40c953039c31084f8f3de9aff13fbd1dc9", + 'cm7n0g04.png': "33bb0ffdfe54d655683e4e1bd6d963b9a35a6500129b5dd574245e78971de8d19f27b86a76d42056716b90c2bfc950241bfdc6c4b52ee0e125571de36ba61904", + 'cm9n0g04.png': "fd59386d15a1a324c5ff32f574484c1209afe4ad99f7dc12dce45b2a9bfefd33311ec93211fea3a8e61d1ad2f98220b0c15d151be304bdaa7f88126d54299f68", + 'cs3n2c16.png': "93ca3eeba9aef67de15f943fb2383d208ad1a68518ab78c9fa5ea306ad077b789e873f9e453f0354535167aa4e3d3fec715df05e827bf510948bf0e6fa0dacad", + 'cs3n3p08.png': "e8ddabbf0b17db03bcd7ff0c61d08cc971b3b88e3b3ecd2d4a296da8cf7d7708fa5b42ff3d5813d936ab7f5b4bafbf5842fa4c0fcf0cff15258548d2d26882f3", + 'cs5n2c08.png': "4e3eae53e8c27d4c58d8ad8cdff2c06b00a61d1528a41f5566694f10ef33c4a66f40d3d9fc247731c3ba6dfb734c9f2f90ef031c64486fbdf8a825e354fd67b9", + 'cs5n3p08.png': "31ee0f7f789c1203a9b0e81da34960a47017f3fce37bf2b711738ebd535bb3003ef60c2b0b1fca16587a59955c1ae24b9d186d7ead1d3ece6ada2bbfbc5aee85", + 'cs8n2c08.png': "11bbc80c3168f632deb4453f9199c7994255a0f4f2d7d2d2b06a00931fda4c56985b5a2ca8e969893ff2d65bf330c3d3148b80cbf72aacfe0054b612e6ae05e6", + 'cs8n3p08.png': "49ae3a9050487f6cae826407d421f32a8c67977dd057a6e36f1b2e1ec6abdf5cd46c8929ef4d7b565921ed6c9ae0dde89e243714fdf1510503c7d7b8af6d66e3", + 'ct0n0g04.png': "b6a66fda9ad82cb3287a1ef54702926204bbd4186969cdc2e0741a28dae1869ed76939199f44fd7dd78332753cb8b20a53c4bf740e353f2cc4247870cf576848", + 'ct1n0g04.png': "7cdbaebb6be5d9165972b5fa24f2b64ab437f5337f0548f3d212be8aa95e5dee6ff9abd76ec232faafedc4a41ab8825221b6ced2ecab81c1b3ab20042ceb81a3", + 'cten0g04.png': "648769788c3eb4acd06784dc428bab9e7868328aa3cfe3718ee6656e13e40c4502ca5ac1fe6d4baccb666d4a4f6b3a5d3c97d489f9919ae0d26c2dcdc62e526c", + 'ctfn0g04.png': "c40768807f13dee8dd80ab012bf82b7e8551cb20bde3c7b5c4c45ed19c764cb981945ef036292bd9a2838d34b1b52284295133fea326aea9fc391708bf1d1fbe", + 'ctgn0g04.png': "e0cb7a2d983f1c1c38054b02aabeec657e3f85dba3a52b4878798664c8c6db77cef84d01f042368de6e77cd07b7c2cc6e324aa70bd44c2c8a3642f0cc8fc6a65", + 'cthn0g04.png': "b8614c14bc8c32bb3b29d3b0ac9f3d04c0fcaa40818ab86866e2a8ba1e0c6a87a989f499f208a776d47bff8ab09bfa09352d52089b3cd5bf599faf27627a630b", + 'ctjn0g04.png': "02e2e0a5fa8054e7c7e1c583945da06fb31eff9a3fdd1a7c9f76ba3333f20ce60aec8fafe07f608e9d65a6543e97bab0ff8ae66f3995e8035c05a7c53168ca9a", + 'ctzn0g04.png': "ac35974bd1182e339327245ffa1c0afde634b3a67ee9d6e4e22deee983d6d31054e7843cf1720087b88f6510ed70276e9b0bf43deaf861bd16ceb166140352f9", + 'emblem-1024.png': "5b2e174847274069fc8f4e30c32870ddc7c0e3616a3f04fd41583543aa99ac6d9b7d5a63ed1da672c551b4d193568bb58ddac5e87a101b73367c7c3b01e36fa9", + 'exif2c08.png': "e81b85aa36c9aab55754dd8b73d42497c38eddf9ff3c2981529eb62993d8c0ab33d1b5146a350dd8a1c528d42a967733b2f86248ac615e0254fed53d66d0d895", + 'f00n0g08.png': "fa362f0262ce522297ce52bd7d18b1dc28a2eee3e099b4104c2fb6bdc3fbce0b70303e6df31b709b4033b41e8acec29c81d456c67cde741243c9a54f1ba17f17", + 'f00n2c08.png': "040e95e05152c4bb30608556c828f453c46253c7e0ab18984076cde29b5b6afea7b6658cb019a2723af02a5aabadb1af3b1190655256f3477cd54b9ebdd4df91", + 'f01n0g08.png': "5c60761dc803de1509ef33b4e0ee350d15488d73f4b4e2f93311beb19667626f42d91af39873cd078617c5a2e7c46cceb831d53299c3ff2e7486b43a02ce4967", + 'f01n2c08.png': "a2762a0c4905d05469178176966e86ed4f14c3fcf5c88336209cb923d76e73acc94c619947be87b9183afc20bcd002ab2cc84d81897ec8fc0a4bdeb02a2b7863", + 'f02n0g08.png': "adf640a6f60662ad1b47b5666d2ce86489c685284e50d47344af7cda37f4a42697b5e249f5140413bb3c3e563cca09b2693dcea8bd9ad9adad1adf654ce00bb1", + 'f02n2c08.png': "5f70f19d318ff1d9de4c2f728d83952b12b59bfebac213766ef835dd19f8214f56fa92318041eff25e720503542d067bc9fdf91d86016713c68eb1c52870bad4", + 'f03n0g08.png': "742efed3d25ada0449ed60e4fe1dc94abbe494870536946810cc0eef5c3bfbebefd9bb6d1a482cd5e2c2ee0f34a74b2ea796772254d05accb6739c1ab4d19cdd", + 'f03n2c08.png': "adfac7d6dcc7354467cb3f65742e30ecd44a09b5913ffb656664c9c4730e9cfab9c5e0df2ff8995d412b1ea9cd30ec061eead939546bf795e50a2d49cd10bf92", + 'f04n0g08.png': "9f229c609e87e6c3b83fa82f4f59d7b6494b70c7f85cc807b3611a12d5c59953f11c163228f2bb8b2e7ce77ad204e0da099ab06f8fc480d3ab0ca99fef83c23d", + 'f04n2c08.png': "2dd8b926d1f370b3d3ebaa982491fbe446f3c22b89e635c76eeab60c9ccd3ee7cf39773108d2cec647e480d40de88c4173369b4a12a3fccfba9e4040752cfb4b", + 'f99n0g04.png': "b41996ddf1b770d01900c309cfd2f96d6e60df8313cfda3585a731f32166aa447bcf66ef4af907d6417528024961408d06ca0894fbd6a63fd47ee5a9ed541b51", + 'g03n0g16.png': "02a49b9735063a4d1888b550ed961251b150794422b00ca3800ebba09cd55bdcba15cc8dfe0c41e5a99b2f4d3976b32b1cd08aba92f3dfc3960c71e28ec6cb51", + 'g03n2c08.png': "70b3d643218e033959c51279439d80982f338016b4355aff12be51e7bc59a79f5a5d519c0fa5f13db072cc667fb9635654766af2a11ea25c1b6673f554ceb1f4", + 'g03n3p04.png': "7bfab2aef6f2c04063c438a8f5cda38f3221892ec22a83ab3d3441a900b97c0a7184336ffc2e0c6748e4d931fc80855eed5d6b208ba6ac0709ef02bfbab3e8f2", + 'g04n0g16.png': "9a1d60c89bd63e1f2c81adf1ce7025b7f465e00f0c5142d8a67b5a92e2b042d41a352704969f237883e376bf50c911db196d46f8c28c30ef5763e1e717710c8a", + 'g04n2c08.png': "8e482c99cbc90e6e4aa678e5dbdc39f5b432d740ff260ab1ec04ffa199d97ed2e06491cf88eb0bbbda2f4133f174cf3741474305d9645e0268916aaaab43299d", + 'g04n3p04.png': "d95a52bdc83db74dd19aaa56b40bcbcea268492498c7b2348882a4a5ea70c2b258462c3d5cef85e5372188f21001f719afeb2fac635006486c8fc84b96cc4622", + 'g05n0g16.png': "75954c2e19aa2ba43f7011adecded403035ecb21595a5d116896d2bfc1b71eac42c9b6f008a748cd21b70004921832b3e0dafa1fc0fda4c51ad44cd2b4d782c9", + 'g05n2c08.png': "272baa8dc73cbd63f4fb9545288cfdfcee544e266c9074b73b401895188a123960a6000959f9c034f7b5abe2bfa5e6185253447bac82e9fbfa9634d7e9981d95", + 'g05n3p04.png': "81105d25df2bbbdce60e90cb9a7d0784326bc3c2857fdca4f1f3ef7ab301627685057b97b8d0c0c725d92bc0b48aa1b156dadf5e302ca35917f0b407689ba054", + 'g07n0g16.png': "cb6babe4e25f4cc7e0c3602d9f0e9e538f46a4c4e40420c29521799c528da31afd07b614ae64fbc0e9d0904c9f3e7395b31452abdc69c6a03bf1b5817035b669", + 'g07n2c08.png': "c61e8f936afda939d6497687597d3381485b7cc00716101fc4d6f3abf44df63659b762c77ee252a8735f8e0be0809961db17abbd42c5deab5bad10d0b6b28a55", + 'g07n3p04.png': "8151fa9e9ccd1991a05ea129a7363e23de80688c65d0554c7f3142ed7099d01d82d8ef122986693718f221202657ff965b1b6387a237b36ae741e3d4ea693280", + 'g10n0g16.png': "28ad93f3bebed928c3b0bb4beecaa1b1b55e480c7922d2a36c8f92fc0de012adab523c42f22871b82c6683a7ae74864ed1c35a76cfad92dc6692be0b78c22f50", + 'g10n2c08.png': "4b922386b48c0dd51aee3852da4e52c5c4f3eabe3fcb000e4cfdf0c0e8b27d6a6f77fed944932726fe884f468ac24d89c5c46d65db99be1ae797bc4bbee4cd01", + 'g10n3p04.png': "9b106a0db8ea7e4bc3876beed0f13d83b6f3d6d7d7211441379dd8d18db080f5dc81c6d15312cc3c8ae569b991852ad48f167229dec033f1a974d2a95c83cb3c", + 'g25n0g16.png': "0910ee601a4c4cb546c3bf2b5e8a799d199e34e1434c58c75ddad17f2b295920cf3dde9fe05eee19689705f76b11474b4edc73f4ff346b6ab2d02ec40a13d3cb", + 'g25n2c08.png': "080ed57fd4185c00c6c70e48c27612621393a6ef3987aefd1481611f74d0aebc58d1a90386e4e7bb0321eca961e97cd403a7e727f7324196c5a3cf0e07bffce3", + 'g25n3p04.png': "1deb4281d9792af858e715c39ef7e6756f3004845d87f52054efc9f02c679b2b1b6c2a548a5e6a3f31604b115469ba4bb81510470a47ff9a22b133427375a8db", + 'logo-slim.png': "0104624a95b1b8a97bb5013927cb8fbe330a8c9e7197814147702702cd1d44cdde956404786bb0e69927c6b03ed8031bab566599b1291b995ce747f7cb2135eb", + 'oi1n0g16.png': "40a96ed10ad5cc58180701e0bb6d6f36c1752c8b8329a80be2960535ad9e168469efbd8f3dc825b57bf65e78a3b61835f19697f2a22511f79c06ce2c6a0034c0", + 'oi1n2c16.png': "f6b3cfbc70ae502edbeabde828823dc079dc4e9a586a7fc326c70caec3033124121e3ee2e6481e6ce966efcdef9376cb3ec3edb8e677e91563f510bd6f6e83e6", + 'oi2n0g16.png': "aab1bbfc7b711ba66260985bd8bda6ffaa1e09a0a546b2fe8869b508d823a9e5a412ba6337355a81d87f010e9db8c95eee5f5084b21ddd5cca5d7db7725603b0", + 'oi2n2c16.png': "8d1dd257f3b1bf44ef0bf38338a1e3f2ff78670ac779959751a56231109ca1ed82414f50a221aa45333263073e1e1a950ac8df8e5318e2ed695422d49400c540", + 'oi4n0g16.png': "7675dfa4cff547c3029b21cc892b90a8647199dc9290add932535b04b4eaadaedbc338704f98a075f4690b87815eec8cc0f90a3dbaa2a7809aa03f238ebc5815", + 'oi4n2c16.png': "66313c9d4731e2a9fa006ee9e43c6ac4a3034ce2826c6213f67bfa349bb8bb3cfd8acd2c4553fd1fcd4b2f43993a54539ec8b7fb7f07b3a406adfe919f17b065", + 'oi9n0g16.png': "5615cd4c277be96b21031827d08c8fb2971fda090a0031fd34594f77f7cc558bc68917542597a32bc39c0cd29f7759f0f0429203aa285c163bba8c8f78894e72", + 'oi9n2c16.png': "e2184c00b952a3aa53078a5f995715fa683718a9cbe42705fae3a7c77b236ee6ad706f6dbf2c243aeea17e2c53e84724907724634545e065dd16ff400f5677ab", + 'PngSuite.png': "af1d473e986b3f5cb1006340f8f99156e980e2f8c9f804f0e27c57a51d0dec332a81d99c6e50162f63792d89da44857a6072f8431aa735f1e8f86c06520eff4e", + 'pp0n2c16.png': "82ee5674861b5f9bdab6cf41910d980fc33b5188e191b8892b051dc3b3bbceb4c6d421cbed7bc9b71a9a14db43991c0458ed2cbe5166939f1cbb1e20e445e8b1", + 'pp0n6a08.png': "71c0d4c87b6b2644a4529cd240c8d583c25d45e79fd8bb71ca850dada37e46571052b2da28b926a8194169b82da505c9a3e3a701816d91ac968ad6ff41132b70", + 'ps1n0g08.png': "b273e94c2f826640b10b27b50c605be06541b397ea1289be6f4ea821dff6c7b4b209ec8817a315db442de04c975b7cfecba07b51c6cec965ab9062c05ba04edd", + 'ps1n2c16.png': "833993b81801432eb3a9dbca81f4fdd8ab720c76f8d99a2d298fa1dc4ebd19759c158dd10a68f690f999ea643f62fb7e779e916df86aeb05c43bc4db62aa520b", + 'ps2n0g08.png': "4abea03946d751f03e1438e5987ae691607e528c577db52e893051b54a5d147969dd965e44aaf5540fea75baad873327d76aa71a07c81de31f04f3b781d01e3c", + 'ps2n2c16.png': "bfea51d7be49c04293de034c7649472d34becb663169608490916795fe988df7b812ff8950a3f8d896ee27756effcf9fb525d8d455226cf3965595ee85188581", + 's01i3p01.png': "18b405c902977d2553aab1738a3c00e602e40d11c121a7007c9b7b4cc499aba1fab12fc12aecbdbd5b5cd2638ec5ca5157b5d8fce5dad3cdc3bea02b0904c9cf", + 's01n3p01.png': "8e3e1c9754ebde8c687355b80eee4bf0e0ee8e37b39b784f1997cd2eb60ece7f077b40c8027b0d7f4b7e8f242c22173a244f4e599db33985187439bd918d4486", + 's02i3p01.png': "3e26a8cf35e3df1650adc1656f2d3e7c9b5e1c7932826cf792cbe2cc538c1283ff145f66e4682d459bb0b4f2a2f9ce7209f1997e336e06ca49a83f75270ccad1", + 's02n3p01.png': "d34685ade19ee550ba52e81657627832cb9ba3655f6fe336ebb5fdc4d35c380e819efc1556e1bd1ca2b4e456727dbc5312eb513e7254dfd057a25963e57f0ff4", + 's03i3p01.png': "818a2c91d6c0f96b13806d945d1fc1b4c64f17a9b6a2ede2658c84e20269cd80289312a163761165f0d99e1824f283844f1b4696af314c05714fd349acf7609e", + 's03n3p01.png': "fe847a62eb64bf9db4d9751600b19333f057b626f2f2eb80ee78a3374ae562944c2ebc9c2712f3bbf862798ef9205f38297cad44e8df5dcd96c158ca2e9d9233", + 's04i3p01.png': "1c63332a0d2f31b3a6457038ec2b8c5b4bd3192320fb1c44873947375dcaa028ea07151853e53c6f3fff6878cf90adedea35ae819e5a1b2dbf92399b29464d56", + 's04n3p01.png': "1312d9f3e5bb07b6cbf0c6798c3ae9b0a6cebae465ae6d4ba115ef585616b3b1f7723c6481fcfaa00626d6c62e4fbff7023faf1e92eedeb5354b9805542d43b6", + 's05i3p02.png': "13225a16a79579c4040cdc03f11c71d8589ab322a4f3926e32d9499fe4ca8503a43870e532b2da2597a6c3dd89c3904428cf89c25a8637d40bb3a353017cad5e", + 's05n3p02.png': "d07f2ef30c06a29b9c5c6a52ce1485a3bb9dacb5f119c2829c4cfd69c8fa272d6065eab21a5acd016bdb4f4c724214e8a737c2b76e0f0151e6afcbe5586a37ad", + 's06i3p02.png': "b386f0387e8496849b6d325e710440f7937a403b123886a52af8327e69e411fd632db19daaecfe2e712d49279630515d7217533112acde73cb429e2cfa465b63", + 's06n3p02.png': "df0968c77975f350a86fc09c047d9e3a0a2b71890a0ae67bdfedb23e7f0ce303ff883a463668e10df1dcf2e57cea8cf1fc7c836f5d13a73c1ecd8d66284fc0c5", + 's07i3p02.png': "0f67816f188ce11f15d0f345d2695f1920a322d84be3f332d542c5d20d10a9cef2cebf1e8ae778b25677beeda229c06221eb3450b851ea0e8cd102e5cad14e66", + 's07n3p02.png': "0af60c935e2da2a8a3173edf614085ad0df095c882a140437bdf93ecd5494cfeb5c068dc7ea4d49e181c67d26dd9cf8c969bb2d95f2fbce212ddf5817dd7f642", + 's08i3p02.png': "3204dd0879b6b1284f197a0437e674c4280adad180d4a1d37dff1555be1924d6234dad5d02266aa575d782c53fa52fd4580d452482ba939c732c09709075306f", + 's08n3p02.png': "135039621ce2079465ef49c1b7e5a5aeab299993d2bac864d822ff0669843df1e733a729ca5226ec05c94ddfebdcb2f4b78699fb3adb741db993d9757b4ca71c", + 's09i3p02.png': "dc4d8ed06a81fcd604f949f43e7d5f482c3ad9efd113d220b709de38ca0ca1a340f4cce7e929ca6323390b4ea7c4399cf2f1f2e34c1ef1b38c8296b51d7e8f4b", + 's09n3p02.png': "96b8204f7008899993d8d277ff42c8eb7c85e7cd522cae2e9cf28b8e10e3904c7ec2e3227372f397f6c5a381875dd747a42409471a29ad5049240417ec1441f3", + 's32i3p04.png': "a4de495c70f54eeccd115492a0dfe1cbbcf7f308343eacf6a57515d7a248b356a2639f5e88246d630c8713724cfd7ab1d5d388c677f026a1c5c9b4270a837c67", + 's32n3p04.png': "757009a2fdf19d1187d85930eeb4e75c6831387348fd8e618d1ef971c27d2682b2464b4160a743a6c6d712553fd7fe1f0e5d78226e348f270093495297ec83bf", + 's33i3p04.png': "19259eaf76a42fec949a21c4c55715247a027c2b59ba4bd0f45fdea1f3406cb475c33213b662fd64089b697a6cd25700364f76923dc2531fa0b39546242b3356", + 's33n3p04.png': "3f42b5f3896c1a47fe5dff9921d56234b4326dcffb70a7c6b1f0e7193a6f8f898438635f3b1cfef92c59d7ab827e2a3f40671d97c8547c8e7063a0076c97fba9", + 's34i3p04.png': "db0f7fe138fd732eae4a5c1b8d013167eb3be4afa86141b3e6ad096eabec67644e3108189311b3ce2c78f891d1ea7f5dfa1c30be59509edf123696064eecd00c", + 's34n3p04.png': "e35d9338637ae4c7a1c74a0e73a5c4ba405c2b0d36efd92512b7572d418c25e7d06361be2a8d16323c2708ff3921da24b76be5a41bd3cccf09c27ad472078261", + 's35i3p04.png': "9f0602e1160b81c2e88fc30daf295ff29c4f6faa5a3391c69d895621e7ab76e2071ced6f5a798e294f69621bb32272070ff4ceeeb1436b1cf03640417961a9d1", + 's35n3p04.png': "f12e6a7364073b7a010db0cf952989f5f5da20c592b0256efabb5e82e96d928dce7695c2a0af0749ddfa2739e3ca985463eb0f4a7fb6b8ab0638d65079fc6265", + 's36i3p04.png': "a2d0374bba6fb665deda98b1bd0ef767243b7a974b9f00c78d54bdbfed2c00decf6faef95816ef711efdc359247142be08ce2b86f7860b7384948ba394b4dd21", + 's36n3p04.png': "e200a6869dba1fc9e2eeeff6e686e02313c366a990bfb5582f66dba486251392a465db03806092543008e1130624f1d16cde61613d0ae2a9589941f69a1608db", + 's37i3p04.png': "555f1f7ec2d8ddb58ced7162a4dec315780be13b7cb9ed6d8978046c7fbcb91b4ecf6fcc5c99bd5b8b8d348e4cd202d882a31dec1ecd25156af8968c4a06fbff", + 's37n3p04.png': "d28b3f442b481214774d543924ab07b75fee5916262e6404992962184ea0059ca34fb32d14076642ecd83a3063966ea80676e3165759632782ffd844702cb74e", + 's38i3p04.png': "d4fe0179effbf28f7d28c0192de614512870367cec14ca04d86eb9fff9d6864b1074a68144023244e46cb69ad601e81632c36eb2ed307a32a3c37b7683f882d5", + 's38n3p04.png': "19d23ca8b9b44d26bc9173a69d1d8332e4e7b2ce6e6422195e71dfd0701158023253b130a831a035b2fce0a1556004e8de74e893caeea3d12410909e6e649831", + 's39i3p04.png': "f0c783232707d288b086398565918079e510677742bb5dab09b4520687a06809ae328d24508ebd8f5c26cf85105300ba98e55c29e3773579929839ed9ddbf7fa", + 's39n3p04.png': "39763c31a17edf2751442cf45ae3cc315623ed5b04141bbced2ee8d233485b2d1a2cc0678d60a1c84e3d89a7513634bfd9c82b58754cdfe95885f7a54ff18e2c", + 's40i3p04.png': "d33b29e6669accf1325e8212c555a6cb1d8413c445140aecb62eb6b40912743ef7c6298ad4bc2e232bc448ddaba37f79fa4d25e0cc8e3d53a5ebc93f8f984555", + 's40n3p04.png': "463eb60a2f0884fc368ea0650c5b7b6469c1429e5f006a6537e4aac721094bbd57baa6bcfe4025939089e27b344d7077ff09618e9ce3a5bd40ee3fe5a0e33ce0", + 'tbbn0g04.png': "24fb55d9fed351946869552edb15bf20a2e7a050094ca4b51ebd135958f8b77401e0e9b18618de0cbd18f835e16df24dc57ef094d3b456f0eb9f73c31748ce2a", + 'tbbn2c16.png': "ee98ae3a1cb4a851830ee3e8f4112d08bd74c2a05b778ce51102780ba9d7170c5200c9cc4e1a5c0833618ebe137595eb8fc0591b8798bb6e4e94c234f8cbba3b", + 'tbbn3p08.png': "ed325815b8525d3a5fa37c968b7c85946add7c08abd1c66d86e0264951cfa5a377078b910a78cc664ec2c43d352093c2609b8d01c9572f4ba922d98264e55c04", + 'tbgn2c16.png': "e6da4190d4cea04b0002d598d68c0536448899dd8fca4931b44bc8ea6d47e6946c55ebc5d2049936db2f7f52caef124648d25a360e838571f5f7cb2795eb3657", + 'tbgn3p08.png': "865358d285a8d8682a16b050d9c1b7492042e1a217b0b5753ad28ae1a698dd77150f8cd6510f345157e1efa1411b4e4d5938a81024c150c9d5e76e423105d9c8", + 'tbrn2c08.png': "cc3cd3b8b6cc9920914e0184bdedcf9e59975db3f99c39b93ea1202cf6e11689eb966fc40ae2caca8ef224a8aac03723142b58b701ca2a02fd73a62e379f7a6b", + 'tbwn0g16.png': "fa8359bf8cdac3ab9ac54cd4f1e96b1469ff3e3494102be179b5c7394a4e37953ef54f5e1ccffe771b4f028225ec164b410b0d08f82224ed93a654433feb14fe", + 'tbwn3p08.png': "a0e10707fe9df085596a724561ba6c80662f87095ba479b2345c985f4beb2933f7767fe3d07b30002591259dc14012f4b26fa9b503cc75fd644def7c27c9f2e6", + 'tbyn3p08.png': "9920b40b016c4a05a094c28a989d06e108e2ebd5d72c2a6ddca359b68ad95238b0b6dca0f60b78c56b551a2e44f924d5a443071bda6f6e31669b0a78c09b18af", + 'tm3n3p02.png': "e9910a8ccb78a10980c55c6ca7115757b48075e42c14a83aece92a7f85eee538d5e1d9301efc443a867628993ceff1c13aebcc574641ad85eec48ae05df9997c", + 'tp0n0g08.png': "57fbf8a07060565c23918420952d1feb506ce5b1bdb25f22d41ee1de4ce9655c6dde04b9643d2491b59efba229b7e0cacd6799010a89005802c28a300a4e578e", + 'tp0n2c08.png': "eed3f6c18bd81d96870a47c737574746293c71c517b6a5ba88afdad5ef89fa30d975717f8a8f84ec16cb98390353934cbdd6e4b099e86f0ca3fe8d50fa07bb11", + 'tp0n3p08.png': "9650347d0f4a1a6596828f48766949947148952c93c4899541324a48289ea558c5d7bd1a076ac0e32f71d197e478ffc418e424c52b3fcacd2f94eaae98a566c3", + 'tp1n3p08.png': "fbd0f987d98d96f85679ec237c05925032e8d7783551b3f3cffb1b7db6ebdb3afb61214460386b2a3a011826bbda8340757ba22727325eea9fe518c136969f24", + 'xc1n0g08.png': "6aa3e16f11e82378fa7d3767a785840960f2c152338374e3f64f94eb0799e1f29637a1a66435b6dcdbffb9208efbff65a70e17e80f1e05b3038a837dcf79312c", + 'xc9n2c08.png': "7e0d4285bc67345e092656f04b235b4fc273c7892e26dea339dc2bb8df6348d8477f7e6573fe4f40ede1c94b49a60d46ef47ff4f7327fb12cd6de3737e8b5e4c", + 'xcrn0g04.png': "f971b781eb229ada882bb333bbcce956740f9761581d68ba95b49d998b89499bdd4598c4155e72240d6a5b74c04d7081fe284f78fd3f85f2550a3d2171f6efbb", + 'xcsn0g01.png': "9e1d234c3775920546ab9f9eeabdb75457bd823d48ed677fdfe61a95c02c65730182ba7e84209bfbf59de5d1bea533ca57c90ff6a49ea6d5749636f949bdc16a", + 'xd0n2c08.png': "6458d4b8f10a01ff86207496fbf38b25c35857cc537e9e11085fd5fa7befe956e707e6c1c61bdd76a393a816fdc916e2003fcecf5b33dfeb53c4bb071110eaf0", + 'xd3n2c08.png': "fdf261941945d1231ff3b8e91db063ac5a52e8e56f1fc80c5c51149ed255a4eebb4351194d76ae156bdff1eaf5180184c2aa2dd27e4129498279360e00d7db4e", + 'xd9n2c08.png': "b7a3a47c0863bde4ae8aa5ef5fe5d43f8e29abb413dc002553b63d6a4c1fb79eaee66011f1f45887c218aef3fcd63fda847a1b1bc1975252c3b4fcad553c7b70", + 'xdtn0g01.png': "788ed6f9e7ed64e5f4dfa8b62dd88f6f37f7abd1c8e3abf4db2d1c46f0344e7ba638f6721e69ebffa19cf6536f7685f485e9eb548a3cae55131963da05950acd", + 'xhdn0g08.png': "1f06044e4607902e7bd8ba291bf2b9bbb855a881b4a7dde6a21e9f5f9b74f0f43f55a8aa31fa6d1c225d0dc891744943c1544aa17836b3ecf900f041b1cca23c", + 'xlfn0g04.png': "bf3467f8aa9d35f7ae17cd59c3b2d5f6bf110b71afdb3a501ee88306647d669e8419e78b93b995651193a9ff99c849f82530a0bd410cec445feffe36c8df8dd1", + 'xs1n0g01.png': "d1bae1e471886f1661354f23b3564a34c9e1b076bd158ba129388aeb1f287d39ba647269b955bf3cc81f2b962ac6a3eb1a887a8c85243574e84778e48096cf88", + 'xs2n0g01.png': "abd509aa6253d8367980e4f6f4d96bb4b3732287601a7bd3dfb0fa4c70dc3908937c16e6459961421409c74f9952b4693ed1d352dc002bd120a57ba5407cac1f", + 'xs4n0g01.png': "015a1bdc1f878435c3de87feed442e467b3c96f3db3134d1e23653b6759a3a3d68f05325d15992ecce18ec5c00cab7e430c1965ccf36b434d8c9f9a4e8194bfe", + 'xs7n0g01.png': "03dab5037599a58f25dcbd1be556ff60dba08ed3e0e92e5791c53e98041b0ef174a9ebdf75fd997696521ca96a19ca1bb9a5eff929f1a7c0dc1a7d3598d07d04", + 'z00n2c08.png': "9a65f94ebb3614b65e093534a7763f55687144fc9a82e2680e7cad9863d72947a0de3dfe57468e11b578234b8460485e8ee895c681c391d140d84b15c7a40f41", + 'z03n2c08.png': "847fd249d190ccd8ec54afc910afaecf007db7ea5753c18eec8de654b159f4cdf99b70bdd55ec276ce5340fd2ede5290468fe4c6029b5e4c0825ca881a75bde3", + 'z06n2c08.png': "94268c1998de1f4304d24219e31175def7375cc26e2bbfc7d1ac20465a42fae49bcc8ff7626873138b537588e8bce21b6d5e1373efaade1f83cae455334074aa", + 'z09n2c08.png': "3cbb1bb58d78ecc9dd5568a8e9093ba020b63449ef3ab102f98fac4220fc9619feaa873336a25f3c1ad99cfb3e5d32bcfe52d966bc8640d1d5ba4e061741743e", + + 'unicode.xml': "e0cdc94f07fdbb15eea811ed2ae6dcf494a83d197dafe6580c740270feb0d8f5f7146d4a7d4c2d2ea25f8bd9678bc986123484b39399819a6b7262687959d1ae", +} def try_download_file(url, out_file): try: with urllib.request.urlopen(url) as response, open(out_file, 'wb') as of: shutil.copyfileobj(response, of) - print("... ", out_file) except urllib.error.HTTPError: print("Could not download", url) return 1 @@ -55,24 +207,39 @@ def try_download_and_unpack_zip(suite): url = ASSETS_BASE_URL.format(suite, "{}.zip".format(suite)) out_file = DOWNLOAD_BASE_PATH.format(suite) + "/{}.zip".format(suite) - print("\tDownloading {} to {}.".format(url, out_file)) + print("\tDownloading {} to {}".format(url, out_file)) if try_download_file(url, out_file) is not None: print("Could not download ZIP file") return 1 # Try opening the ZIP file and extracting the test images - try: - with zipfile.ZipFile(out_file) as z: - for file in z.filelist: - filename = file.filename - extract_path = DOWNLOAD_BASE_PATH.format(suite) + #try: + with zipfile.ZipFile(out_file) as z: + print("\tUnpacking and verifying using HMAC(\"{}\", data, {}):\n".format(HMAC_KEY, HMAC_HASH.__name__)) + for file in z.filelist: + if file.filename not in HMAC_DIGESTS: + print("Missing digest for {}".format(file.filename)) + return 3 - print("\t\tExtracting: {}".format(filename)) - z.extract(file, extract_path) - except: - print("Could not extract ZIP file") - return 2 + extract_path = DOWNLOAD_BASE_PATH.format(suite) + z.extract(file, extract_path) + + file_path = "{}/{}".format(extract_path, file.filename) + + with open(file_path, "rb") as f: + file_data = f.read() + digest = hashlib.sha3_512(file_data).hexdigest() + + hmac_digest = hmac.new(HMAC_KEY.encode(), file_data, HMAC_HASH).hexdigest() + print("{} *{}".format(hmac_digest, file.filename)) + if not hmac.compare_digest(hmac_digest, HMAC_DIGESTS[file.filename]): + print("FAIL! Expected: {}".format(HMAC_DIGESTS[file.filename])) + return 4 + + #except: + # print("Could not extract ZIP file") + # return 2 def main(): for suite in TEST_SUITES: @@ -91,9 +258,7 @@ def main(): return r # We could fall back on downloading the PNG files individually, but it's slow - print("Done downloading {} assets.".format(suite)) - - + print("\nDone downloading {} assets.".format(suite)) return 0 diff --git a/tests/core/image/test_core_image.odin b/tests/core/image/test_core_image.odin index 54b3608b7..ae92ca617 100644 --- a/tests/core/image/test_core_image.odin +++ b/tests/core/image/test_core_image.odin @@ -1580,7 +1580,7 @@ run_png_suite :: proc(t: ^testing.T, suite: []PNG_Test) -> (subtotal: int) { { // Roundtrip through PBM to test the PBM encoders and decoders - prefer ASCII - pbm_info, pbm_format_selected := pbm.autoselect_pbm_format_from_image(img, false) + pbm_info, _ := pbm.autoselect_pbm_format_from_image(img, false) // We already tested the binary formats above. if pbm_info.header.format in pbm.ASCII { @@ -1912,4 +1912,4 @@ run_png_suite :: proc(t: ^testing.T, suite: []PNG_Test) -> (subtotal: int) { } return -} \ No newline at end of file +} diff --git a/tests/internal/Makefile b/tests/internal/Makefile index 00e46197b..c5c612cdd 100644 --- a/tests/internal/Makefile +++ b/tests/internal/Makefile @@ -1,6 +1,6 @@ ODIN=../../odin -all: rtti_test map_test pow_test +all: rtti_test map_test pow_test 128_test asan_test rtti_test: $(ODIN) run test_rtti.odin -file -vet -strict-style -o:minimal @@ -9,4 +9,10 @@ map_test: $(ODIN) run test_map.odin -file -vet -strict-style -o:minimal pow_test: - $(ODIN) run test_pow.odin -file -vet -strict-style -o:minimal \ No newline at end of file + $(ODIN) run test_pow.odin -file -vet -strict-style -o:minimal + +128_test: + $(ODIN) run test_128.odin -file -vet -strict-style -o:minimal + +asan_test: + $(ODIN) run test_asan.odin -file -sanitize:address -debug diff --git a/tests/internal/build.bat b/tests/internal/build.bat index f289d17fa..da4fe890d 100644 --- a/tests/internal/build.bat +++ b/tests/internal/build.bat @@ -3,4 +3,6 @@ set PATH_TO_ODIN==..\..\odin rem %PATH_TO_ODIN% run test_rtti.odin -file -vet -strict-style -o:minimal || exit /b %PATH_TO_ODIN% run test_map.odin -file -vet -strict-style -o:minimal || exit /b rem -define:SEED=42 -%PATH_TO_ODIN% run test_pow.odin -file -vet -strict-style -o:minimal || exit /b \ No newline at end of file +%PATH_TO_ODIN% run test_pow.odin -file -vet -strict-style -o:minimal || exit /b + +%PATH_TO_ODIN% run test_128.odin -file -vet -strict-style -o:minimal || exit /b diff --git a/tests/internal/test_128.odin b/tests/internal/test_128.odin new file mode 100644 index 000000000..11ef068ed --- /dev/null +++ b/tests/internal/test_128.odin @@ -0,0 +1,59 @@ +package test_128 + +import "core:fmt" +import "core:os" +import "core:testing" + +TEST_count := 0 +TEST_fail := 0 + +when ODIN_TEST { + expect :: testing.expect + log :: testing.log +} else { + expect :: proc(t: ^testing.T, condition: bool, message: string, loc := #caller_location) { + TEST_count += 1 + if !condition { + TEST_fail += 1 + fmt.printf("[%v] %v\n", loc, message) + return + } + } + log :: proc(t: ^testing.T, v: any, loc := #caller_location) { + fmt.printf("[%v] ", loc) + fmt.printf("log: %v\n", v) + } +} + +main :: proc() { + t := testing.T{} + + test_128_align(&t) + + fmt.printf("%v/%v tests successful.\n", TEST_count - TEST_fail, TEST_count) + if TEST_fail > 0 { + os.exit(1) + } +} + +@test +test_128_align :: proc(t: ^testing.T) { + Danger_Struct :: struct { + x: u128, + y: u64, + } + + list := [?]Danger_Struct{{0, 0}, {1, 0}, {2, 0}, {3, 0}} + + expect(t, list[0].x == 0, fmt.tprintf("[0].x (%v) != 0", list[0].x)) + expect(t, list[0].y == 0, fmt.tprintf("[0].y (%v) != 0", list[0].y)) + + expect(t, list[1].x == 1, fmt.tprintf("[1].x (%v) != 1", list[1].x)) + expect(t, list[1].y == 0, fmt.tprintf("[1].y (%v) != 0", list[1].y)) + + expect(t, list[2].x == 2, fmt.tprintf("[2].x (%v) != 2", list[2].x)) + expect(t, list[2].y == 0, fmt.tprintf("[2].y (%v) != 0", list[2].y)) + + expect(t, list[3].x == 3, fmt.tprintf("[3].x (%v) != 3", list[3].x)) + expect(t, list[3].y == 0, fmt.tprintf("[3].y (%v) != 0", list[3].y)) +} diff --git a/tests/internal/test_asan.odin b/tests/internal/test_asan.odin new file mode 100644 index 000000000..2384ada76 --- /dev/null +++ b/tests/internal/test_asan.odin @@ -0,0 +1,62 @@ +// Intended to contain code that would trigger asan easily if the abi was set up badly. +package test_asan + +import "core:fmt" +import "core:testing" +import "core:os" + +TEST_count := 0 +TEST_fail := 0 + +when ODIN_TEST { + expect :: testing.expect + log :: testing.log +} else { + expect :: proc(t: ^testing.T, condition: bool, message: string, loc := #caller_location) { + TEST_count += 1 + if !condition { + TEST_fail += 1 + fmt.printf("[%v] %v\n", loc, message) + return + } + } + log :: proc(t: ^testing.T, v: any, loc := #caller_location) { + fmt.printf("[%v] ", loc) + fmt.printf("log: %v\n", v) + } +} + +main :: proc() { + t := testing.T{} + + test_12_bytes(&t) + test_12_bytes_two(&t) + + fmt.printf("%v/%v tests successful.\n", TEST_count - TEST_fail, TEST_count) + if TEST_fail > 0 { + os.exit(1) + } +} + +@(test) +test_12_bytes :: proc(t: ^testing.T) { + internal :: proc() -> (a, b: f32, ok: bool) { + return max(f32), 0, true + } + + a, b, ok := internal() + expect(t, a == max(f32), fmt.tprintf("a (%v) != max(f32)", a)) + expect(t, b == 0, fmt.tprintf("b (%v) != 0", b)) + expect(t, ok, fmt.tprintf("ok (%v) != true", ok)) +} + +@(test) +test_12_bytes_two :: proc(t: ^testing.T) { + internal :: proc() -> (a: f32, b: int) { + return 100., max(int) + } + + a, b := internal() + expect(t, a == 100., fmt.tprintf("a (%v) != 100.", a)) + expect(t, b == max(int), fmt.tprintf("b (%v) != max(int)", b)) +} diff --git a/tests/internal/test_map.odin b/tests/internal/test_map.odin index 2c808d85e..7d1dbf470 100644 --- a/tests/internal/test_map.odin +++ b/tests/internal/test_map.odin @@ -32,7 +32,7 @@ map_insert_random_key_value :: proc(t: ^testing.T) { } key_count := 0 - for k in m { + for _ in m { key_count += 1 } @@ -82,7 +82,7 @@ map_update_random_key_value :: proc(t: ^testing.T) { } key_count := 0 - for k in m { + for _ in m { key_count += 1 } @@ -144,7 +144,7 @@ map_delete_random_key_value :: proc(t: ^testing.T) { } key_count := 0 - for k in m { + for _ in m { key_count += 1 } @@ -220,7 +220,7 @@ set_insert_random_key_value :: proc(t: ^testing.T) { } key_count := 0 - for k in m { + for _ in m { key_count += 1 } @@ -268,7 +268,7 @@ set_delete_random_key_value :: proc(t: ^testing.T) { } key_count := 0 - for k in m { + for _ in m { key_count += 1 } @@ -379,4 +379,4 @@ when ODIN_TEST { fmt.printf("[%v] ", loc) fmt.printf("log: %v\n", v) } -} \ No newline at end of file +} diff --git a/vendor/darwin/Foundation/NSApplication.odin b/vendor/darwin/Foundation/NSApplication.odin index c87a3d44c..d332345f9 100644 --- a/vendor/darwin/Foundation/NSApplication.odin +++ b/vendor/darwin/Foundation/NSApplication.odin @@ -79,11 +79,22 @@ Application_setActivationPolicy :: proc "c" (self: ^Application, activationPolic return msgSend(BOOL, self, "setActivationPolicy:", activationPolicy) } +@(deprecated="Use NSApplication method activate instead.") @(objc_type=Application, objc_name="activateIgnoringOtherApps") Application_activateIgnoringOtherApps :: proc "c" (self: ^Application, ignoreOtherApps: BOOL) { msgSend(nil, self, "activateIgnoringOtherApps:", ignoreOtherApps) } +@(objc_type=Application, objc_name="activate") +Application_activate :: proc "c" (self: ^Application) { + msgSend(nil, self, "activate") +} + +@(objc_type=Application, objc_name="setTitle") +Application_setTitle :: proc "c" (self: ^Application, title: ^String) { + msgSend(nil, self, "setTitle", title) +} + @(objc_type=Application, objc_name="setMainMenu") Application_setMainMenu :: proc "c" (self: ^Application, menu: ^Menu) { msgSend(nil, self, "setMainMenu:", menu) diff --git a/vendor/microui/microui.odin b/vendor/microui/microui.odin index 1ddad2121..495289ede 100644 --- a/vendor/microui/microui.odin +++ b/vendor/microui/microui.odin @@ -1316,10 +1316,10 @@ begin_window :: proc(ctx: ^Context, title: string, rect: Rect, opt := Options{}) /* do title text */ if .NO_TITLE not_in opt { - id := get_id(ctx, "!title") - update_control(ctx, id, tr, opt) + tid := get_id(ctx, "!title") + update_control(ctx, tid, tr, opt) draw_control_text(ctx, title, tr, .TITLE_TEXT, opt) - if id == ctx.focus_id && ctx.mouse_down_bits == {.LEFT} { + if tid == ctx.focus_id && ctx.mouse_down_bits == {.LEFT} { cnt.rect.x += ctx.mouse_delta.x cnt.rect.y += ctx.mouse_delta.y } @@ -1329,12 +1329,12 @@ begin_window :: proc(ctx: ^Context, title: string, rect: Rect, opt := Options{}) /* do `close` button */ if .NO_CLOSE not_in opt { - id := get_id(ctx, "!close") + cid := get_id(ctx, "!close") r := Rect{tr.x + tr.w - tr.h, tr.y, tr.h, tr.h} tr.w -= r.w draw_icon(ctx, .CLOSE, r, ctx.style.colors[.TITLE_TEXT]) - update_control(ctx, id, r, opt) - if .LEFT in ctx.mouse_released_bits && id == ctx.hover_id { + update_control(ctx, cid, r, opt) + if .LEFT in ctx.mouse_released_bits && cid == ctx.hover_id { cnt.open = false } } @@ -1343,11 +1343,11 @@ begin_window :: proc(ctx: ^Context, title: string, rect: Rect, opt := Options{}) /* do `resize` handle */ if .NO_RESIZE not_in opt { sz := ctx.style.footer_height - id := get_id(ctx, "!resize") + rid := get_id(ctx, "!resize") r := Rect{rect.x + rect.w - sz, rect.y + rect.h - sz, sz, sz} draw_icon(ctx, .RESIZE, r, ctx.style.colors[.TEXT]) - update_control(ctx, id, r, opt) - if id == ctx.focus_id && .LEFT in ctx.mouse_down_bits { + update_control(ctx, rid, r, opt) + if rid == ctx.focus_id && .LEFT in ctx.mouse_down_bits { cnt.rect.w = max(96, cnt.rect.w + ctx.mouse_delta.x) cnt.rect.h = max(64, cnt.rect.h + ctx.mouse_delta.y) } diff --git a/vendor/nanovg/nanovg.odin b/vendor/nanovg/nanovg.odin index 74fc70692..15611cfef 100644 --- a/vendor/nanovg/nanovg.odin +++ b/vendor/nanovg/nanovg.odin @@ -2009,7 +2009,7 @@ __expandStroke :: proc( } } - for j in start.. c.int --- SemTryWait :: proc(s: ^sem) -> c.int --- SemWaitTimeout :: proc(s: ^sem, ms: u32) -> c.int --- + SemPost :: proc(s: ^sem) -> c.int --- SemValue :: proc(s: ^sem) -> u32 --- CreateCond :: proc() -> ^cond ---