From 19188a6e5c64e05366c9d06039c97c8f17506372 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 6 Mar 2025 09:44:41 +0000 Subject: [PATCH] Use subtyping for `Type_Info` to minimize memory usage --- base/runtime/core.odin | 118 ++++--- base/runtime/core_builtin_soa.odin | 31 +- base/runtime/error_checks.odin | 4 +- base/runtime/print.odin | 70 ++-- core/fmt/fmt.odin | 152 ++++---- core/os/errors.odin | 2 +- core/reflect/iterator.odin | 12 +- core/reflect/reflect.odin | 288 +++++++-------- core/reflect/types.odin | 260 +++++++------- src/llvm_backend.cpp | 1 - src/llvm_backend_general.cpp | 49 ++- src/llvm_backend_type.cpp | 542 +++++++++++++---------------- 12 files changed, 753 insertions(+), 776 deletions(-) diff --git a/base/runtime/core.odin b/base/runtime/core.odin index cd7d35540..6e2753633 100644 --- a/base/runtime/core.odin +++ b/base/runtime/core.odin @@ -63,38 +63,44 @@ Type_Info_Struct_Soa_Kind :: enum u8 { // Variant Types Type_Info_Named :: struct { + using info: Type_Info, name: string, base: ^Type_Info, pkg: string, loc: ^Source_Code_Location, } -Type_Info_Integer :: struct {signed: bool, endianness: Platform_Endianness} -Type_Info_Rune :: struct {} -Type_Info_Float :: struct {endianness: Platform_Endianness} -Type_Info_Complex :: struct {} -Type_Info_Quaternion :: struct {} -Type_Info_String :: struct {is_cstring: bool} -Type_Info_Boolean :: struct {} -Type_Info_Any :: struct {} -Type_Info_Type_Id :: struct {} +Type_Info_Integer :: struct {using info: Type_Info, signed: bool, endianness: Platform_Endianness} +Type_Info_Rune :: struct {using info: Type_Info} +Type_Info_Float :: struct {using info: Type_Info, endianness: Platform_Endianness} +Type_Info_Complex :: struct {using info: Type_Info} +Type_Info_Quaternion :: struct {using info: Type_Info} +Type_Info_String :: struct {using info: Type_Info, is_cstring: bool} +Type_Info_Boolean :: struct {using info: Type_Info} +Type_Info_Any :: struct {using info: Type_Info} +Type_Info_Type_Id :: struct {using info: Type_Info} Type_Info_Pointer :: struct { + using info: Type_Info, elem: ^Type_Info, // nil -> rawptr } Type_Info_Multi_Pointer :: struct { + using info: Type_Info, elem: ^Type_Info, } Type_Info_Procedure :: struct { + using info: Type_Info, params: ^Type_Info, // Type_Info_Parameters results: ^Type_Info, // Type_Info_Parameters variadic: bool, convention: Calling_Convention, } Type_Info_Array :: struct { + using info: Type_Info, elem: ^Type_Info, elem_size: int, count: int, } Type_Info_Enumerated_Array :: struct { + using info: Type_Info, elem: ^Type_Info, index: ^Type_Info, elem_size: int, @@ -103,12 +109,21 @@ Type_Info_Enumerated_Array :: struct { max_value: Type_Info_Enum_Value, is_sparse: bool, } -Type_Info_Dynamic_Array :: struct {elem: ^Type_Info, elem_size: int} -Type_Info_Slice :: struct {elem: ^Type_Info, elem_size: int} +Type_Info_Dynamic_Array :: struct { + using info: Type_Info, + elem: ^Type_Info, + elem_size: int, +} +Type_Info_Slice :: struct { + using info: Type_Info, + elem: ^Type_Info, + elem_size: int, +} Type_Info_Parameters :: struct { // Only used for procedures parameters and results - types: []^Type_Info, - names: []string, + using info: Type_Info, + types: []^Type_Info, + names: []string, } Type_Info_Tuple :: Type_Info_Parameters // Will be removed eventually @@ -121,6 +136,8 @@ Type_Info_Struct_Flag :: enum u8 { } Type_Info_Struct :: struct { + using info: Type_Info, + // Slice these with `field_count` types: [^]^Type_Info `fmt:"v,field_count"`, names: [^]string `fmt:"v,field_count"`, @@ -130,16 +147,20 @@ Type_Info_Struct :: struct { field_count: i32, - flags: Type_Info_Struct_Flags, + struct_flags: Type_Info_Struct_Flags, // These are only set iff this structure is an SOA structure soa_kind: Type_Info_Struct_Soa_Kind, + _: [2]u8, soa_len: i32, + _: [4]u8, soa_base_type: ^Type_Info, equal: Equal_Proc, // set only when the struct has .Comparable set but does not have .Simple_Compare set } Type_Info_Union :: struct { + using info: Type_Info, + variants: []^Type_Info, tag_offset: uintptr, tag_type: ^Type_Info, @@ -151,27 +172,32 @@ Type_Info_Union :: struct { shared_nil: bool, } Type_Info_Enum :: struct { + using info: Type_Info, base: ^Type_Info, names: []string, values: []Type_Info_Enum_Value, } Type_Info_Map :: struct { + using info: Type_Info, key: ^Type_Info, value: ^Type_Info, map_info: ^Map_Info, } Type_Info_Bit_Set :: struct { + using info: Type_Info, elem: ^Type_Info, underlying: ^Type_Info, // Possibly nil lower: i64, upper: i64, } Type_Info_Simd_Vector :: struct { + using info: Type_Info, elem: ^Type_Info, elem_size: int, count: int, } Type_Info_Matrix :: struct { + using info: Type_Info, elem: ^Type_Info, elem_size: int, elem_stride: int, // elem_stride >= row_count @@ -184,9 +210,11 @@ Type_Info_Matrix :: struct { }, } Type_Info_Soa_Pointer :: struct { + using info: Type_Info, elem: ^Type_Info, } Type_Info_Bit_Field :: struct { + using info: Type_Info, backing_type: ^Type_Info, names: [^]string `fmt:"v,field_count"`, types: [^]^Type_Info `fmt:"v,field_count"`, @@ -209,33 +237,33 @@ Type_Info :: struct { id: typeid, variant: union { - Type_Info_Named, - Type_Info_Integer, - Type_Info_Rune, - Type_Info_Float, - Type_Info_Complex, - Type_Info_Quaternion, - Type_Info_String, - Type_Info_Boolean, - Type_Info_Any, - Type_Info_Type_Id, - Type_Info_Pointer, - Type_Info_Multi_Pointer, - Type_Info_Procedure, - Type_Info_Array, - Type_Info_Enumerated_Array, - Type_Info_Dynamic_Array, - Type_Info_Slice, - Type_Info_Parameters, - Type_Info_Struct, - Type_Info_Union, - Type_Info_Enum, - Type_Info_Map, - Type_Info_Bit_Set, - Type_Info_Simd_Vector, - Type_Info_Matrix, - Type_Info_Soa_Pointer, - Type_Info_Bit_Field, + ^Type_Info_Named, + ^Type_Info_Integer, + ^Type_Info_Rune, + ^Type_Info_Float, + ^Type_Info_Complex, + ^Type_Info_Quaternion, + ^Type_Info_String, + ^Type_Info_Boolean, + ^Type_Info_Any, + ^Type_Info_Type_Id, + ^Type_Info_Pointer, + ^Type_Info_Multi_Pointer, + ^Type_Info_Procedure, + ^Type_Info_Array, + ^Type_Info_Enumerated_Array, + ^Type_Info_Dynamic_Array, + ^Type_Info_Slice, + ^Type_Info_Parameters, + ^Type_Info_Struct, + ^Type_Info_Union, + ^Type_Info_Enum, + ^Type_Info_Map, + ^Type_Info_Bit_Set, + ^Type_Info_Simd_Vector, + ^Type_Info_Matrix, + ^Type_Info_Soa_Pointer, + ^Type_Info_Bit_Field, }, } @@ -622,7 +650,7 @@ type_info_base :: proc "contextless" (info: ^Type_Info) -> ^Type_Info { base := info loop: for { #partial switch i in base.variant { - case Type_Info_Named: base = i.base + case ^Type_Info_Named: base = i.base case: break loop } } @@ -638,9 +666,9 @@ type_info_core :: proc "contextless" (info: ^Type_Info) -> ^Type_Info { base := info loop: for { #partial switch i in base.variant { - case Type_Info_Named: base = i.base - case Type_Info_Enum: base = i.base - case Type_Info_Bit_Field: base = i.backing_type + case ^Type_Info_Named: base = i.base + case ^Type_Info_Enum: base = i.base + case ^Type_Info_Bit_Field: base = i.backing_type case: break loop } } diff --git a/base/runtime/core_builtin_soa.odin b/base/runtime/core_builtin_soa.odin index ff27a4559..714f87f58 100644 --- a/base/runtime/core_builtin_soa.odin +++ b/base/runtime/core_builtin_soa.odin @@ -91,13 +91,13 @@ make_soa_aligned :: proc($T: typeid/#soa[]$E, #any_int length, alignment: int, a ti := type_info_of(typeid_of(T)) ti = type_info_base(ti) - si := &ti.variant.(Type_Info_Struct) + si := ti.variant.(^Type_Info_Struct) field_count := uintptr(len(E) when intrinsics.type_is_array(E) else intrinsics.type_struct_field_count(E)) total_size := 0 for i in 0.. 0 && cap(array)-len(array) > 0 { ti := type_info_of(T) ti = type_info_base(ti) - si := &ti.variant.(Type_Info_Struct) + si := ti.variant.(^Type_Info_Struct) field_count := uintptr(len(E) when intrinsics.type_is_array(E) else intrinsics.type_struct_field_count(E)) data := (^rawptr)(array)^ @@ -325,7 +324,7 @@ _append_soa_elem :: proc(array: ^$T/#soa[dynamic]$E, zero_memory: bool, #no_broa max_align :: align_of(E) for i in 0.. 0 && arg_len > 0 { ti := type_info_of(typeid_of(T)) ti = type_info_base(ti) - si := &ti.variant.(Type_Info_Struct) + si := ti.variant.(^Type_Info_Struct) field_count := uintptr(len(E) when intrinsics.type_is_array(E) else intrinsics.type_struct_field_count(E)) data := (^rawptr)(array)^ @@ -386,7 +385,7 @@ _append_soa_elems :: proc(array: ^$T/#soa[dynamic]$E, zero_memory: bool, #no_bro max_align :: align_of(E) for i in 0.. 0 { print_string(", ") } @@ -336,7 +336,7 @@ print_type :: #force_no_inline proc "contextless" (ti: ^Type_Info) { print_string(" -> ") print_type(info.results) } - case Type_Info_Parameters: + case ^Type_Info_Parameters: count := len(info.names) if count != 1 { print_byte('(') } for name, i in info.names { @@ -352,13 +352,13 @@ print_type :: #force_no_inline proc "contextless" (ti: ^Type_Info) { } if count != 1 { print_string(")") } - case Type_Info_Array: + case ^Type_Info_Array: print_byte('[') print_u64(u64(info.count)) print_byte(']') print_type(info.elem) - case Type_Info_Enumerated_Array: + case ^Type_Info_Enumerated_Array: if info.is_sparse { print_string("#sparse") } @@ -368,20 +368,20 @@ print_type :: #force_no_inline proc "contextless" (ti: ^Type_Info) { print_type(info.elem) - case Type_Info_Dynamic_Array: + case ^Type_Info_Dynamic_Array: print_string("[dynamic]") print_type(info.elem) - case Type_Info_Slice: + case ^Type_Info_Slice: print_string("[]") print_type(info.elem) - case Type_Info_Map: + case ^Type_Info_Map: print_string("map[") print_type(info.key) print_byte(']') print_type(info.value) - case Type_Info_Struct: + case ^Type_Info_Struct: switch info.soa_kind { case .None: // Ignore case .Fixed: @@ -401,10 +401,10 @@ print_type :: #force_no_inline proc "contextless" (ti: ^Type_Info) { } print_string("struct ") - if .packed in info.flags { print_string("#packed ") } - if .raw_union in info.flags { print_string("#raw_union ") } - if .no_copy in info.flags { print_string("#no_copy ") } - if .align in info.flags { + if .packed in info.struct_flags { print_string("#packed ") } + if .raw_union in info.struct_flags { print_string("#raw_union ") } + if .no_copy in info.struct_flags { print_string("#no_copy ") } + if .align in info.struct_flags { print_string("#align(") print_u64(u64(ti.align)) print_string(") ") @@ -418,7 +418,7 @@ print_type :: #force_no_inline proc "contextless" (ti: ^Type_Info) { } print_byte('}') - case Type_Info_Union: + case ^Type_Info_Union: print_string("union ") if info.custom_align { print_string("#align(") @@ -435,7 +435,7 @@ print_type :: #force_no_inline proc "contextless" (ti: ^Type_Info) { } print_string("}") - case Type_Info_Enum: + case ^Type_Info_Enum: print_string("enum ") print_type(info.base) print_string(" {") @@ -445,13 +445,13 @@ print_type :: #force_no_inline proc "contextless" (ti: ^Type_Info) { } print_string("}") - case Type_Info_Bit_Set: + case ^Type_Info_Bit_Set: print_string("bit_set[") #partial switch elem in type_info_base(info.elem).variant { - case Type_Info_Enum: + case ^Type_Info_Enum: print_type(info.elem) - case Type_Info_Rune: + case ^Type_Info_Rune: print_encoded_rune(rune(info.lower)) print_string("..") print_encoded_rune(rune(info.upper)) @@ -466,7 +466,7 @@ print_type :: #force_no_inline proc "contextless" (ti: ^Type_Info) { } print_byte(']') - case Type_Info_Bit_Field: + case ^Type_Info_Bit_Field: print_string("bit_field ") print_type(info.backing_type) print_string(" {") @@ -481,13 +481,13 @@ print_type :: #force_no_inline proc "contextless" (ti: ^Type_Info) { print_byte('}') - case Type_Info_Simd_Vector: + case ^Type_Info_Simd_Vector: print_string("#simd[") print_u64(u64(info.count)) print_byte(']') print_type(info.elem) - case Type_Info_Matrix: + case ^Type_Info_Matrix: print_string("matrix[") print_u64(u64(info.row_count)) print_string(", ") diff --git a/core/fmt/fmt.odin b/core/fmt/fmt.odin index b7b42ffa4..14d722689 100644 --- a/core/fmt/fmt.odin +++ b/core/fmt/fmt.odin @@ -1603,7 +1603,7 @@ enum_value_to_string :: proc(val: any) -> (string, bool) { // string_to_enum_value :: proc($T: typeid, s: string) -> (T, bool) { ti := runtime.type_info_base(type_info_of(T)) - if e, ok := ti.variant.(runtime.Type_Info_Enum); ok { + if e, ok := ti.variant.(^runtime.Type_Info_Enum); ok { for str, idx in e.names { if s == str { // NOTE(bill): Unsafe cast @@ -1630,7 +1630,7 @@ fmt_enum :: proc(fi: ^Info, v: any, verb: rune) { type_info := type_info_of(v.id) #partial switch e in type_info.variant { case: fmt_bad_verb(fi, verb) - case runtime.Type_Info_Enum: + case ^runtime.Type_Info_Enum: switch verb { case: fmt_bad_verb(fi, verb) case 'i', 'd', 'f': @@ -1670,7 +1670,7 @@ stored_enum_value_to_string :: proc(enum_type: ^runtime.Type_Info, ev: runtime.T ev += runtime.Type_Info_Enum_Value(offset) #partial switch e in et.variant { case: return "", false - case runtime.Type_Info_Enum: + case ^runtime.Type_Info_Enum: if reflect.is_string(e.base) { for val, idx in e.values { if val == ev { @@ -1706,7 +1706,7 @@ fmt_bit_set :: proc(fi: ^Info, v: any, name: string = "", verb: rune = 'v') { } t := runtime.type_info_base(ti) #partial switch info in t.variant { - case runtime.Type_Info_Integer: + case ^runtime.Type_Info_Integer: switch info.endianness { case .Platform: return false case .Little: return ODIN_ENDIAN != .Little @@ -1720,12 +1720,12 @@ fmt_bit_set :: proc(fi: ^Info, v: any, name: string = "", verb: rune = 'v') { type_info := type_info_of(v.id) #partial switch info in type_info.variant { - case runtime.Type_Info_Named: + case ^runtime.Type_Info_Named: val := v val.id = info.base.id fmt_bit_set(fi, val, info.name, verb) - case runtime.Type_Info_Bit_Set: + case ^runtime.Type_Info_Bit_Set: bits: u128 bit_size := u128(8*type_info.size) @@ -1793,7 +1793,7 @@ fmt_bit_set :: proc(fi: ^Info, v: any, name: string = "", verb: rune = 'v') { io.write_byte(fi.writer, '{', &fi.n) defer io.write_byte(fi.writer, '}', &fi.n) - e, is_enum := et.variant.(runtime.Type_Info_Enum) + e, is_enum := et.variant.(^runtime.Type_Info_Enum) commas := 0 loop: for i in 0 ..< bit_size { if bits & (1< (do_continue: bool) { - handle_optional_len :: proc(data: rawptr, info: reflect.Type_Info_Struct, field_name: string, optional_len: ^int) { +handle_tag :: proc(state: ^Info_State, data: rawptr, info: ^reflect.Type_Info_Struct, idx: int, verb: ^rune, optional_len: ^int, use_nul_termination: ^bool) -> (do_continue: bool) { + handle_optional_len :: proc(data: rawptr, info: ^reflect.Type_Info_Struct, field_name: string, optional_len: ^int) { if optional_len == nil { return } @@ -2001,12 +2001,12 @@ handle_tag :: proc(state: ^Info_State, data: rawptr, info: reflect.Type_Info_Str // - info: Type information about the struct // - type_name: The name of the type being formatted // -fmt_struct :: proc(fi: ^Info, v: any, the_verb: rune, info: runtime.Type_Info_Struct, type_name: string) { +fmt_struct :: proc(fi: ^Info, v: any, the_verb: rune, info: ^runtime.Type_Info_Struct, type_name: string) { if the_verb != 'v' && the_verb != 'w' { fmt_bad_verb(fi, the_verb) return } - if .raw_union in info.flags { + if .raw_union in info.struct_flags { if type_name == "" { io.write_string(fi.writer, "(raw union)", &fi.n) } else { @@ -2047,7 +2047,7 @@ fmt_struct :: proc(fi: ^Info, v: any, the_verb: rune, info: runtime.Type_Info_St defer fi.indent -= 1 base_type_name: string - if v, ok := info.soa_base_type.variant.(runtime.Type_Info_Named); ok { + if v, ok := info.soa_base_type.variant.(^runtime.Type_Info_Named); ok { base_type_name = v.name } @@ -2111,7 +2111,7 @@ fmt_struct :: proc(fi: ^Info, v: any, the_verb: rune, info: runtime.Type_Info_St io.write_string(fi.writer, " = ", &fi.n) if info.soa_kind == .Fixed { - t := info.types[i].variant.(runtime.Type_Info_Array).elem + t := info.types[i].variant.(^runtime.Type_Info_Array).elem t_size := uintptr(t.size) if reflect.is_any(t) { io.write_string(fi.writer, "any{}", &fi.n) @@ -2120,7 +2120,7 @@ fmt_struct :: proc(fi: ^Info, v: any, the_verb: rune, info: runtime.Type_Info_St fmt_arg(fi, any{data, t.id}, verb) } } else { - t := info.types[i].variant.(runtime.Type_Info_Multi_Pointer).elem + t := info.types[i].variant.(^runtime.Type_Info_Multi_Pointer).elem t_size := uintptr(t.size) if reflect.is_any(t) { io.write_string(fi.writer, "any{}", &fi.n) @@ -2293,7 +2293,7 @@ fmt_array :: proc(fi: ^Info, data: rawptr, n: int, elem_size: int, elem: ^reflec // // NOTE: This procedure supports built-in custom formatters for core library types such as runtime.Source_Code_Location, time.Duration, and time.Time. // -fmt_named :: proc(fi: ^Info, v: any, verb: rune, info: runtime.Type_Info_Named) { +fmt_named :: proc(fi: ^Info, v: any, verb: rune, info: ^runtime.Type_Info_Named) { write_padded_number :: proc(fi: ^Info, i: i64, width: int) { n := width-1 for x := i; x >= 10; x /= 10 { @@ -2450,26 +2450,26 @@ fmt_named :: proc(fi: ^Info, v: any, verb: rune, info: runtime.Type_Info_Named) } #partial switch b in info.base.variant { - case runtime.Type_Info_Struct: + case ^runtime.Type_Info_Struct: fmt_struct(fi, v, verb, b, info.name) - case runtime.Type_Info_Bit_Field: + case ^runtime.Type_Info_Bit_Field: fmt_bit_field(fi, v, verb, b, info.name) - case runtime.Type_Info_Bit_Set: + case ^runtime.Type_Info_Bit_Set: fmt_bit_set(fi, v, verb = verb) case: if verb == 'w' { #partial switch _ in info.base.variant { - case runtime.Type_Info_Array, - runtime.Type_Info_Enumerated_Array, - runtime.Type_Info_Dynamic_Array, - runtime.Type_Info_Slice, - runtime.Type_Info_Struct, - runtime.Type_Info_Enum, - runtime.Type_Info_Map, - runtime.Type_Info_Bit_Set, - runtime.Type_Info_Simd_Vector, - runtime.Type_Info_Matrix, - runtime.Type_Info_Bit_Field: + case ^runtime.Type_Info_Array, + ^runtime.Type_Info_Enumerated_Array, + ^runtime.Type_Info_Dynamic_Array, + ^runtime.Type_Info_Slice, + ^runtime.Type_Info_Struct, + ^runtime.Type_Info_Enum, + ^runtime.Type_Info_Map, + ^runtime.Type_Info_Bit_Set, + ^runtime.Type_Info_Simd_Vector, + ^runtime.Type_Info_Matrix, + ^runtime.Type_Info_Bit_Field: io.write_string(fi.writer, info.name, &fi.n) } } @@ -2485,7 +2485,7 @@ fmt_named :: proc(fi: ^Info, v: any, verb: rune, info: runtime.Type_Info_Named) // - info: The union type information. // - type_size: The size of the union type. // -fmt_union :: proc(fi: ^Info, v: any, verb: rune, info: runtime.Type_Info_Union, type_size: int) { +fmt_union :: proc(fi: ^Info, v: any, verb: rune, info: ^runtime.Type_Info_Union, type_size: int) { if type_size == 0 { io.write_string(fi.writer, "nil", &fi.n) return @@ -2538,7 +2538,7 @@ fmt_union :: proc(fi: ^Info, v: any, verb: rune, info: runtime.Type_Info_Union, // - verb: The formatting verb rune. // - info: A runtime.Type_Info_Matrix struct containing matrix type information. // -fmt_matrix :: proc(fi: ^Info, v: any, verb: rune, info: runtime.Type_Info_Matrix) { +fmt_matrix :: proc(fi: ^Info, v: any, verb: rune, info: ^runtime.Type_Info_Matrix) { if verb == 'w' { io.write_byte(fi.writer, '{', &fi.n) } else { @@ -2595,7 +2595,7 @@ fmt_matrix :: proc(fi: ^Info, v: any, verb: rune, info: runtime.Type_Info_Matrix } } -fmt_bit_field :: proc(fi: ^Info, v: any, verb: rune, info: runtime.Type_Info_Bit_Field, type_name: string) { +fmt_bit_field :: proc(fi: ^Info, v: any, verb: rune, info: ^runtime.Type_Info_Bit_Field, type_name: string) { read_bits :: proc(ptr: [^]byte, offset, size: uintptr) -> (res: u64) { for i in 0.. (do_continue: bool) { + handle_bit_field_tag :: proc(data: rawptr, info: ^runtime.Type_Info_Bit_Field, idx: int, verb: ^rune) -> (do_continue: bool) { tag := info.tags[idx] if vt, ok := reflect.struct_tag_lookup(reflect.Struct_Tag(tag), "fmt"); ok { value := strings.trim_space(string(vt)) @@ -2716,21 +2716,21 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) { type_info := type_info_of(v.id) switch info in type_info.variant { - case runtime.Type_Info_Any: // Ignore - case runtime.Type_Info_Parameters: // Ignore + case ^runtime.Type_Info_Any: // Ignore + case ^runtime.Type_Info_Parameters: // Ignore - case runtime.Type_Info_Named: + case ^runtime.Type_Info_Named: fmt_named(fi, v, verb, info) - case runtime.Type_Info_Boolean: fmt_arg(fi, v, verb) - case runtime.Type_Info_Integer: fmt_arg(fi, v, verb) - case runtime.Type_Info_Rune: fmt_arg(fi, v, verb) - case runtime.Type_Info_Float: fmt_arg(fi, v, verb) - case runtime.Type_Info_Complex: fmt_arg(fi, v, verb) - case runtime.Type_Info_Quaternion: fmt_arg(fi, v, verb) - case runtime.Type_Info_String: fmt_arg(fi, v, verb) + case ^runtime.Type_Info_Boolean: fmt_arg(fi, v, verb) + case ^runtime.Type_Info_Integer: fmt_arg(fi, v, verb) + case ^runtime.Type_Info_Rune: fmt_arg(fi, v, verb) + case ^runtime.Type_Info_Float: fmt_arg(fi, v, verb) + case ^runtime.Type_Info_Complex: fmt_arg(fi, v, verb) + case ^runtime.Type_Info_Quaternion: fmt_arg(fi, v, verb) + case ^runtime.Type_Info_String: fmt_arg(fi, v, verb) - case runtime.Type_Info_Pointer: + case ^runtime.Type_Info_Pointer: if v.id == typeid_of(^runtime.Type_Info) { reflect.write_type(fi.writer, (^^runtime.Type_Info)(v.data)^, &fi.n) } else { @@ -2741,10 +2741,10 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) { elem := runtime.type_info_base(info.elem) if elem != nil { #partial switch e in elem.variant { - case runtime.Type_Info_Array, - runtime.Type_Info_Slice, - runtime.Type_Info_Dynamic_Array, - runtime.Type_Info_Map: + case ^runtime.Type_Info_Array, + ^runtime.Type_Info_Slice, + ^runtime.Type_Info_Dynamic_Array, + ^runtime.Type_Info_Map: if ptr == nil { io.write_string(fi.writer, "", &fi.n) return @@ -2757,9 +2757,9 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) { return } - case runtime.Type_Info_Struct, - runtime.Type_Info_Union, - runtime.Type_Info_Bit_Field: + case ^runtime.Type_Info_Struct, + ^runtime.Type_Info_Union, + ^runtime.Type_Info_Bit_Field: if ptr == nil { io.write_string(fi.writer, "", &fi.n) return @@ -2777,11 +2777,11 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) { fmt_pointer(fi, ptr, verb) } - case runtime.Type_Info_Soa_Pointer: + case ^runtime.Type_Info_Soa_Pointer: ptr := (^runtime.Raw_Soa_Pointer)(v.data)^ fmt_soa_pointer(fi, ptr, verb) - case runtime.Type_Info_Multi_Pointer: + case ^runtime.Type_Info_Multi_Pointer: ptr := (^rawptr)(v.data)^ if ptr == nil { io.write_string(fi.writer, "", &fi.n) @@ -2803,7 +2803,7 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) { } #partial switch e in elem.variant { - case runtime.Type_Info_Integer: + case ^runtime.Type_Info_Integer: switch verb { case 's', 'q': switch elem.id { @@ -2817,10 +2817,10 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) { } } - case runtime.Type_Info_Array, - runtime.Type_Info_Slice, - runtime.Type_Info_Dynamic_Array, - runtime.Type_Info_Map: + case ^runtime.Type_Info_Array, + ^runtime.Type_Info_Slice, + ^runtime.Type_Info_Dynamic_Array, + ^runtime.Type_Info_Map: if fi.indirection_level < 1 { fi.indirection_level += 1 defer fi.indirection_level -= 1 @@ -2829,8 +2829,8 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) { return } - case runtime.Type_Info_Struct, - runtime.Type_Info_Union: + case ^runtime.Type_Info_Struct, + ^runtime.Type_Info_Union: if fi.indirection_level < 1 { fi.indirection_level += 1 defer fi.indirection_level -= 1 @@ -2843,7 +2843,7 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) { } fmt_pointer(fi, ptr, verb) - case runtime.Type_Info_Enumerated_Array: + case ^runtime.Type_Info_Enumerated_Array: fi.record_level += 1 defer fi.record_level -= 1 @@ -2895,7 +2895,7 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) { } } - case runtime.Type_Info_Array: + case ^runtime.Type_Info_Array: n := info.count ptr := v.data if ol, ok := fi.optional_len.?; ok { @@ -2908,7 +2908,7 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) { } fmt_array(fi, ptr, n, info.elem_size, info.elem, verb) - case runtime.Type_Info_Slice: + case ^runtime.Type_Info_Slice: slice := cast(^mem.Raw_Slice)v.data n := slice.len ptr := slice.data @@ -2922,7 +2922,7 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) { } fmt_array(fi, ptr, n, info.elem_size, info.elem, verb) - case runtime.Type_Info_Dynamic_Array: + case ^runtime.Type_Info_Dynamic_Array: array := cast(^mem.Raw_Dynamic_Array)v.data n := array.len ptr := array.data @@ -2936,7 +2936,7 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) { } fmt_array(fi, ptr, n, info.elem_size, info.elem, verb) - case runtime.Type_Info_Simd_Vector: + case ^runtime.Type_Info_Simd_Vector: io.write_byte(fi.writer, '<', &fi.n) defer io.write_byte(fi.writer, '>', &fi.n) for i in 0.. string where intrinsi err := runtime.Type_Info_Enum_Value(e) - ti := &runtime.type_info_base(type_info_of(Platform_Error)).variant.(runtime.Type_Info_Enum) + ti := runtime.type_info_base(type_info_of(Platform_Error)).variant.(^runtime.Type_Info_Enum) if idx, ok := binary_search(ti.values, err); ok { return ti.names[idx] } diff --git a/core/reflect/iterator.odin b/core/reflect/iterator.odin index 090fe04cc..b4019d907 100644 --- a/core/reflect/iterator.odin +++ b/core/reflect/iterator.odin @@ -10,11 +10,11 @@ iterate_array :: proc(val: any, it: ^int) -> (elem: any, index: int, ok: bool) { ti := type_info_base(type_info_of(val.id)) #partial switch info in ti.variant { - case Type_Info_Pointer: + case ^Type_Info_Pointer: if ptr := (^rawptr)(val.data)^; ptr != nil { return iterate_array(any{ptr, info.elem.id}, it) } - case Type_Info_Array: + case ^Type_Info_Array: if it^ < info.count { elem.data = rawptr(uintptr(val.data) + uintptr(it^ * info.elem_size)) elem.id = info.elem.id @@ -22,7 +22,7 @@ iterate_array :: proc(val: any, it: ^int) -> (elem: any, index: int, ok: bool) { index = it^ it^ += 1 } - case Type_Info_Slice: + case ^Type_Info_Slice: array := (^runtime.Raw_Slice)(val.data) if it^ < array.len { elem.data = rawptr(uintptr(array.data) + uintptr(it^ * info.elem_size)) @@ -31,7 +31,7 @@ iterate_array :: proc(val: any, it: ^int) -> (elem: any, index: int, ok: bool) { index = it^ it^ += 1 } - case Type_Info_Dynamic_Array: + case ^Type_Info_Dynamic_Array: array := (^runtime.Raw_Dynamic_Array)(val.data) if it^ < array.len { elem.data = rawptr(uintptr(array.data) + uintptr(it^ * info.elem_size)) @@ -52,11 +52,11 @@ iterate_map :: proc(val: any, it: ^int) -> (key, value: any, ok: bool) { } ti := type_info_base(type_info_of(val.id)) #partial switch info in ti.variant { - case Type_Info_Pointer: + case ^Type_Info_Pointer: if ptr := (^rawptr)(val.data)^; ptr != nil { return iterate_map(any{ptr, info.elem.id}, it) } - case Type_Info_Map: + case ^Type_Info_Map: if info.map_info == nil { break } diff --git a/core/reflect/reflect.odin b/core/reflect/reflect.odin index 7f79acb77..4ac3311c5 100644 --- a/core/reflect/reflect.odin +++ b/core/reflect/reflect.odin @@ -76,33 +76,33 @@ type_kind :: proc(T: typeid) -> Type_Kind { ti := type_info_of(T) if ti != nil { switch _ in ti.variant { - case Type_Info_Named: return .Named - case Type_Info_Integer: return .Integer - case Type_Info_Rune: return .Rune - case Type_Info_Float: return .Float - case Type_Info_Complex: return .Complex - case Type_Info_Quaternion: return .Quaternion - case Type_Info_String: return .String - case Type_Info_Boolean: return .Boolean - case Type_Info_Any: return .Any - case Type_Info_Type_Id: return .Type_Id - case Type_Info_Pointer: return .Pointer - case Type_Info_Multi_Pointer: return .Multi_Pointer - case Type_Info_Procedure: return .Procedure - case Type_Info_Array: return .Array - case Type_Info_Enumerated_Array: return .Enumerated_Array - case Type_Info_Dynamic_Array: return .Dynamic_Array - case Type_Info_Slice: return .Slice - case Type_Info_Parameters: return .Tuple - case Type_Info_Struct: return .Struct - case Type_Info_Union: return .Union - case Type_Info_Enum: return .Enum - case Type_Info_Map: return .Map - case Type_Info_Bit_Set: return .Bit_Set - case Type_Info_Simd_Vector: return .Simd_Vector - case Type_Info_Matrix: return .Matrix - case Type_Info_Soa_Pointer: return .Soa_Pointer - case Type_Info_Bit_Field: return .Bit_Field + case ^Type_Info_Named: return .Named + case ^Type_Info_Integer: return .Integer + case ^Type_Info_Rune: return .Rune + case ^Type_Info_Float: return .Float + case ^Type_Info_Complex: return .Complex + case ^Type_Info_Quaternion: return .Quaternion + case ^Type_Info_String: return .String + case ^Type_Info_Boolean: return .Boolean + case ^Type_Info_Any: return .Any + case ^Type_Info_Type_Id: return .Type_Id + case ^Type_Info_Pointer: return .Pointer + case ^Type_Info_Multi_Pointer: return .Multi_Pointer + case ^Type_Info_Procedure: return .Procedure + case ^Type_Info_Array: return .Array + case ^Type_Info_Enumerated_Array: return .Enumerated_Array + case ^Type_Info_Dynamic_Array: return .Dynamic_Array + case ^Type_Info_Slice: return .Slice + case ^Type_Info_Parameters: return .Tuple + case ^Type_Info_Struct: return .Struct + case ^Type_Info_Union: return .Union + case ^Type_Info_Enum: return .Enum + case ^Type_Info_Map: return .Map + case ^Type_Info_Bit_Set: return .Bit_Set + case ^Type_Info_Simd_Vector: return .Simd_Vector + case ^Type_Info_Matrix: return .Matrix + case ^Type_Info_Soa_Pointer: return .Soa_Pointer + case ^Type_Info_Bit_Field: return .Bit_Field } } @@ -159,23 +159,23 @@ typeid_elem :: proc(id: typeid) -> typeid { bits := 8*ti.size #partial switch v in ti.variant { - case Type_Info_Complex: + case ^Type_Info_Complex: switch bits { case 64: return f32 case 128: return f64 } - case Type_Info_Quaternion: + case ^Type_Info_Quaternion: switch bits { case 128: return f32 case 256: return f64 } - case Type_Info_Pointer: return v.elem.id - case Type_Info_Multi_Pointer: return v.elem.id - case Type_Info_Soa_Pointer: return v.elem.id - case Type_Info_Array: return v.elem.id - case Type_Info_Enumerated_Array: return v.elem.id - case Type_Info_Slice: return v.elem.id - case Type_Info_Dynamic_Array: return v.elem.id + case ^Type_Info_Pointer: return v.elem.id + case ^Type_Info_Multi_Pointer: return v.elem.id + case ^Type_Info_Soa_Pointer: return v.elem.id + case ^Type_Info_Array: return v.elem.id + case ^Type_Info_Enumerated_Array: return v.elem.id + case ^Type_Info_Slice: return v.elem.id + case ^Type_Info_Dynamic_Array: return v.elem.id } return id } @@ -233,28 +233,28 @@ length :: proc(val: any) -> int { if val == nil { return 0 } #partial switch a in type_info_of(val.id).variant { - case Type_Info_Named: + case ^Type_Info_Named: return length({val.data, a.base.id}) - case Type_Info_Pointer: + case ^Type_Info_Pointer: return length({val.data, a.elem.id}) - case Type_Info_Array: + case ^Type_Info_Array: return a.count - case Type_Info_Enumerated_Array: + case ^Type_Info_Enumerated_Array: return a.count - case Type_Info_Slice: + case ^Type_Info_Slice: return (^runtime.Raw_Slice)(val.data).len - case Type_Info_Dynamic_Array: + case ^Type_Info_Dynamic_Array: return (^runtime.Raw_Dynamic_Array)(val.data).len - case Type_Info_Map: + case ^Type_Info_Map: return runtime.map_len((^runtime.Raw_Map)(val.data)^) - case Type_Info_String: + case ^Type_Info_String: if a.is_cstring { return len((^cstring)(val.data)^) } else { @@ -269,22 +269,22 @@ capacity :: proc(val: any) -> int { if val == nil { return 0 } #partial switch a in type_info_of(val.id).variant { - case Type_Info_Named: + case ^Type_Info_Named: return capacity({val.data, a.base.id}) - case Type_Info_Pointer: + case ^Type_Info_Pointer: return capacity({val.data, a.elem.id}) - case Type_Info_Array: + case ^Type_Info_Array: return a.count - case Type_Info_Enumerated_Array: + case ^Type_Info_Enumerated_Array: return a.count - case Type_Info_Dynamic_Array: + case ^Type_Info_Dynamic_Array: return (^runtime.Raw_Dynamic_Array)(val.data).cap - case Type_Info_Map: + case ^Type_Info_Map: return runtime.map_cap((^runtime.Raw_Map)(val.data)^) } return 0 @@ -296,50 +296,50 @@ index :: proc(val: any, i: int, loc := #caller_location) -> any { if val == nil { return nil } #partial switch a in type_info_of(val.id).variant { - case Type_Info_Named: + case ^Type_Info_Named: return index({val.data, a.base.id}, i, loc) - case Type_Info_Pointer: + case ^Type_Info_Pointer: ptr := (^rawptr)(val.data)^ if ptr == nil { return nil } return index({ptr, a.elem.id}, i, loc) - case Type_Info_Multi_Pointer: + case ^Type_Info_Multi_Pointer: ptr := (^rawptr)(val.data)^ if ptr == nil { return nil } return index({ptr, a.elem.id}, i, loc) - case Type_Info_Array: + case ^Type_Info_Array: runtime.bounds_check_error_loc(loc, i, a.count) offset := uintptr(a.elem.size * i) data := rawptr(uintptr(val.data) + offset) return any{data, a.elem.id} - case Type_Info_Enumerated_Array: + case ^Type_Info_Enumerated_Array: runtime.bounds_check_error_loc(loc, i, a.count) offset := uintptr(a.elem.size * i) data := rawptr(uintptr(val.data) + offset) return any{data, a.elem.id} - case Type_Info_Slice: + case ^Type_Info_Slice: raw := (^runtime.Raw_Slice)(val.data) runtime.bounds_check_error_loc(loc, i, raw.len) offset := uintptr(a.elem.size * i) data := rawptr(uintptr(raw.data) + offset) return any{data, a.elem.id} - case Type_Info_Dynamic_Array: + case ^Type_Info_Dynamic_Array: raw := (^runtime.Raw_Dynamic_Array)(val.data) runtime.bounds_check_error_loc(loc, i, raw.len) offset := uintptr(a.elem.size * i) data := rawptr(uintptr(raw.data) + offset) return any{data, a.elem.id} - case Type_Info_String: + case ^Type_Info_String: if a.is_cstring { return nil } raw := (^runtime.Raw_String)(val.data) @@ -355,7 +355,7 @@ index :: proc(val: any, i: int, loc := #caller_location) -> any { deref :: proc(val: any) -> any { if val != nil { ti := type_info_base(type_info_of(val.id)) - if info, ok := ti.variant.(Type_Info_Pointer); ok { + if info, ok := ti.variant.(^Type_Info_Pointer); ok { return any{ (^rawptr)(val.data)^, info.elem.id, @@ -384,7 +384,7 @@ Struct_Field :: struct { @(require_results) struct_field_at :: proc(T: typeid, i: int) -> (field: Struct_Field) { ti := runtime.type_info_base(type_info_of(T)) - if s, ok := ti.variant.(runtime.Type_Info_Struct); ok { + if s, ok := ti.variant.(^runtime.Type_Info_Struct); ok { if 0 <= i && i < int(s.field_count) { field.name = s.names[i] field.type = s.types[i] @@ -399,7 +399,7 @@ struct_field_at :: proc(T: typeid, i: int) -> (field: Struct_Field) { @(require_results) struct_field_by_name :: proc(T: typeid, name: string) -> (field: Struct_Field) { ti := runtime.type_info_base(type_info_of(T)) - if s, ok := ti.variant.(runtime.Type_Info_Struct); ok { + if s, ok := ti.variant.(^runtime.Type_Info_Struct); ok { for fname, i in s.names[:s.field_count] { if fname == name { field.name = s.names[i] @@ -420,7 +420,7 @@ struct_field_value_by_name :: proc(a: any, field: string, allow_using := false) ti := runtime.type_info_base(type_info_of(a.id)) - if s, ok := ti.variant.(runtime.Type_Info_Struct); ok { + if s, ok := ti.variant.(^runtime.Type_Info_Struct); ok { for name, i in s.names[:s.field_count] { if name == field { return any{ @@ -456,7 +456,7 @@ struct_field_value :: proc(a: any, field: Struct_Field) -> any { @(require_results) struct_field_names :: proc(T: typeid) -> []string { ti := runtime.type_info_base(type_info_of(T)) - if s, ok := ti.variant.(runtime.Type_Info_Struct); ok { + if s, ok := ti.variant.(^runtime.Type_Info_Struct); ok { return s.names[:s.field_count] } return nil @@ -465,7 +465,7 @@ struct_field_names :: proc(T: typeid) -> []string { @(require_results) struct_field_types :: proc(T: typeid) -> []^Type_Info { ti := runtime.type_info_base(type_info_of(T)) - if s, ok := ti.variant.(runtime.Type_Info_Struct); ok { + if s, ok := ti.variant.(^runtime.Type_Info_Struct); ok { return s.types[:s.field_count] } return nil @@ -475,7 +475,7 @@ struct_field_types :: proc(T: typeid) -> []^Type_Info { @(require_results) struct_field_tags :: proc(T: typeid) -> []Struct_Tag { ti := runtime.type_info_base(type_info_of(T)) - if s, ok := ti.variant.(runtime.Type_Info_Struct); ok { + if s, ok := ti.variant.(^runtime.Type_Info_Struct); ok { return transmute([]Struct_Tag)s.tags[:s.field_count] } return nil @@ -484,7 +484,7 @@ struct_field_tags :: proc(T: typeid) -> []Struct_Tag { @(require_results) struct_field_offsets :: proc(T: typeid) -> []uintptr { ti := runtime.type_info_base(type_info_of(T)) - if s, ok := ti.variant.(runtime.Type_Info_Struct); ok { + if s, ok := ti.variant.(^runtime.Type_Info_Struct); ok { return s.offsets[:s.field_count] } return nil @@ -523,7 +523,7 @@ Example: @(require_results) struct_field_count :: proc(T: typeid, method := Struct_Field_Count_Method.Top_Level) -> (count: int) { ti := runtime.type_info_base(type_info_of(T)) - if s, ok := ti.variant.(runtime.Type_Info_Struct); ok { + if s, ok := ti.variant.(^runtime.Type_Info_Struct); ok { switch method { case .Top_Level: return int(s.field_count) @@ -551,7 +551,7 @@ struct_field_count :: proc(T: typeid, method := Struct_Field_Count_Method.Top_Le @(require_results) struct_fields_zipped :: proc(T: typeid) -> (fields: #soa[]Struct_Field) { ti := runtime.type_info_base(type_info_of(T)) - if s, ok := ti.variant.(runtime.Type_Info_Struct); ok { + if s, ok := ti.variant.(^runtime.Type_Info_Struct); ok { return soa_zip( name = s.names[:s.field_count], type = s.types[:s.field_count], @@ -634,7 +634,7 @@ struct_tag_lookup :: proc(tag: Struct_Tag, key: string) -> (value: string, ok: b enum_string :: proc(a: any) -> string { if a == nil { return "" } ti := runtime.type_info_base(type_info_of(a.id)) - if e, ok := ti.variant.(runtime.Type_Info_Enum); ok { + if e, ok := ti.variant.(^runtime.Type_Info_Enum); ok { v, _ := as_i64(a) for value, i in e.values { if value == Type_Info_Enum_Value(v) { @@ -652,7 +652,7 @@ enum_string :: proc(a: any) -> string { @(require_results) enum_from_name :: proc($Enum_Type: typeid, name: string) -> (value: Enum_Type, ok: bool) { ti := type_info_base(type_info_of(Enum_Type)) - if eti, eti_ok := ti.variant.(runtime.Type_Info_Enum); eti_ok { + if eti, eti_ok := ti.variant.(^runtime.Type_Info_Enum); eti_ok { for value_name, i in eti.names { if value_name != name { continue @@ -669,7 +669,7 @@ enum_from_name :: proc($Enum_Type: typeid, name: string) -> (value: Enum_Type, o @(require_results) enum_from_name_any :: proc(Enum_Type: typeid, name: string) -> (value: Type_Info_Enum_Value, ok: bool) { ti := runtime.type_info_base(type_info_of(Enum_Type)) - if eti, eti_ok := ti.variant.(runtime.Type_Info_Enum); eti_ok { + if eti, eti_ok := ti.variant.(^runtime.Type_Info_Enum); eti_ok { for value_name, i in eti.names { if value_name != name { continue @@ -685,7 +685,7 @@ enum_from_name_any :: proc(Enum_Type: typeid, name: string) -> (value: Type_Info @(require_results) enum_name_from_value :: proc(value: $Enum_Type) -> (name: string, ok: bool) where intrinsics.type_is_enum(Enum_Type) { ti := type_info_base(type_info_of(Enum_Type)) - e := ti.variant.(runtime.Type_Info_Enum) or_return + e := ti.variant.(^runtime.Type_Info_Enum) or_return if len(e.values) == 0 { return } @@ -704,7 +704,7 @@ enum_name_from_value_any :: proc(value: any) -> (name: string, ok: bool) { return } ti := type_info_base(type_info_of(value.id)) - e := ti.variant.(runtime.Type_Info_Enum) or_return + e := ti.variant.(^runtime.Type_Info_Enum) or_return if len(e.values) == 0 { return } @@ -744,7 +744,7 @@ enum_value_has_name :: proc(value: $T) -> bool where intrinsics.type_is_enum(T) @(require_results) enum_field_names :: proc(Enum_Type: typeid) -> []string { ti := runtime.type_info_base(type_info_of(Enum_Type)) - if eti, eti_ok := ti.variant.(runtime.Type_Info_Enum); eti_ok { + if eti, eti_ok := ti.variant.(^runtime.Type_Info_Enum); eti_ok { return eti.names } return nil @@ -752,7 +752,7 @@ enum_field_names :: proc(Enum_Type: typeid) -> []string { @(require_results) enum_field_values :: proc(Enum_Type: typeid) -> []Type_Info_Enum_Value { ti := runtime.type_info_base(type_info_of(Enum_Type)) - if eti, eti_ok := ti.variant.(runtime.Type_Info_Enum); eti_ok { + if eti, eti_ok := ti.variant.(^runtime.Type_Info_Enum); eti_ok { return eti.values } return nil @@ -766,7 +766,7 @@ Enum_Field :: struct { @(require_results) enum_fields_zipped :: proc(Enum_Type: typeid) -> (fields: #soa[]Enum_Field) { ti := runtime.type_info_base(type_info_of(Enum_Type)) - if eti, eti_ok := ti.variant.(runtime.Type_Info_Enum); eti_ok { + if eti, eti_ok := ti.variant.(^runtime.Type_Info_Enum); eti_ok { return soa_zip(name=eti.names, value=eti.values) } return nil @@ -781,7 +781,7 @@ union_variant_type_info :: proc(a: any) -> ^Type_Info { } @(require_results) -type_info_union_is_pure_maybe :: proc(info: runtime.Type_Info_Union) -> bool { +type_info_union_is_pure_maybe :: proc(info: ^runtime.Type_Info_Union) -> bool { return len(info.variants) == 1 && is_pointer_internally(info.variants[0]) } @@ -790,7 +790,7 @@ union_variant_typeid :: proc(a: any) -> typeid { if a == nil { return nil } ti := runtime.type_info_base(type_info_of(a.id)) - if info, ok := ti.variant.(runtime.Type_Info_Union); ok { + if info, ok := ti.variant.(^runtime.Type_Info_Union); ok { if type_info_union_is_pure_maybe(info) { if a.data != nil { return info.variants[0].id @@ -830,7 +830,7 @@ get_union_variant_raw_tag :: proc(a: any) -> i64 { if a == nil { return -1 } ti := runtime.type_info_base(type_info_of(a.id)) - if info, ok := ti.variant.(runtime.Type_Info_Union); ok { + if info, ok := ti.variant.(^runtime.Type_Info_Union); ok { if type_info_union_is_pure_maybe(info) { return 1 if a.data != nil else 0 } @@ -883,7 +883,7 @@ set_union_variant_raw_tag :: proc(a: any, tag: i64) { if a == nil { return } ti := runtime.type_info_base(type_info_of(a.id)) - if info, ok := ti.variant.(runtime.Type_Info_Union); ok { + if info, ok := ti.variant.(^runtime.Type_Info_Union); ok { if type_info_union_is_pure_maybe(info) { // Cannot do anything return @@ -913,7 +913,7 @@ set_union_variant_typeid :: proc(a: any, id: typeid) { if a == nil { return } ti := runtime.type_info_base(type_info_of(a.id)) - if info, ok := ti.variant.(runtime.Type_Info_Union); ok { + if info, ok := ti.variant.(^runtime.Type_Info_Union); ok { if type_info_union_is_pure_maybe(info) { // Cannot do anything return @@ -943,7 +943,7 @@ set_union_variant_type_info :: proc(a: any, tag_ti: ^Type_Info) { if a == nil { return } ti := runtime.type_info_base(type_info_of(a.id)) - if info, ok := ti.variant.(runtime.Type_Info_Union); ok { + if info, ok := ti.variant.(^runtime.Type_Info_Union); ok { if type_info_union_is_pure_maybe(info) { // Cannot do anything return @@ -973,7 +973,7 @@ set_union_value :: proc(dst: any, value: any) -> bool { if dst == nil { return false } ti := runtime.type_info_base(type_info_of(dst.id)) - if info, ok := ti.variant.(runtime.Type_Info_Union); ok { + if info, ok := ti.variant.(^runtime.Type_Info_Union); ok { if value.id == nil { intrinsics.mem_zero(dst.data, ti.size) return true @@ -1012,11 +1012,11 @@ bit_set_is_big_endian :: proc(value: any, loc := #caller_location) -> bool { if value == nil { return ODIN_ENDIAN == .Big } ti := runtime.type_info_base(type_info_of(value.id)) - if info, ok := ti.variant.(runtime.Type_Info_Bit_Set); ok { + if info, ok := ti.variant.(^runtime.Type_Info_Bit_Set); ok { if info.underlying == nil { return ODIN_ENDIAN == .Big } underlying_ti := runtime.type_info_base(info.underlying) - if underlying_info, uok := underlying_ti.variant.(runtime.Type_Info_Integer); uok { + if underlying_info, uok := underlying_ti.variant.(^runtime.Type_Info_Integer); uok { switch underlying_info.endianness { case .Platform: return ODIN_ENDIAN == .Big case .Little: return false @@ -1041,7 +1041,7 @@ Bit_Field :: struct { @(require_results) bit_fields_zipped :: proc(T: typeid) -> (fields: #soa[]Bit_Field) { ti := runtime.type_info_base(type_info_of(T)) - if s, ok := ti.variant.(runtime.Type_Info_Bit_Field); ok { + if s, ok := ti.variant.(^runtime.Type_Info_Bit_Field); ok { return soa_zip( name = s.names[:s.field_count], type = s.types[:s.field_count], @@ -1056,7 +1056,7 @@ bit_fields_zipped :: proc(T: typeid) -> (fields: #soa[]Bit_Field) { @(require_results) bit_field_names :: proc(T: typeid) -> []string { ti := runtime.type_info_base(type_info_of(T)) - if s, ok := ti.variant.(runtime.Type_Info_Bit_Field); ok { + if s, ok := ti.variant.(^runtime.Type_Info_Bit_Field); ok { return s.names[:s.field_count] } return nil @@ -1065,7 +1065,7 @@ bit_field_names :: proc(T: typeid) -> []string { @(require_results) bit_field_types :: proc(T: typeid) -> []^Type_Info { ti := runtime.type_info_base(type_info_of(T)) - if s, ok := ti.variant.(runtime.Type_Info_Bit_Field); ok { + if s, ok := ti.variant.(^runtime.Type_Info_Bit_Field); ok { return s.types[:s.field_count] } return nil @@ -1074,7 +1074,7 @@ bit_field_types :: proc(T: typeid) -> []^Type_Info { @(require_results) bit_field_sizes :: proc(T: typeid) -> []uintptr { ti := runtime.type_info_base(type_info_of(T)) - if s, ok := ti.variant.(runtime.Type_Info_Bit_Field); ok { + if s, ok := ti.variant.(^runtime.Type_Info_Bit_Field); ok { return s.bit_sizes[:s.field_count] } return nil @@ -1083,7 +1083,7 @@ bit_field_sizes :: proc(T: typeid) -> []uintptr { @(require_results) bit_field_offsets :: proc(T: typeid) -> []uintptr { ti := runtime.type_info_base(type_info_of(T)) - if s, ok := ti.variant.(runtime.Type_Info_Bit_Field); ok { + if s, ok := ti.variant.(^runtime.Type_Info_Bit_Field); ok { return s.bit_offsets[:s.field_count] } return nil @@ -1092,7 +1092,7 @@ bit_field_offsets :: proc(T: typeid) -> []uintptr { @(require_results) bit_field_tags :: proc(T: typeid) -> []Struct_Tag { ti := runtime.type_info_base(type_info_of(T)) - if s, ok := ti.variant.(runtime.Type_Info_Bit_Field); ok { + if s, ok := ti.variant.(^runtime.Type_Info_Bit_Field); ok { return transmute([]Struct_Tag)s.tags[:s.field_count] } return nil @@ -1106,7 +1106,7 @@ as_bool :: proc(a: any) -> (value: bool, valid: bool) { a.id = ti.id #partial switch info in ti.variant { - case Type_Info_Boolean: + case ^Type_Info_Boolean: valid = true switch v in a { case bool: value = v @@ -1145,7 +1145,7 @@ as_i64 :: proc(a: any) -> (value: i64, valid: bool) { a.id = ti.id #partial switch info in ti.variant { - case Type_Info_Integer: + case ^Type_Info_Integer: valid = true switch v in a { case i8: value = i64(v) @@ -1185,12 +1185,12 @@ as_i64 :: proc(a: any) -> (value: i64, valid: bool) { case: valid = false } - case Type_Info_Rune: + case ^Type_Info_Rune: r := a.(rune) value = i64(r) valid = true - case Type_Info_Float: + case ^Type_Info_Float: valid = true switch v in a { case f32: value = i64(v) @@ -1202,7 +1202,7 @@ as_i64 :: proc(a: any) -> (value: i64, valid: bool) { case: valid = false } - case Type_Info_Boolean: + case ^Type_Info_Boolean: valid = true switch v in a { case bool: value = i64(v) @@ -1213,7 +1213,7 @@ as_i64 :: proc(a: any) -> (value: i64, valid: bool) { case: valid = false } - case Type_Info_Complex: + case ^Type_Info_Complex: switch v in a { case complex64: if imag(v) == 0 { @@ -1227,7 +1227,7 @@ as_i64 :: proc(a: any) -> (value: i64, valid: bool) { } } - case Type_Info_Quaternion: + case ^Type_Info_Quaternion: switch v in a { case quaternion128: if imag(v) == 0 && jmag(v) == 0 && kmag(v) == 0 { @@ -1253,7 +1253,7 @@ as_u64 :: proc(a: any) -> (value: u64, valid: bool) { a.id = ti.id #partial switch info in ti.variant { - case Type_Info_Integer: + case ^Type_Info_Integer: valid = true switch v in a { case i8: value = u64(v) @@ -1293,12 +1293,12 @@ as_u64 :: proc(a: any) -> (value: u64, valid: bool) { case: valid = false } - case Type_Info_Rune: + case ^Type_Info_Rune: r := a.(rune) value = u64(r) valid = true - case Type_Info_Float: + case ^Type_Info_Float: valid = true switch v in a { case f16: value = u64(v) @@ -1311,7 +1311,7 @@ as_u64 :: proc(a: any) -> (value: u64, valid: bool) { case: valid = false } - case Type_Info_Boolean: + case ^Type_Info_Boolean: valid = true switch v in a { case bool: value = u64(v) @@ -1322,7 +1322,7 @@ as_u64 :: proc(a: any) -> (value: u64, valid: bool) { case: valid = false } - case Type_Info_Complex: + case ^Type_Info_Complex: switch v in a { case complex64: if imag(v) == 0 { @@ -1336,7 +1336,7 @@ as_u64 :: proc(a: any) -> (value: u64, valid: bool) { } } - case Type_Info_Quaternion: + case ^Type_Info_Quaternion: switch v in a { case quaternion128: if imag(v) == 0 && jmag(v) == 0 && kmag(v) == 0 { @@ -1363,7 +1363,7 @@ as_f64 :: proc(a: any) -> (value: f64, valid: bool) { a.id = ti.id #partial switch info in ti.variant { - case Type_Info_Integer: + case ^Type_Info_Integer: valid = true switch v in a { case i8: value = f64(v) @@ -1400,12 +1400,12 @@ as_f64 :: proc(a: any) -> (value: f64, valid: bool) { case: valid = false } - case Type_Info_Rune: + case ^Type_Info_Rune: r := a.(rune) value = f64(i32(r)) valid = true - case Type_Info_Float: + case ^Type_Info_Float: valid = true switch v in a { case f16: value = f64(v) @@ -1418,7 +1418,7 @@ as_f64 :: proc(a: any) -> (value: f64, valid: bool) { case: valid = false } - case Type_Info_Boolean: + case ^Type_Info_Boolean: valid = true switch v in a { case bool: value = f64(i32(v)) @@ -1429,7 +1429,7 @@ as_f64 :: proc(a: any) -> (value: f64, valid: bool) { case: valid = false } - case Type_Info_Complex: + case ^Type_Info_Complex: switch v in a { case complex64: if imag(v) == 0 { @@ -1443,7 +1443,7 @@ as_f64 :: proc(a: any) -> (value: f64, valid: bool) { } } - case Type_Info_Quaternion: + case ^Type_Info_Quaternion: switch v in a { case quaternion128: if imag(v) == 0 && jmag(v) == 0 && kmag(v) == 0 { @@ -1470,7 +1470,7 @@ as_string :: proc(a: any) -> (value: string, valid: bool) { a.id = ti.id #partial switch info in ti.variant { - case Type_Info_String: + case ^Type_Info_String: valid = true switch v in a { case string: value = v @@ -1533,11 +1533,11 @@ as_pointer :: proc(a: any) -> (value: rawptr, valid: bool) { a.id = ti.id #partial switch info in ti.variant { - case Type_Info_Pointer: + case ^Type_Info_Pointer: valid = true value = (^rawptr)(a.data)^ - case Type_Info_String: + case ^Type_Info_String: valid = true switch v in a { case cstring: value = rawptr(v) @@ -1557,7 +1557,7 @@ as_raw_data :: proc(a: any) -> (value: rawptr, valid: bool) { a.id = ti.id #partial switch info in ti.variant { - case Type_Info_String: + case ^Type_Info_String: valid = true switch v in a { case string: value = raw_data(v) @@ -1565,15 +1565,15 @@ as_raw_data :: proc(a: any) -> (value: rawptr, valid: bool) { case: valid = false } - case Type_Info_Array: + case ^Type_Info_Array: valid = true value = a.data - case Type_Info_Slice: + case ^Type_Info_Slice: valid = true value = (^runtime.Raw_Slice)(a.data).data - case Type_Info_Dynamic_Array: + case ^Type_Info_Dynamic_Array: valid = true value = (^runtime.Raw_Dynamic_Array)(a.data).data } @@ -1625,38 +1625,38 @@ equal :: proc(a, b: any, including_indirect_array_recursion := false, recursion_ t = runtime.type_info_core(t) switch v in t.variant { - case Type_Info_Named: + case ^Type_Info_Named: unreachable() - case Type_Info_Parameters: + case ^Type_Info_Parameters: unreachable() - case Type_Info_Any: + case ^Type_Info_Any: if !including_indirect_array_recursion { return false } va := (^any)(a.data) vb := (^any)(b.data) return equal(va, vb, including_indirect_array_recursion, recursion_level+1) - case Type_Info_Map: + case ^Type_Info_Map: return false case - Type_Info_Boolean, - Type_Info_Integer, - Type_Info_Rune, - Type_Info_Float, - Type_Info_Complex, - Type_Info_Quaternion, - Type_Info_Type_Id, - Type_Info_Pointer, - Type_Info_Multi_Pointer, - Type_Info_Procedure, - Type_Info_Bit_Set, - Type_Info_Enum, - Type_Info_Simd_Vector, - Type_Info_Soa_Pointer, - Type_Info_Matrix: + ^Type_Info_Boolean, + ^Type_Info_Integer, + ^Type_Info_Rune, + ^Type_Info_Float, + ^Type_Info_Complex, + ^Type_Info_Quaternion, + ^Type_Info_Type_Id, + ^Type_Info_Pointer, + ^Type_Info_Multi_Pointer, + ^Type_Info_Procedure, + ^Type_Info_Bit_Set, + ^Type_Info_Enum, + ^Type_Info_Simd_Vector, + ^Type_Info_Soa_Pointer, + ^Type_Info_Matrix: return runtime.memory_compare(a.data, b.data, t.size) == 0 - case Type_Info_String: + case ^Type_Info_String: if v.is_cstring { x := string((^cstring)(a.data)^) y := string((^cstring)(b.data)^) @@ -1667,7 +1667,7 @@ equal :: proc(a, b: any, including_indirect_array_recursion := false, recursion_ return x == y } return true - case Type_Info_Array: + case ^Type_Info_Array: for i in 0.. bool { } switch x in a.variant { - case Type_Info_Named: - y := b.variant.(Type_Info_Named) or_return + case ^Type_Info_Named: + y := b.variant.(^Type_Info_Named) or_return return x.base == y.base - case Type_Info_Integer: - y := b.variant.(Type_Info_Integer) or_return + case ^Type_Info_Integer: + y := b.variant.(^Type_Info_Integer) or_return return x.signed == y.signed && x.endianness == y.endianness - case Type_Info_Rune: - _, ok := b.variant.(Type_Info_Rune) + case ^Type_Info_Rune: + _, ok := b.variant.(^Type_Info_Rune) return ok - case Type_Info_Float: - _, ok := b.variant.(Type_Info_Float) + case ^Type_Info_Float: + _, ok := b.variant.(^Type_Info_Float) return ok - case Type_Info_Complex: - _, ok := b.variant.(Type_Info_Complex) + case ^Type_Info_Complex: + _, ok := b.variant.(^Type_Info_Complex) return ok - case Type_Info_Quaternion: - _, ok := b.variant.(Type_Info_Quaternion) + case ^Type_Info_Quaternion: + _, ok := b.variant.(^Type_Info_Quaternion) return ok - case Type_Info_Type_Id: - _, ok := b.variant.(Type_Info_Type_Id) + case ^Type_Info_Type_Id: + _, ok := b.variant.(^Type_Info_Type_Id) return ok - case Type_Info_String: - _, ok := b.variant.(Type_Info_String) + case ^Type_Info_String: + _, ok := b.variant.(^Type_Info_String) return ok - case Type_Info_Boolean: - _, ok := b.variant.(Type_Info_Boolean) + case ^Type_Info_Boolean: + _, ok := b.variant.(^Type_Info_Boolean) return ok - case Type_Info_Any: - _, ok := b.variant.(Type_Info_Any) + case ^Type_Info_Any: + _, ok := b.variant.(^Type_Info_Any) return ok - case Type_Info_Pointer: - y := b.variant.(Type_Info_Pointer) or_return + case ^Type_Info_Pointer: + y := b.variant.(^Type_Info_Pointer) or_return return are_types_identical(x.elem, y.elem) - case Type_Info_Multi_Pointer: - y := b.variant.(Type_Info_Multi_Pointer) or_return + case ^Type_Info_Multi_Pointer: + y := b.variant.(^Type_Info_Multi_Pointer) or_return return are_types_identical(x.elem, y.elem) - case Type_Info_Soa_Pointer: - y := b.variant.(Type_Info_Soa_Pointer) or_return + case ^Type_Info_Soa_Pointer: + y := b.variant.(^Type_Info_Soa_Pointer) or_return return are_types_identical(x.elem, y.elem) - case Type_Info_Procedure: - y := b.variant.(Type_Info_Procedure) or_return + case ^Type_Info_Procedure: + y := b.variant.(^Type_Info_Procedure) or_return switch { case x.variadic != y.variadic, x.convention != y.convention: @@ -82,27 +82,27 @@ are_types_identical :: proc(a, b: ^Type_Info) -> bool { return are_types_identical(x.params, y.params) && are_types_identical(x.results, y.results) - case Type_Info_Array: - y := b.variant.(Type_Info_Array) or_return + case ^Type_Info_Array: + y := b.variant.(^Type_Info_Array) or_return if x.count != y.count { return false } return are_types_identical(x.elem, y.elem) - case Type_Info_Enumerated_Array: - y := b.variant.(Type_Info_Enumerated_Array) or_return + case ^Type_Info_Enumerated_Array: + y := b.variant.(^Type_Info_Enumerated_Array) or_return if x.count != y.count { return false } return are_types_identical(x.index, y.index) && are_types_identical(x.elem, y.elem) - case Type_Info_Dynamic_Array: - y := b.variant.(Type_Info_Dynamic_Array) or_return + case ^Type_Info_Dynamic_Array: + y := b.variant.(^Type_Info_Dynamic_Array) or_return return are_types_identical(x.elem, y.elem) - case Type_Info_Slice: - y := b.variant.(Type_Info_Slice) or_return + case ^Type_Info_Slice: + y := b.variant.(^Type_Info_Slice) or_return return are_types_identical(x.elem, y.elem) - case Type_Info_Parameters: - y := b.variant.(Type_Info_Parameters) or_return + case ^Type_Info_Parameters: + y := b.variant.(^Type_Info_Parameters) or_return if len(x.types) != len(y.types) { return false } for _, i in x.types { xt, yt := x.types[i], y.types[i] @@ -112,8 +112,8 @@ are_types_identical :: proc(a, b: ^Type_Info) -> bool { } return true - case Type_Info_Struct: - y := b.variant.(Type_Info_Struct) or_return + case ^Type_Info_Struct: + y := b.variant.(^Type_Info_Struct) or_return switch { case x.field_count != y.field_count, x.flags != y.flags, @@ -133,8 +133,8 @@ are_types_identical :: proc(a, b: ^Type_Info) -> bool { } return true - case Type_Info_Union: - y := b.variant.(Type_Info_Union) or_return + case ^Type_Info_Union: + y := b.variant.(^Type_Info_Union) or_return if len(x.variants) != len(y.variants) { return false } for _, i in x.variants { @@ -143,31 +143,31 @@ are_types_identical :: proc(a, b: ^Type_Info) -> bool { } return true - case Type_Info_Enum: + case ^Type_Info_Enum: // NOTE(bill): Should be handled above return false - case Type_Info_Map: - y := b.variant.(Type_Info_Map) or_return + case ^Type_Info_Map: + y := b.variant.(^Type_Info_Map) or_return return are_types_identical(x.key, y.key) && are_types_identical(x.value, y.value) - case Type_Info_Bit_Set: - y := b.variant.(Type_Info_Bit_Set) or_return + case ^Type_Info_Bit_Set: + y := b.variant.(^Type_Info_Bit_Set) or_return return x.elem == y.elem && x.lower == y.lower && x.upper == y.upper - case Type_Info_Simd_Vector: - y := b.variant.(Type_Info_Simd_Vector) or_return + case ^Type_Info_Simd_Vector: + y := b.variant.(^Type_Info_Simd_Vector) or_return return x.count == y.count && x.elem == y.elem - case Type_Info_Matrix: - y := b.variant.(Type_Info_Matrix) or_return + case ^Type_Info_Matrix: + y := b.variant.(^Type_Info_Matrix) or_return if x.row_count != y.row_count { return false } if x.column_count != y.column_count { return false } if x.layout != y.layout { return false } return are_types_identical(x.elem, y.elem) - case Type_Info_Bit_Field: - y := b.variant.(Type_Info_Bit_Field) or_return + case ^Type_Info_Bit_Field: + y := b.variant.(^Type_Info_Bit_Field) or_return if !are_types_identical(x.backing_type, y.backing_type) { return false } if x.field_count != y.field_count { return false } for _, i in x.names[:x.field_count] { @@ -191,8 +191,8 @@ are_types_identical :: proc(a, b: ^Type_Info) -> bool { is_signed :: proc(info: ^Type_Info) -> bool { if info == nil { return false } #partial switch i in type_info_base(info).variant { - case Type_Info_Integer: return i.signed - case Type_Info_Float: return true + case ^Type_Info_Integer: return i.signed + case ^Type_Info_Float: return true } return false } @@ -200,8 +200,8 @@ is_signed :: proc(info: ^Type_Info) -> bool { is_unsigned :: proc(info: ^Type_Info) -> bool { if info == nil { return false } #partial switch i in type_info_base(info).variant { - case Type_Info_Integer: return !i.signed - case Type_Info_Float: return false + case ^Type_Info_Integer: return !i.signed + case ^Type_Info_Float: return false } return false } @@ -210,7 +210,7 @@ is_unsigned :: proc(info: ^Type_Info) -> bool { is_byte :: proc(info: ^Type_Info) -> bool { if info == nil { return false } #partial switch i in type_info_base(info).variant { - case Type_Info_Integer: return info.size == 1 + case ^Type_Info_Integer: return info.size == 1 } return false } @@ -219,83 +219,83 @@ is_byte :: proc(info: ^Type_Info) -> bool { @(require_results) is_integer :: proc(info: ^Type_Info) -> bool { if info == nil { return false } - _, ok := type_info_base(info).variant.(Type_Info_Integer) + _, ok := type_info_base(info).variant.(^Type_Info_Integer) return ok } @(require_results) is_rune :: proc(info: ^Type_Info) -> bool { if info == nil { return false } - _, ok := type_info_base(info).variant.(Type_Info_Rune) + _, ok := type_info_base(info).variant.(^Type_Info_Rune) return ok } @(require_results) is_float :: proc(info: ^Type_Info) -> bool { if info == nil { return false } - _, ok := type_info_base(info).variant.(Type_Info_Float) + _, ok := type_info_base(info).variant.(^Type_Info_Float) return ok } @(require_results) is_complex :: proc(info: ^Type_Info) -> bool { if info == nil { return false } - _, ok := type_info_base(info).variant.(Type_Info_Complex) + _, ok := type_info_base(info).variant.(^Type_Info_Complex) return ok } @(require_results) is_quaternion :: proc(info: ^Type_Info) -> bool { if info == nil { return false } - _, ok := type_info_base(info).variant.(Type_Info_Quaternion) + _, ok := type_info_base(info).variant.(^Type_Info_Quaternion) return ok } @(require_results) is_any :: proc(info: ^Type_Info) -> bool { if info == nil { return false } - _, ok := type_info_base(info).variant.(Type_Info_Any) + _, ok := type_info_base(info).variant.(^Type_Info_Any) return ok } @(require_results) is_string :: proc(info: ^Type_Info) -> bool { if info == nil { return false } - _, ok := type_info_base(info).variant.(Type_Info_String) + _, ok := type_info_base(info).variant.(^Type_Info_String) return ok } @(require_results) is_cstring :: proc(info: ^Type_Info) -> bool { if info == nil { return false } - v, ok := type_info_base(info).variant.(Type_Info_String) + v, ok := type_info_base(info).variant.(^Type_Info_String) return ok && v.is_cstring } @(require_results) is_boolean :: proc(info: ^Type_Info) -> bool { if info == nil { return false } - _, ok := type_info_base(info).variant.(Type_Info_Boolean) + _, ok := type_info_base(info).variant.(^Type_Info_Boolean) return ok } @(require_results) is_pointer :: proc(info: ^Type_Info) -> bool { if info == nil { return false } - _, ok := type_info_base(info).variant.(Type_Info_Pointer) + _, ok := type_info_base(info).variant.(^Type_Info_Pointer) return ok } @(require_results) is_multi_pointer :: proc(info: ^Type_Info) -> bool { if info == nil { return false } - _, ok := type_info_base(info).variant.(Type_Info_Multi_Pointer) + _, ok := type_info_base(info).variant.(^Type_Info_Multi_Pointer) return ok } @(require_results) is_soa_pointer :: proc(info: ^Type_Info) -> bool { if info == nil { return false } - _, ok := type_info_base(info).variant.(Type_Info_Soa_Pointer) + _, ok := type_info_base(info).variant.(^Type_Info_Soa_Pointer) return ok } @(require_results) is_pointer_internally :: proc(info: ^Type_Info) -> bool { if info == nil { return false } #partial switch v in info.variant { - case Type_Info_Pointer, Type_Info_Multi_Pointer, - Type_Info_Procedure: + case ^Type_Info_Pointer, ^Type_Info_Multi_Pointer, + ^Type_Info_Procedure: return true - case Type_Info_String: + case ^Type_Info_String: return v.is_cstring } return false @@ -303,85 +303,85 @@ is_pointer_internally :: proc(info: ^Type_Info) -> bool { @(require_results) is_procedure :: proc(info: ^Type_Info) -> bool { if info == nil { return false } - _, ok := type_info_base(info).variant.(Type_Info_Procedure) + _, ok := type_info_base(info).variant.(^Type_Info_Procedure) return ok } @(require_results) is_array :: proc(info: ^Type_Info) -> bool { if info == nil { return false } - _, ok := type_info_base(info).variant.(Type_Info_Array) + _, ok := type_info_base(info).variant.(^Type_Info_Array) return ok } @(require_results) is_enumerated_array :: proc(info: ^Type_Info) -> bool { if info == nil { return false } - _, ok := type_info_base(info).variant.(Type_Info_Enumerated_Array) + _, ok := type_info_base(info).variant.(^Type_Info_Enumerated_Array) return ok } @(require_results) is_dynamic_array :: proc(info: ^Type_Info) -> bool { if info == nil { return false } - _, ok := type_info_base(info).variant.(Type_Info_Dynamic_Array) + _, ok := type_info_base(info).variant.(^Type_Info_Dynamic_Array) return ok } @(require_results) is_dynamic_map :: proc(info: ^Type_Info) -> bool { if info == nil { return false } - _, ok := type_info_base(info).variant.(Type_Info_Map) + _, ok := type_info_base(info).variant.(^Type_Info_Map) return ok } @(require_results) is_bit_set :: proc(info: ^Type_Info) -> bool { if info == nil { return false } - _, ok := type_info_base(info).variant.(Type_Info_Bit_Set) + _, ok := type_info_base(info).variant.(^Type_Info_Bit_Set) return ok } @(require_results) is_slice :: proc(info: ^Type_Info) -> bool { if info == nil { return false } - _, ok := type_info_base(info).variant.(Type_Info_Slice) + _, ok := type_info_base(info).variant.(^Type_Info_Slice) return ok } @(require_results) is_parameters :: proc(info: ^Type_Info) -> bool { if info == nil { return false } - _, ok := type_info_base(info).variant.(Type_Info_Parameters) + _, ok := type_info_base(info).variant.(^Type_Info_Parameters) return ok } @(require_results, deprecated="prefer is_parameters") is_tuple :: proc(info: ^Type_Info) -> bool { if info == nil { return false } - _, ok := type_info_base(info).variant.(Type_Info_Parameters) + _, ok := type_info_base(info).variant.(^Type_Info_Parameters) return ok } @(require_results) is_struct :: proc(info: ^Type_Info) -> bool { if info == nil { return false } - s, ok := type_info_base(info).variant.(Type_Info_Struct) - return ok && .raw_union not_in s.flags + s, ok := type_info_base(info).variant.(^Type_Info_Struct) + return ok && .raw_union not_in s.struct_flags } @(require_results) is_raw_union :: proc(info: ^Type_Info) -> bool { if info == nil { return false } - s, ok := type_info_base(info).variant.(Type_Info_Struct) - return ok && .raw_union in s.flags + s, ok := type_info_base(info).variant.(^Type_Info_Struct) + return ok && .raw_union in s.struct_flags } @(require_results) is_union :: proc(info: ^Type_Info) -> bool { if info == nil { return false } - _, ok := type_info_base(info).variant.(Type_Info_Union) + _, ok := type_info_base(info).variant.(^Type_Info_Union) return ok } @(require_results) is_enum :: proc(info: ^Type_Info) -> bool { if info == nil { return false } - _, ok := type_info_base(info).variant.(Type_Info_Enum) + _, ok := type_info_base(info).variant.(^Type_Info_Enum) return ok } @(require_results) is_simd_vector :: proc(info: ^Type_Info) -> bool { if info == nil { return false } - _, ok := type_info_base(info).variant.(Type_Info_Simd_Vector) + _, ok := type_info_base(info).variant.(^Type_Info_Simd_Vector) return ok } @@ -392,14 +392,14 @@ is_endian_platform :: proc(info: ^Type_Info) -> bool { info := info info = type_info_core(info) #partial switch v in info.variant { - case Type_Info_Integer: + case ^Type_Info_Integer: return v.endianness == .Platform - case Type_Info_Bit_Set: + case ^Type_Info_Bit_Set: if v.underlying != nil { return is_endian_platform(v.underlying) } return true - case Type_Info_Pointer: + case ^Type_Info_Pointer: return true } return false @@ -411,17 +411,17 @@ is_endian_little :: proc(info: ^Type_Info) -> bool { info := info info = type_info_core(info) #partial switch v in info.variant { - case Type_Info_Integer: + case ^Type_Info_Integer: if v.endianness == .Platform { return ODIN_ENDIAN == .Little } return v.endianness == .Little - case Type_Info_Bit_Set: + case ^Type_Info_Bit_Set: if v.underlying != nil { return is_endian_platform(v.underlying) } return ODIN_ENDIAN == .Little - case Type_Info_Pointer: + case ^Type_Info_Pointer: return ODIN_ENDIAN == .Little } return ODIN_ENDIAN == .Little @@ -433,17 +433,17 @@ is_endian_big :: proc(info: ^Type_Info) -> bool { info := info info = type_info_core(info) #partial switch v in info.variant { - case Type_Info_Integer: + case ^Type_Info_Integer: if v.endianness == .Platform { return ODIN_ENDIAN == .Big } return v.endianness == .Big - case Type_Info_Bit_Set: + case ^Type_Info_Bit_Set: if v.underlying != nil { return is_endian_platform(v.underlying) } return ODIN_ENDIAN == .Big - case Type_Info_Pointer: + case ^Type_Info_Pointer: return ODIN_ENDIAN == .Big } return ODIN_ENDIAN == .Big @@ -483,9 +483,9 @@ write_type_writer :: #force_no_inline proc(w: io.Writer, ti: ^Type_Info, n_writt } switch info in ti.variant { - case Type_Info_Named: + case ^Type_Info_Named: io.write_string(w, info.name, &n) or_return - case Type_Info_Integer: + case ^Type_Info_Integer: switch ti.id { case int: io.write_string(w, "int", &n) or_return case uint: io.write_string(w, "uint", &n) or_return @@ -499,9 +499,9 @@ write_type_writer :: #force_no_inline proc(w: io.Writer, ti: ^Type_Info, n_writt case .Big: io.write_string(w, "be", &n) or_return } } - case Type_Info_Rune: + case ^Type_Info_Rune: io.write_string(w, "rune", &n) or_return - case Type_Info_Float: + case ^Type_Info_Float: io.write_byte(w, 'f', &n) or_return io.write_i64(w, i64(8*ti.size), 10, &n) or_return switch info.endianness { @@ -509,50 +509,50 @@ write_type_writer :: #force_no_inline proc(w: io.Writer, ti: ^Type_Info, n_writt case .Little: io.write_string(w, "le", &n) or_return case .Big: io.write_string(w, "be", &n) or_return } - case Type_Info_Complex: + case ^Type_Info_Complex: io.write_string(w, "complex", &n) or_return io.write_i64(w, i64(8*ti.size), 10, &n) or_return - case Type_Info_Quaternion: + case ^Type_Info_Quaternion: io.write_string(w, "quaternion", &n) or_return io.write_i64(w, i64(8*ti.size), 10, &n) or_return - case Type_Info_String: + case ^Type_Info_String: if info.is_cstring { io.write_string(w, "cstring", &n) or_return } else { io.write_string(w, "string", &n) or_return } - case Type_Info_Boolean: + case ^Type_Info_Boolean: switch ti.id { case bool: io.write_string(w, "bool", &n) or_return case: io.write_byte(w, 'b', &n) or_return io.write_i64(w, i64(8*ti.size), 10, &n) or_return } - case Type_Info_Any: + case ^Type_Info_Any: io.write_string(w, "any", &n) or_return - case Type_Info_Type_Id: + case ^Type_Info_Type_Id: io.write_string(w, "typeid", &n) or_return - case Type_Info_Pointer: + case ^Type_Info_Pointer: if info.elem == nil { io.write_string(w, "rawptr", &n) or_return } else { io.write_string(w, "^", &n) or_return write_type(w, info.elem, &n) or_return } - case Type_Info_Multi_Pointer: + case ^Type_Info_Multi_Pointer: io.write_string(w, "[^]", &n) or_return write_type(w, info.elem, &n) or_return - case Type_Info_Soa_Pointer: + case ^Type_Info_Soa_Pointer: io.write_string(w, "#soa ^", &n) or_return write_type(w, info.elem, &n) or_return - case Type_Info_Procedure: + case ^Type_Info_Procedure: io.write_string(w, "proc", &n) or_return if info.params == nil { io.write_string(w, "()", &n) or_return } else { - t := info.params.variant.(Type_Info_Parameters) + t := info.params.variant.(^Type_Info_Parameters) io.write_string(w, "(", &n) or_return for t, i in t.types { if i > 0 { @@ -566,7 +566,7 @@ write_type_writer :: #force_no_inline proc(w: io.Writer, ti: ^Type_Info, n_writt io.write_string(w, " -> ", &n) or_return write_type(w, info.results, &n) or_return } - case Type_Info_Parameters: + case ^Type_Info_Parameters: count := len(info.names) if count != 1 { io.write_string(w, "(", &n) or_return @@ -586,13 +586,13 @@ write_type_writer :: #force_no_inline proc(w: io.Writer, ti: ^Type_Info, n_writt io.write_string(w, ")", &n) or_return } - case Type_Info_Array: + case ^Type_Info_Array: io.write_string(w, "[", &n) or_return io.write_i64(w, i64(info.count), 10, &n) or_return io.write_string(w, "]", &n) or_return write_type(w, info.elem, &n) or_return - case Type_Info_Enumerated_Array: + case ^Type_Info_Enumerated_Array: if info.is_sparse { io.write_string(w, "#sparse", &n) or_return } @@ -601,20 +601,20 @@ write_type_writer :: #force_no_inline proc(w: io.Writer, ti: ^Type_Info, n_writt io.write_string(w, "]", &n) or_return write_type(w, info.elem, &n) or_return - case Type_Info_Dynamic_Array: + case ^Type_Info_Dynamic_Array: io.write_string(w, "[dynamic]", &n) or_return write_type(w, info.elem, &n) or_return - case Type_Info_Slice: + case ^Type_Info_Slice: io.write_string(w, "[]", &n) or_return write_type(w, info.elem, &n) or_return - case Type_Info_Map: + case ^Type_Info_Map: io.write_string(w, "map[", &n) or_return write_type(w, info.key, &n) or_return io.write_byte(w, ']', &n) or_return write_type(w, info.value, &n) or_return - case Type_Info_Struct: + case ^Type_Info_Struct: switch info.soa_kind { case .None: // Ignore case .Fixed: @@ -634,10 +634,10 @@ write_type_writer :: #force_no_inline proc(w: io.Writer, ti: ^Type_Info, n_writt } io.write_string(w, "struct ", &n) or_return - if .packed in info.flags { io.write_string(w, "#packed ", &n) or_return } - if .raw_union in info.flags { io.write_string(w, "#raw_union ", &n) or_return } - if .no_copy in info.flags { io.write_string(w, "#no_copy ", &n) or_return } - if .align in info.flags { + if .packed in info.struct_flags { io.write_string(w, "#packed ", &n) or_return } + if .raw_union in info.struct_flags { io.write_string(w, "#raw_union ", &n) or_return } + if .no_copy in info.struct_flags { io.write_string(w, "#no_copy ", &n) or_return } + if .align in info.struct_flags { io.write_string(w, "#align(", &n) or_return io.write_i64(w, i64(ti.align), 10, &n) or_return io.write_string(w, ") ", &n) or_return @@ -651,7 +651,7 @@ write_type_writer :: #force_no_inline proc(w: io.Writer, ti: ^Type_Info, n_writt } io.write_byte(w, '}', &n) or_return - case Type_Info_Union: + case ^Type_Info_Union: io.write_string(w, "union ", &n) or_return if info.no_nil { io.write_string(w, "#no_nil ", &n) or_return } if info.shared_nil { io.write_string(w, "#shared_nil ", &n) or_return } @@ -667,7 +667,7 @@ write_type_writer :: #force_no_inline proc(w: io.Writer, ti: ^Type_Info, n_writt } io.write_byte(w, '}', &n) or_return - case Type_Info_Enum: + case ^Type_Info_Enum: io.write_string(w, "enum ", &n) or_return write_type(w, info.base, &n) or_return io.write_string(w, " {", &n) or_return @@ -677,7 +677,7 @@ write_type_writer :: #force_no_inline proc(w: io.Writer, ti: ^Type_Info, n_writt } io.write_byte(w, '}', &n) or_return - case Type_Info_Bit_Set: + case ^Type_Info_Bit_Set: io.write_string(w, "bit_set[", &n) or_return switch { case is_enum(info.elem): @@ -697,7 +697,7 @@ write_type_writer :: #force_no_inline proc(w: io.Writer, ti: ^Type_Info, n_writt } io.write_byte(w, ']', &n) or_return - case Type_Info_Bit_Field: + case ^Type_Info_Bit_Field: io.write_string(w, "bit_field ", &n) or_return write_type(w, info.backing_type, &n) or_return io.write_string(w, " {", &n) or_return @@ -711,13 +711,13 @@ write_type_writer :: #force_no_inline proc(w: io.Writer, ti: ^Type_Info, n_writt } io.write_string(w, "}", &n) or_return - case Type_Info_Simd_Vector: + case ^Type_Info_Simd_Vector: io.write_string(w, "#simd[", &n) or_return io.write_i64(w, i64(info.count), 10, &n) or_return io.write_byte(w, ']', &n) or_return write_type(w, info.elem, &n) or_return - case Type_Info_Matrix: + case ^Type_Info_Matrix: if info.layout == .Row_Major { io.write_string(w, "#row_major ", &n) or_return } diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 88e099930..75fbbe941 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -2592,7 +2592,6 @@ gb_internal String lb_filepath_obj_for_module(lbModule *m) { path = gb_string_append_length(path, name.text, name.len); { - GB_ASSERT(m->module_name != nullptr); String s = make_string_c(m->module_name); String prefix = str_lit("odin_package"); diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp index 0705e2e93..2a01f75fb 100644 --- a/src/llvm_backend_general.cpp +++ b/src/llvm_backend_general.cpp @@ -18,23 +18,36 @@ gb_global isize lb_global_type_info_member_tags_index = 0; gb_internal void lb_init_module(lbModule *m, Checker *c) { m->info = &c->info; - gbString module_name = gb_string_make(heap_allocator(), "odin_package"); - if (m->file) { - if (m->pkg) { + + String name = build_context.build_paths[BuildPath_Output].name; + gbString module_name = gb_string_make(heap_allocator(), ""); + module_name = gb_string_append_length(module_name, name.text, name.len); + + if (!USE_SEPARATE_MODULES) { + // ignore suffixes + } else if (m->file) { + if (gb_string_length(module_name)) { + module_name = gb_string_appendc(module_name, "-"); + } + if (m->pkg) { + module_name = gb_string_append_length(module_name, m->pkg->name.text, m->pkg->name.len); module_name = gb_string_appendc(module_name, "-"); - module_name = gb_string_append_length(module_name, m->pkg->name.text, m->pkg->name.len); } - module_name = gb_string_appendc(module_name, "-"); String filename = filename_from_path(m->file->filename); module_name = gb_string_append_length(module_name, filename.text, filename.len); } else if (m->pkg) { - module_name = gb_string_appendc(module_name, "-"); + if (gb_string_length(module_name)) { + module_name = gb_string_appendc(module_name, "-"); + } module_name = gb_string_append_length(module_name, m->pkg->name.text, m->pkg->name.len); - } else if (USE_SEPARATE_MODULES) { - module_name = gb_string_appendc(module_name, "-builtin"); + } else { + if (gb_string_length(module_name)) { + module_name = gb_string_appendc(module_name, "-"); + } + module_name = gb_string_appendc(module_name, "builtin"); } - m->module_name = module_name ? module_name : "odin_package"; + m->module_name = module_name; m->ctx = LLVMContextCreate(); m->mod = LLVMModuleCreateWithNameInContext(m->module_name, m->ctx); // m->debug_builder = nullptr; @@ -2090,8 +2103,22 @@ gb_internal LLVMTypeRef lb_type_internal(lbModule *m, Type *type) { LLVMTypeRef variant = lb_type(m, type->Union.variants[0]); array_add(&fields, variant); } else { - LLVMTypeRef block_type = lb_type_padding_filler(m, block_size, align); - LLVMTypeRef tag_type = lb_type(m, union_tag_type(type)); + LLVMTypeRef block_type = nullptr; + + bool all_pointers = align == build_context.ptr_size; + for (isize i = 0; all_pointers && i < type->Union.variants.count; i++) { + Type *t = type->Union.variants[i]; + if (!is_type_internally_pointer_like(t)) { + all_pointers = false; + } + } + if (all_pointers) { + block_type = lb_type(m, t_rawptr); + } else { + block_type = lb_type_padding_filler(m, block_size, align); + } + + LLVMTypeRef tag_type = lb_type(m, union_tag_type(type)); array_add(&fields, block_type); array_add(&fields, tag_type); i64 used_size = lb_sizeof(block_type) + lb_sizeof(tag_type); diff --git a/src/llvm_backend_type.cpp b/src/llvm_backend_type.cpp index ad4250f3c..5383f9e0d 100644 --- a/src/llvm_backend_type.cpp +++ b/src/llvm_backend_type.cpp @@ -34,17 +34,23 @@ gb_internal u64 lb_typeid_kind(lbModule *m, Type *type, u64 id=0) { TypeKind tk = bt->kind; switch (tk) { case Type_Basic: { - u32 flags = bt->Basic.flags; - if (flags & BasicFlag_Boolean) kind = Typeid_Boolean; - if (flags & BasicFlag_Integer) kind = Typeid_Integer; - if (flags & BasicFlag_Unsigned) kind = Typeid_Integer; - if (flags & BasicFlag_Float) kind = Typeid_Float; - if (flags & BasicFlag_Complex) kind = Typeid_Complex; - if (flags & BasicFlag_Pointer) kind = Typeid_Pointer; - if (flags & BasicFlag_String) kind = Typeid_String; - if (flags & BasicFlag_Rune) kind = Typeid_Rune; + switch (bt->Basic.kind) { + case Basic_typeid: return Typeid_Type_Id; + case Basic_any: return Typeid_Any; + case Basic_rune: return Typeid_Rune; + } - if (bt->Basic.kind == Basic_typeid) kind = Typeid_Type_Id; + u32 flags = bt->Basic.flags; + if (0) {} + else if (flags & BasicFlag_Boolean) kind = Typeid_Boolean; + else if (flags & BasicFlag_Integer) kind = Typeid_Integer; + else if (flags & BasicFlag_Unsigned) kind = Typeid_Integer; + else if (flags & BasicFlag_Float) kind = Typeid_Float; + else if (flags & BasicFlag_Complex) kind = Typeid_Complex; + else if (flags & BasicFlag_Quaternion) kind = Typeid_Quaternion; + else if (flags & BasicFlag_Pointer) kind = Typeid_Pointer; + else if (flags & BasicFlag_String) kind = Typeid_String; + else GB_PANIC("Unhandled basic type"); } break; case Type_Pointer: kind = Typeid_Pointer; break; case Type_MultiPointer: kind = Typeid_Multi_Pointer; break; @@ -156,6 +162,7 @@ gb_internal lbValue lb_type_info_member_tags_offset(lbModule *m, isize count, i6 } gb_internal LLVMTypeRef *lb_setup_modified_types_for_type_info(lbModule *m, isize max_type_info_count) { +#if 0 LLVMTypeRef *element_types = gb_alloc_array(heap_allocator(), LLVMTypeRef, max_type_info_count); defer (gb_free(heap_allocator(), element_types)); @@ -213,6 +220,22 @@ gb_internal LLVMTypeRef *lb_setup_modified_types_for_type_info(lbModule *m, isiz } return modified_types; +#else + Type *tibt = base_type(t_type_info); + GB_ASSERT(tibt->kind == Type_Struct); + Type *ut = base_type(tibt->Struct.fields[tibt->Struct.fields.count-1]->type); + GB_ASSERT(ut->kind == Type_Union); + + LLVMTypeRef *modified_types = gb_alloc_array(heap_allocator(), LLVMTypeRef, Typeid__COUNT); + GB_ASSERT(Typeid__COUNT == ut->Union.variants.count); + for_array(i, ut->Union.variants) { + Type *pt = ut->Union.variants[i]; + Type *t = type_deref(pt); + modified_types[i] = lb_type(m, t); + } + + return modified_types; +#endif } gb_internal void lb_setup_type_info_data_giant_array(lbModule *m, i64 global_type_info_data_entity_count) { // NOTE(bill): Setup type_info data @@ -281,7 +304,8 @@ gb_internal void lb_setup_type_info_data_giant_array(lbModule *m, i64 global_typ } - LLVMValueRef *small_const_values = gb_alloc_array(heap_allocator(), LLVMValueRef, 6); + enum {SMALL_CONST_VALUES_COUNT = 6}; + LLVMValueRef *small_const_values = gb_alloc_array(heap_allocator(), LLVMValueRef, SMALL_CONST_VALUES_COUNT); defer (gb_free(heap_allocator(), small_const_values)); #define type_info_allocate_values(name) \ @@ -330,7 +354,6 @@ gb_internal void lb_setup_type_info_data_giant_array(lbModule *m, i64 global_typ } entries_handled[entry_index] = true; - LLVMTypeRef stype = nullptr; if (t->kind == Type_Named) { stype = modified_types[0]; @@ -338,39 +361,9 @@ gb_internal void lb_setup_type_info_data_giant_array(lbModule *m, i64 global_typ stype = modified_types[lb_typeid_kind(m, t)]; } - i64 size = type_size_of(t); - i64 align = type_align_of(t); - u32 flags = type_info_flags_of_type(t); - lbValue id = lb_typeid(m, t); - GB_ASSERT_MSG(align != 0, "%lld %s", align, type_to_string(t)); - lbValue type_info_flags = lb_const_int(m, t_type_info_flags, flags); + LLVMValueRef vals[32] = {}; - for (isize i = 0; i < 6; i++) { - small_const_values[i] = nullptr; - } - - small_const_values[0] = LLVMConstInt(lb_type(m, t_int), size, true); - small_const_values[1] = LLVMConstInt(lb_type(m, t_int), align, true); - small_const_values[2] = type_info_flags.value; - - unsigned variant_index = 0; - if (build_context.ptr_size == 8) { - small_const_values[3] = LLVMConstNull(LLVMStructGetTypeAtIndex(stype, 3)); - small_const_values[4] = id.value; - variant_index = 5; - } else { - small_const_values[3] = id.value; - variant_index = 4; - } - - LLVMTypeRef full_variant_type = LLVMStructGetTypeAtIndex(stype, variant_index); - unsigned full_variant_elem_count = LLVMCountStructElementTypes(full_variant_type); - if (full_variant_elem_count != 2) { - GB_ASSERT_MSG(LLVMCountStructElementTypes(full_variant_type) == 3, "%lld %s", entry_index, type_to_string(t)); // blob, padding, tag - } - - LLVMValueRef variant_value = nullptr; Type *tag_type = nullptr; switch (t->kind) { @@ -395,14 +388,11 @@ gb_internal void lb_setup_type_info_data_giant_array(lbModule *m, i64 global_typ lbValue loc = lb_const_source_code_location_as_global_ptr(m, proc_name, pos); - LLVMValueRef vals[4] = { - lb_const_string(m, t->Named.type_name->token.string).value, - get_type_info_ptr(m, t->Named.base), - pkg_name, - loc.value - }; - variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals)); + vals[1] = lb_const_string(m, t->Named.type_name->token.string).value; + vals[2] = get_type_info_ptr(m, t->Named.base); + vals[3] = pkg_name; + vals[4] = loc.value; break; } @@ -459,12 +449,8 @@ gb_internal void lb_setup_type_info_data_giant_array(lbModule *m, i64 global_typ } lbValue endianness = lb_const_int(m, t_u8, endianness_value); - LLVMValueRef vals[2] = { - is_signed.value, - endianness.value, - }; - - variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals)); + vals[1] = is_signed.value; + vals[2] = endianness.value; break; } @@ -493,11 +479,7 @@ gb_internal void lb_setup_type_info_data_giant_array(lbModule *m, i64 global_typ } lbValue endianness = lb_const_int(m, t_u8, endianness_value); - LLVMValueRef vals[1] = { - endianness.value, - }; - - variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals)); + vals[1] = endianness.value; } break; @@ -515,21 +497,17 @@ gb_internal void lb_setup_type_info_data_giant_array(lbModule *m, i64 global_typ case Basic_rawptr: tag_type = t_type_info_pointer; + vals[1] = LLVMConstNull(lb_type(m, t_type_info_ptr)); break; case Basic_string: tag_type = t_type_info_string; + vals[1] = lb_const_bool(m, t_bool, false).value; break; case Basic_cstring: - { - tag_type = t_type_info_string; - LLVMValueRef vals[1] = { - lb_const_bool(m, t_bool, true).value, - }; - - variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals)); - } + tag_type = t_type_info_string; + vals[1] = lb_const_bool(m, t_bool, true).value; break; case Basic_any: @@ -542,90 +520,53 @@ gb_internal void lb_setup_type_info_data_giant_array(lbModule *m, i64 global_typ } break; - case Type_Pointer: { + case Type_Pointer: tag_type = t_type_info_pointer; - LLVMValueRef vals[1] = { - get_type_info_ptr(m, t->Pointer.elem), - }; - - - variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals)); + vals[1] = get_type_info_ptr(m, t->Pointer.elem); break; - } - case Type_MultiPointer: { + case Type_MultiPointer: tag_type = t_type_info_multi_pointer; - - LLVMValueRef vals[1] = { - get_type_info_ptr(m, t->MultiPointer.elem), - }; - - variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals)); + vals[1] = get_type_info_ptr(m, t->MultiPointer.elem); break; - } - case Type_SoaPointer: { + case Type_SoaPointer: tag_type = t_type_info_soa_pointer; - - LLVMValueRef vals[1] = { - get_type_info_ptr(m, t->SoaPointer.elem), - }; - - variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals)); + vals[1] = get_type_info_ptr(m, t->SoaPointer.elem); break; - } case Type_Array: { tag_type = t_type_info_array; i64 ez = type_size_of(t->Array.elem); - LLVMValueRef vals[3] = { - get_type_info_ptr(m, t->Array.elem), - lb_const_int(m, t_int, ez).value, - lb_const_int(m, t_int, t->Array.count).value, - }; - - variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals)); + vals[1] = get_type_info_ptr(m, t->Array.elem); + vals[2] = lb_const_int(m, t_int, ez).value; + vals[3] = lb_const_int(m, t_int, t->Array.count).value; break; } - case Type_EnumeratedArray: { + case Type_EnumeratedArray: tag_type = t_type_info_enumerated_array; - LLVMValueRef vals[7] = { - get_type_info_ptr(m, t->EnumeratedArray.elem), - get_type_info_ptr(m, t->EnumeratedArray.index), - lb_const_int(m, t_int, type_size_of(t->EnumeratedArray.elem)).value, - lb_const_int(m, t_int, t->EnumeratedArray.count).value, + vals[1] = get_type_info_ptr(m, t->EnumeratedArray.elem); + vals[2] = get_type_info_ptr(m, t->EnumeratedArray.index); + vals[3] = lb_const_int(m, t_int, type_size_of(t->EnumeratedArray.elem)).value; + vals[4] = lb_const_int(m, t_int, t->EnumeratedArray.count).value; // Unions - lb_const_value(m, t_type_info_enum_value, *t->EnumeratedArray.min_value).value, - lb_const_value(m, t_type_info_enum_value, *t->EnumeratedArray.max_value).value, + vals[5] = lb_const_value(m, t_type_info_enum_value, *t->EnumeratedArray.min_value).value; + vals[6] = lb_const_value(m, t_type_info_enum_value, *t->EnumeratedArray.max_value).value; - lb_const_bool(m, t_bool, t->EnumeratedArray.is_sparse).value, - }; - - variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals)); + vals[7] = lb_const_bool(m, t_bool, t->EnumeratedArray.is_sparse).value; break; - } - case Type_DynamicArray: { + case Type_DynamicArray: tag_type = t_type_info_dynamic_array; - LLVMValueRef vals[2] = { - get_type_info_ptr(m, t->DynamicArray.elem), - lb_const_int(m, t_int, type_size_of(t->DynamicArray.elem)).value, - }; - - variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals)); + vals[1] = get_type_info_ptr(m, t->DynamicArray.elem); + vals[2] = lb_const_int(m, t_int, type_size_of(t->DynamicArray.elem)).value; break; - } - case Type_Slice: { + case Type_Slice: tag_type = t_type_info_slice; - LLVMValueRef vals[2] = { - get_type_info_ptr(m, t->Slice.elem), - lb_const_int(m, t_int, type_size_of(t->Slice.elem)).value, - }; - - variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals)); + vals[1] = get_type_info_ptr(m, t->Slice.elem); + vals[2] = lb_const_int(m, t_int, type_size_of(t->Slice.elem)).value; break; - } case Type_Proc: { tag_type = t_type_info_procedure; @@ -638,14 +579,10 @@ gb_internal void lb_setup_type_info_data_giant_array(lbModule *m, i64 global_typ results = get_type_info_ptr(m, t->Proc.results); } - LLVMValueRef vals[4] = { - params, - results, - lb_const_bool(m, t_bool, t->Proc.variadic).value, - lb_const_int(m, t_u8, t->Proc.calling_convention).value, - }; - - variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals)); + vals[1] = params; + vals[2] = results; + vals[3] = lb_const_bool(m, t_bool, t->Proc.variadic).value; + vals[4] = lb_const_int(m, t_u8, t->Proc.calling_convention).value; break; } case Type_Tuple: { @@ -673,61 +610,47 @@ gb_internal void lb_setup_type_info_data_giant_array(lbModule *m, i64 global_typ LLVMValueRef types_slice = llvm_const_slice(m, memory_types, count); LLVMValueRef names_slice = llvm_const_slice(m, memory_names, count); - LLVMValueRef vals[2] = { - types_slice, - names_slice, - }; - - variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals)); + vals[1] = types_slice; + vals[2] = names_slice; break; } case Type_Enum: tag_type = t_type_info_enum; - - { - GB_ASSERT(t->Enum.base_type != nullptr); - // GB_ASSERT_MSG(type_size_of(t_type_info_enum_value) == 16, "%lld == 16", cast(long long)type_size_of(t_type_info_enum_value)); + GB_ASSERT(t->Enum.base_type != nullptr); + vals[1] = get_type_info_ptr(m, t->Enum.base_type); + if (t->Enum.fields.count > 0) { + auto fields = t->Enum.fields; + lbValue name_array = lb_generate_global_array(m, t_string, fields.count, + str_lit("$enum_names"), cast(i64)entry_index); + lbValue value_array = lb_generate_global_array(m, t_type_info_enum_value, fields.count, + str_lit("$enum_values"), cast(i64)entry_index); - LLVMValueRef vals[3] = {}; - vals[0] = get_type_info_ptr(m, t->Enum.base_type); - if (t->Enum.fields.count > 0) { - auto fields = t->Enum.fields; - lbValue name_array = lb_generate_global_array(m, t_string, fields.count, - str_lit("$enum_names"), cast(i64)entry_index); - lbValue value_array = lb_generate_global_array(m, t_type_info_enum_value, fields.count, - str_lit("$enum_values"), cast(i64)entry_index); + LLVMValueRef *name_values = gb_alloc_array(temporary_allocator(), LLVMValueRef, fields.count); + LLVMValueRef *value_values = gb_alloc_array(temporary_allocator(), LLVMValueRef, fields.count); + GB_ASSERT(is_type_integer(t->Enum.base_type)); - LLVMValueRef *name_values = gb_alloc_array(temporary_allocator(), LLVMValueRef, fields.count); - LLVMValueRef *value_values = gb_alloc_array(temporary_allocator(), LLVMValueRef, fields.count); - - GB_ASSERT(is_type_integer(t->Enum.base_type)); - - for_array(i, fields) { - name_values[i] = lb_const_string(m, fields[i]->token.string).value; - value_values[i] = lb_const_value(m, t_i64, fields[i]->Constant.value).value; - } - - LLVMValueRef name_init = llvm_const_array(lb_type(m, t_string), name_values, cast(unsigned)fields.count); - LLVMValueRef value_init = llvm_const_array(lb_type(m, t_type_info_enum_value), value_values, cast(unsigned)fields.count); - LLVMSetInitializer(name_array.value, name_init); - LLVMSetInitializer(value_array.value, value_init); - LLVMSetGlobalConstant(name_array.value, true); - LLVMSetGlobalConstant(value_array.value, true); - - lbValue v_count = lb_const_int(m, t_int, fields.count); - - vals[1] = llvm_const_slice(m, lbValue{name_array.value, alloc_type_pointer(t_string)}, v_count); - vals[2] = llvm_const_slice(m, lbValue{value_array.value, alloc_type_pointer(t_type_info_enum_value)}, v_count); - } else { - vals[1] = LLVMConstNull(lb_type(m, base_type(t_type_info_enum)->Struct.fields[1]->type)); - vals[2] = LLVMConstNull(lb_type(m, base_type(t_type_info_enum)->Struct.fields[2]->type)); + for_array(i, fields) { + name_values[i] = lb_const_string(m, fields[i]->token.string).value; + value_values[i] = lb_const_value(m, t_i64, fields[i]->Constant.value).value; } + LLVMValueRef name_init = llvm_const_array(lb_type(m, t_string), name_values, cast(unsigned)fields.count); + LLVMValueRef value_init = llvm_const_array(lb_type(m, t_type_info_enum_value), value_values, cast(unsigned)fields.count); + LLVMSetInitializer(name_array.value, name_init); + LLVMSetInitializer(value_array.value, value_init); + LLVMSetGlobalConstant(name_array.value, true); + LLVMSetGlobalConstant(value_array.value, true); - variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals)); + lbValue v_count = lb_const_int(m, t_int, fields.count); + + vals[2] = llvm_const_slice(m, lbValue{name_array.value, alloc_type_pointer(t_string)}, v_count); + vals[3] = llvm_const_slice(m, lbValue{value_array.value, alloc_type_pointer(t_type_info_enum_value)}, v_count); + } else { + vals[2] = LLVMConstNull(LLVMStructGetTypeAtIndex(stype, 2)); + vals[3] = LLVMConstNull(LLVMStructGetTypeAtIndex(stype, 3)); } break; @@ -735,8 +658,6 @@ gb_internal void lb_setup_type_info_data_giant_array(lbModule *m, i64 global_typ tag_type = t_type_info_union; { - LLVMValueRef vals[7] = {}; - isize variant_count = gb_max(0, t->Union.variants.count); i64 variant_offset = 0; lbValue memory_types = lb_type_info_member_types_offset(m, variant_count, &variant_offset); @@ -747,33 +668,27 @@ gb_internal void lb_setup_type_info_data_giant_array(lbModule *m, i64 global_typ } lbValue count = lb_const_int(m, t_int, variant_count); - vals[0] = llvm_const_slice(m, memory_types, count); + vals[1] = llvm_const_slice(m, memory_types, count); i64 tag_size = union_tag_size(t); if (tag_size > 0) { i64 tag_offset = align_formula(t->Union.variant_block_size, tag_size); - vals[1] = lb_const_int(m, t_uintptr, tag_offset).value; - vals[2] = get_type_info_ptr(m, union_tag_type(t)); + vals[2] = lb_const_int(m, t_uintptr, tag_offset).value; + vals[3] = get_type_info_ptr(m, union_tag_type(t)); } else { - vals[1] = lb_const_int(m, t_uintptr, 0).value; - vals[2] = LLVMConstNull(lb_type(m, t_type_info_ptr)); + vals[2] = lb_const_int(m, t_uintptr, 0).value; + vals[3] = LLVMConstNull(lb_type(m, t_type_info_ptr)); } if (is_type_comparable(t) && !is_type_simple_compare(t)) { - vals[3] = lb_equal_proc_for_type(m, t).value; + vals[4] = lb_equal_proc_for_type(m, t).value; + } else { + vals[4] = LLVMConstNull(lb_type(m, t_equal_proc)); } - vals[4] = lb_const_bool(m, t_bool, t->Union.custom_align != 0).value; - vals[5] = lb_const_bool(m, t_bool, t->Union.kind == UnionType_no_nil).value; - vals[6] = lb_const_bool(m, t_bool, t->Union.kind == UnionType_shared_nil).value; - - for (isize i = 0; i < gb_count_of(vals); i++) { - if (vals[i] == nullptr) { - vals[i] = LLVMConstNull(lb_type(m, get_struct_field_type(tag_type, i))); - } - } - - variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals)); + vals[5] = lb_const_bool(m, t_bool, t->Union.custom_align != 0).value; + vals[6] = lb_const_bool(m, t_bool, t->Union.kind == UnionType_no_nil).value; + vals[7] = lb_const_bool(m, t_bool, t->Union.kind == UnionType_shared_nil).value; } break; @@ -782,8 +697,6 @@ gb_internal void lb_setup_type_info_data_giant_array(lbModule *m, i64 global_typ case Type_Struct: { tag_type = t_type_info_struct; - LLVMValueRef vals[11] = {}; - { u8 flags = 0; if (t->Struct.is_packed) flags |= 1<<0; @@ -791,23 +704,31 @@ gb_internal void lb_setup_type_info_data_giant_array(lbModule *m, i64 global_typ if (t->Struct.is_no_copy) flags |= 1<<2; if (t->Struct.custom_align) flags |= 1<<3; - vals[6] = lb_const_int(m, t_u8, flags).value; + vals[7] = lb_const_int(m, t_u8, flags).value; if (is_type_comparable(t) && !is_type_simple_compare(t)) { - vals[10] = lb_equal_proc_for_type(m, t).value; + vals[13] = lb_equal_proc_for_type(m, t).value; + } else { + vals[13] = LLVMConstNull(lb_type(m, t_equal_proc)); } + Type *soa_kind_type = get_struct_field_type(tag_type, 7); if (t->Struct.soa_kind != StructSoa_None) { - Type *kind_type = get_struct_field_type(tag_type, 7); - lbValue soa_kind = lb_const_value(m, kind_type, exact_value_i64(t->Struct.soa_kind)); + lbValue soa_kind = lb_const_value(m, soa_kind_type, exact_value_i64(t->Struct.soa_kind)); LLVMValueRef soa_type = get_type_info_ptr(m, t->Struct.soa_elem); lbValue soa_len = lb_const_int(m, t_i32, t->Struct.soa_count); - vals[7] = soa_kind.value; - vals[8] = soa_len.value; - vals[9] = soa_type; + vals[8] = soa_kind.value; + vals[10] = soa_len.value; + vals[12] = soa_type; + } else { + vals[8] = LLVMConstNull(lb_type(m, soa_kind_type)); + vals[10] = LLVMConstNull(lb_type(m, t_i32)); + vals[12] = LLVMConstNull(lb_type(m, t_type_info_ptr)); } + vals[9] = LLVMConstNull(lb_type(m, base_type(t_type_info_struct)->Struct.fields[9]->type)); + vals[11] = LLVMConstNull(lb_type(m, base_type(t_type_info_struct)->Struct.fields[11]->type)); } isize count = t->Struct.fields.count; @@ -854,70 +775,53 @@ gb_internal void lb_setup_type_info_data_giant_array(lbModule *m, i64 global_typ } lbValue cv = lb_const_int(m, t_i32, count); - vals[0] = memory_types.value; - vals[1] = memory_names.value; - vals[2] = memory_offsets.value; - vals[3] = memory_usings.value; - vals[4] = memory_tags.value; - vals[5] = cv.value; + vals[1] = memory_types.value; + vals[2] = memory_names.value; + vals[3] = memory_offsets.value; + vals[4] = memory_usings.value; + vals[5] = memory_tags.value; + vals[6] = cv.value; + } else { + vals[1] = LLVMConstNull(lb_type(m, base_type(t_type_info_struct)->Struct.fields[1]->type)); + vals[2] = LLVMConstNull(lb_type(m, base_type(t_type_info_struct)->Struct.fields[2]->type)); + vals[3] = LLVMConstNull(lb_type(m, base_type(t_type_info_struct)->Struct.fields[3]->type)); + vals[4] = LLVMConstNull(lb_type(m, base_type(t_type_info_struct)->Struct.fields[4]->type)); + vals[5] = LLVMConstNull(lb_type(m, base_type(t_type_info_struct)->Struct.fields[5]->type)); + vals[6] = LLVMConstNull(lb_type(m, base_type(t_type_info_struct)->Struct.fields[6]->type)); } - for (isize i = 0; i < gb_count_of(vals); i++) { - if (vals[i] == nullptr) { - vals[i] = LLVMConstNull(lb_type(m, get_struct_field_type(tag_type, i))); - } - } - - variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals)); break; } - case Type_Map: { + case Type_Map: tag_type = t_type_info_map; init_map_internal_debug_types(t); - LLVMValueRef vals[3] = { - get_type_info_ptr(m, t->Map.key), - get_type_info_ptr(m, t->Map.value), - lb_gen_map_info_ptr(m, t).value - }; - - variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals)); + vals[1] = get_type_info_ptr(m, t->Map.key); + vals[2] = get_type_info_ptr(m, t->Map.value); + vals[3] = lb_gen_map_info_ptr(m, t).value; break; - } case Type_BitSet: - { - tag_type = t_type_info_bit_set; + tag_type = t_type_info_bit_set; - GB_ASSERT(is_type_typed(t->BitSet.elem)); + GB_ASSERT(is_type_typed(t->BitSet.elem)); + vals[1] = get_type_info_ptr(m, t->BitSet.elem); + vals[2] = LLVMConstNull(lb_type(m, t_type_info_ptr)); + vals[3] = lb_const_int(m, t_i64, t->BitSet.lower).value; + vals[4] = lb_const_int(m, t_i64, t->BitSet.upper).value; - LLVMValueRef vals[4] = { - get_type_info_ptr(m, t->BitSet.elem), - LLVMConstNull(lb_type(m, t_type_info_ptr)), - lb_const_int(m, t_i64, t->BitSet.lower).value, - lb_const_int(m, t_i64, t->BitSet.upper).value, - }; - if (t->BitSet.underlying != nullptr) { - vals[1] = get_type_info_ptr(m, t->BitSet.underlying); - } - - variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals)); + if (t->BitSet.underlying != nullptr) { + vals[2] = get_type_info_ptr(m, t->BitSet.underlying); } break; case Type_SimdVector: - { - tag_type = t_type_info_simd_vector; + tag_type = t_type_info_simd_vector; - LLVMValueRef vals[3] = {}; - - vals[0] = get_type_info_ptr(m, t->SimdVector.elem); - vals[1] = lb_const_int(m, t_int, type_size_of(t->SimdVector.elem)).value; - vals[2] = lb_const_int(m, t_int, t->SimdVector.count).value; - - variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals)); - } + vals[1] = get_type_info_ptr(m, t->SimdVector.elem); + vals[2] = lb_const_int(m, t_int, type_size_of(t->SimdVector.elem)).value; + vals[3] = lb_const_int(m, t_int, t->SimdVector.count).value; break; case Type_Matrix: @@ -925,16 +829,12 @@ gb_internal void lb_setup_type_info_data_giant_array(lbModule *m, i64 global_typ tag_type = t_type_info_matrix; i64 ez = type_size_of(t->Matrix.elem); - LLVMValueRef vals[6] = { - get_type_info_ptr(m, t->Matrix.elem), - lb_const_int(m, t_int, ez).value, - lb_const_int(m, t_int, matrix_type_stride_in_elems(t)).value, - lb_const_int(m, t_int, t->Matrix.row_count).value, - lb_const_int(m, t_int, t->Matrix.column_count).value, - lb_const_int(m, t_u8, cast(u8)t->Matrix.is_row_major).value, - }; - - variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals)); + vals[1] = get_type_info_ptr(m, t->Matrix.elem); + vals[2] = lb_const_int(m, t_int, ez).value; + vals[3] = lb_const_int(m, t_int, matrix_type_stride_in_elems(t)).value; + vals[4] = lb_const_int(m, t_int, t->Matrix.row_count).value; + vals[5] = lb_const_int(m, t_int, t->Matrix.column_count).value; + vals[6] = lb_const_int(m, t_u8, cast(u8)t->Matrix.is_row_major).value; } break; @@ -942,8 +842,7 @@ gb_internal void lb_setup_type_info_data_giant_array(lbModule *m, i64 global_typ { tag_type = t_type_info_bit_field; - LLVMValueRef vals[7] = {}; - vals[0] = get_type_info_ptr(m, t->BitField.backing_type); + vals[1] = get_type_info_ptr(m, t->BitField.backing_type); isize count = t->BitField.fields.count; if (count > 0) { i64 names_offset = 0; @@ -983,64 +882,91 @@ gb_internal void lb_setup_type_info_data_giant_array(lbModule *m, i64 global_typ } lbValue cv = lb_const_int(m, t_int, count); - vals[1] = memory_names.value; - vals[2] = memory_types.value; - vals[3] = memory_bit_sizes.value; - vals[4] = memory_bit_offsets.value; - vals[5] = memory_tags.value; - vals[6] = cv.value; + vals[2] = memory_names.value; + vals[3] = memory_types.value; + vals[4] = memory_bit_sizes.value; + vals[5] = memory_bit_offsets.value; + vals[6] = memory_tags.value; + vals[7] = cv.value; + } else { + vals[2] = LLVMConstNull(lb_type(m, base_type(t_type_info_bit_field)->Struct.fields[2]->type)); + vals[3] = LLVMConstNull(lb_type(m, base_type(t_type_info_bit_field)->Struct.fields[3]->type)); + vals[4] = LLVMConstNull(lb_type(m, base_type(t_type_info_bit_field)->Struct.fields[4]->type)); + vals[5] = LLVMConstNull(lb_type(m, base_type(t_type_info_bit_field)->Struct.fields[5]->type)); + vals[6] = LLVMConstNull(lb_type(m, base_type(t_type_info_bit_field)->Struct.fields[6]->type)); + vals[7] = LLVMConstNull(lb_type(m, base_type(t_type_info_bit_field)->Struct.fields[7]->type)); } - - - for (isize i = 0; i < gb_count_of(vals); i++) { - if (vals[i] == nullptr) { - vals[i] = LLVMConstNull(lb_type(m, get_struct_field_type(tag_type, i))); - } - } - - variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals)); break; } } + i64 size = type_size_of(t); + i64 align = type_align_of(t); + u32 flags = type_info_flags_of_type(t); + lbValue id = lb_typeid(m, t); + GB_ASSERT_MSG(align != 0, "%lld %s", align, type_to_string(t)); + + lbValue type_info_flags = lb_const_int(m, t_type_info_flags, flags); + + for (isize i = 0; i < SMALL_CONST_VALUES_COUNT; i++) { + small_const_values[i] = nullptr; + } + + small_const_values[0] = LLVMConstInt(lb_type(m, t_int), size, true); + small_const_values[1] = LLVMConstInt(lb_type(m, t_int), align, true); + small_const_values[2] = type_info_flags.value; + + unsigned variant_index = 0; + if (build_context.ptr_size == 8) { + LLVMTypeRef base_type_info_type = LLVMStructGetTypeAtIndex(stype, 0); + small_const_values[3] = LLVMConstNull(LLVMStructGetTypeAtIndex(base_type_info_type, 3)); + small_const_values[4] = id.value; + variant_index = 5; + } else { + small_const_values[3] = id.value; + variant_index = 4; + } + i64 tag_index = 0; if (tag_type != nullptr) { - tag_index = union_variant_index(ut, tag_type); + tag_index = union_variant_index(ut, alloc_type_pointer(tag_type)); } GB_ASSERT(tag_index <= Typeid__COUNT); - LLVMValueRef full_variant_values[3] = {}; + LLVMValueRef full_variant_values[2] = {}; - if (full_variant_elem_count == 2) { - if (variant_value == nullptr) { - full_variant_values[0] = LLVMConstNull(LLVMStructGetTypeAtIndex(full_variant_type, 0)); - full_variant_values[1] = LLVMConstInt(LLVMStructGetTypeAtIndex(full_variant_type, 1), tag_index, false); - } else { - full_variant_values[0] = variant_value; - full_variant_values[1] = LLVMConstInt(LLVMStructGetTypeAtIndex(full_variant_type, 1), tag_index, false); - } + LLVMTypeRef type_info_base_type = LLVMStructGetTypeAtIndex(stype, 0); + LLVMTypeRef variant_type = LLVMStructGetTypeAtIndex(type_info_base_type, LLVMCountStructElementTypes(type_info_base_type)-1); + + if (tag_type == nullptr) { + full_variant_values[0] = LLVMConstNull(LLVMStructGetTypeAtIndex(variant_type, 0)); + full_variant_values[1] = LLVMConstInt(LLVMStructGetTypeAtIndex(variant_type, 1), tag_index, false); } else { - if (variant_value == nullptr) { - variant_value = LLVMConstNull(LLVMStructGetTypeAtIndex(full_variant_type, 0)); - } else { - GB_ASSERT_MSG(LLVMStructGetTypeAtIndex(full_variant_type, 0) == LLVMTypeOf(variant_value), - "\n%s -> %s\n%s vs %s\n", - type_to_string(t), LLVMPrintValueToString(variant_value), - LLVMPrintTypeToString(LLVMStructGetTypeAtIndex(full_variant_type, 0)), LLVMPrintTypeToString(LLVMTypeOf(variant_value)) - ); - } - - full_variant_values[0] = variant_value; - full_variant_values[1] = LLVMConstNull(LLVMStructGetTypeAtIndex(full_variant_type, 1)); - full_variant_values[2] = LLVMConstInt(LLVMStructGetTypeAtIndex(full_variant_type, 2), tag_index, false); + full_variant_values[0] = LLVMConstPointerCast(giant_const_values[entry_index], LLVMStructGetTypeAtIndex(variant_type, 0)); + full_variant_values[1] = LLVMConstInt(LLVMStructGetTypeAtIndex(variant_type, 1), tag_index, false); } - LLVMValueRef full_variant_value = LLVMConstNamedStruct(full_variant_type, full_variant_values, full_variant_elem_count); + LLVMValueRef full_variant_value = LLVMConstNamedStruct(variant_type, full_variant_values, 2); small_const_values[variant_index] = full_variant_value; - LLVMSetInitializer(giant_const_values[entry_index], LLVMConstNamedStruct(stype, small_const_values, variant_index+1)); + vals[0] = LLVMConstNamedStruct(LLVMStructGetTypeAtIndex(stype, 0), small_const_values, variant_index+1); + + unsigned total_elem_count = LLVMCountStructElementTypes(stype); + for (unsigned i = 0; i < total_elem_count; i++) { + if (vals[i] == nullptr) { + if (i+1 == total_elem_count) { + LLVMTypeRef end_type = LLVMStructGetTypeAtIndex(stype, i); + GB_ASSERT_MSG(LLVMGetTypeKind(end_type) == LLVMArrayTypeKind, "%s %s %u < %u %s", LLVMPrintTypeToString(end_type), type_to_string(tag_type), i, total_elem_count, LLVMPrintTypeToString(stype)); + vals[i] = LLVMConstNull(end_type); + } else { + GB_PANIC("HERE! %s %u < %u %s %d", type_to_string(tag_type), i, total_elem_count, LLVMPrintTypeToString(stype), lb_typeid_kind(m, t)); + } + } + } + + LLVMSetInitializer(giant_const_values[entry_index], LLVMConstNamedStruct(stype, vals, total_elem_count)); } for (isize i = 0; i < global_type_info_data_entity_count; i++) { auto *ptr = &giant_const_values[i]; @@ -1073,9 +999,7 @@ gb_internal void lb_setup_type_info_data(lbModule *m) { // NOTE(bill): Setup typ GB_ASSERT(type->kind == Type_Array); global_type_info_data_entity_count = type->Array.count; - if (true) { - lb_setup_type_info_data_giant_array(m, global_type_info_data_entity_count); - } + lb_setup_type_info_data_giant_array(m, global_type_info_data_entity_count); LLVMValueRef data = lb_global_type_info_data_ptr(m).value; data = LLVMConstPointerCast(data, lb_type(m, alloc_type_pointer(type->Array.elem)));