Use subtyping for Type_Info to minimize memory usage

This commit is contained in:
gingerBill
2025-03-06 09:44:41 +00:00
parent 951bef4ade
commit 19188a6e5c
12 changed files with 753 additions and 776 deletions

View File

@@ -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
}
}

View File

@@ -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..<field_count {
type := si.types[i].variant.(Type_Info_Multi_Pointer).elem
type := si.types[i].variant.(^Type_Info_Multi_Pointer).elem
total_size += type.size * length
total_size = align_forward_int(total_size, max_align)
}
@@ -121,7 +121,7 @@ make_soa_aligned :: proc($T: typeid/#soa[]$E, #any_int length, alignment: int, a
data := uintptr(&array)
offset := 0
for i in 0..<field_count {
type := si.types[i].variant.(Type_Info_Multi_Pointer).elem
type := si.types[i].variant.(^Type_Info_Multi_Pointer).elem
offset = align_forward_int(offset, max_align)
@@ -226,9 +226,8 @@ _reserve_soa :: proc(array: ^$T/#soa[dynamic]$E, capacity: int, zero_memory: boo
return nil
}
ti := type_info_of(typeid_of(T))
ti = type_info_base(ti)
si := &ti.variant.(Type_Info_Struct)
ti := type_info_base(type_info_of(T))
si := ti.variant.(^Type_Info_Struct)
field_count := uintptr(len(E) when intrinsics.type_is_array(E) else intrinsics.type_struct_field_count(E))
assert(footer.cap == old_cap)
@@ -238,7 +237,7 @@ _reserve_soa :: proc(array: ^$T/#soa[dynamic]$E, capacity: int, zero_memory: boo
max_align :: align_of(E)
for i in 0..<field_count {
type := si.types[i].variant.(Type_Info_Multi_Pointer).elem
type := si.types[i].variant.(^Type_Info_Multi_Pointer).elem
old_size += type.size * old_cap
new_size += type.size * capacity
@@ -261,7 +260,7 @@ _reserve_soa :: proc(array: ^$T/#soa[dynamic]$E, capacity: int, zero_memory: boo
old_offset := 0
new_offset := 0
for i in 0..<field_count {
type := si.types[i].variant.(Type_Info_Multi_Pointer).elem
type := si.types[i].variant.(^Type_Info_Multi_Pointer).elem
old_offset = align_forward_int(old_offset, max_align)
new_offset = align_forward_int(new_offset, max_align)
@@ -312,7 +311,7 @@ _append_soa_elem :: proc(array: ^$T/#soa[dynamic]$E, zero_memory: bool, #no_broa
if size_of(E) > 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..<field_count {
type := si.types[i].variant.(Type_Info_Multi_Pointer).elem
type := si.types[i].variant.(^Type_Info_Multi_Pointer).elem
soa_offset = align_forward_int(soa_offset, max_align)
item_offset = align_forward_int(item_offset, type.align)
@@ -374,7 +373,7 @@ _append_soa_elems :: proc(array: ^$T/#soa[dynamic]$E, zero_memory: bool, #no_bro
if size_of(E) > 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..<field_count {
type := si.types[i].variant.(Type_Info_Multi_Pointer).elem
type := si.types[i].variant.(^Type_Info_Multi_Pointer).elem
soa_offset = align_forward_int(soa_offset, max_align)
item_offset = align_forward_int(item_offset, type.align)
@@ -491,13 +490,13 @@ unordered_remove_soa :: proc(array: ^$T/#soa[dynamic]$E, #any_int index: int, lo
if index+1 < len(array) {
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 := uintptr(array)
for i in 0..<field_count {
type := si.types[i].variant.(Type_Info_Multi_Pointer).elem
type := si.types[i].variant.(^Type_Info_Multi_Pointer).elem
offset := rawptr((^uintptr)(data)^ + uintptr(index*type.size))
final := rawptr((^uintptr)(data)^ + uintptr((len(array)-1)*type.size))
@@ -519,13 +518,13 @@ ordered_remove_soa :: proc(array: ^$T/#soa[dynamic]$E, #any_int index: int, loc
if index+1 < len(array) {
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 := uintptr(array)
for i in 0..<field_count {
type := si.types[i].variant.(Type_Info_Multi_Pointer).elem
type := si.types[i].variant.(^Type_Info_Multi_Pointer).elem
offset := (^uintptr)(data)^ + uintptr(index*type.size)
length := type.size*(len(array) - index - 1)

View File

@@ -191,9 +191,9 @@ when ODIN_NO_RTTI {
}
ti := type_info_base(type_info_of(id))
#partial switch v in ti.variant {
case Type_Info_Any:
case ^Type_Info_Any:
return (^any)(data).id
case Type_Info_Union:
case ^Type_Info_Union:
tag_ptr := uintptr(data) + v.tag_offset
idx := 0
switch v.tag_type.size {

View File

@@ -64,7 +64,7 @@ when !ODIN_NO_RTTI {
case:
ti := type_info_of(x.id)
#partial switch v in ti.variant {
case Type_Info_Pointer, Type_Info_Multi_Pointer:
case ^Type_Info_Pointer, ^Type_Info_Multi_Pointer:
print_uintptr((^uintptr)(x.data)^)
return
}
@@ -270,9 +270,9 @@ print_type :: #force_no_inline proc "contextless" (ti: ^Type_Info) {
}
switch info in ti.variant {
case Type_Info_Named:
case ^Type_Info_Named:
print_string(info.name)
case Type_Info_Integer:
case ^Type_Info_Integer:
switch ti.id {
case int: print_string("int")
case uint: print_string("uint")
@@ -281,50 +281,50 @@ print_type :: #force_no_inline proc "contextless" (ti: ^Type_Info) {
print_byte('i' if info.signed else 'u')
print_u64(u64(8*ti.size))
}
case Type_Info_Rune:
case ^Type_Info_Rune:
print_string("rune")
case Type_Info_Float:
case ^Type_Info_Float:
print_byte('f')
print_u64(u64(8*ti.size))
case Type_Info_Complex:
case ^Type_Info_Complex:
print_string("complex")
print_u64(u64(8*ti.size))
case Type_Info_Quaternion:
case ^Type_Info_Quaternion:
print_string("quaternion")
print_u64(u64(8*ti.size))
case Type_Info_String:
case ^Type_Info_String:
print_string("string")
case Type_Info_Boolean:
case ^Type_Info_Boolean:
switch ti.id {
case bool: print_string("bool")
case:
print_byte('b')
print_u64(u64(8*ti.size))
}
case Type_Info_Any:
case ^Type_Info_Any:
print_string("any")
case Type_Info_Type_Id:
case ^Type_Info_Type_Id:
print_string("typeid")
case Type_Info_Pointer:
case ^Type_Info_Pointer:
if info.elem == nil {
print_string("rawptr")
} else {
print_string("^")
print_type(info.elem)
}
case Type_Info_Multi_Pointer:
case ^Type_Info_Multi_Pointer:
print_string("[^]")
print_type(info.elem)
case Type_Info_Soa_Pointer:
case ^Type_Info_Soa_Pointer:
print_string("#soa ^")
print_type(info.elem)
case Type_Info_Procedure:
case ^Type_Info_Procedure:
print_string("proc")
if info.params == nil {
print_string("()")
} else {
t := info.params.variant.(Type_Info_Parameters)
t := info.params.variant.(^Type_Info_Parameters)
print_byte('(')
for t, i in t.types {
if i > 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(", ")

View File

@@ -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<<i) == 0 {
@@ -1806,7 +1806,7 @@ fmt_bit_set :: proc(fi: ^Info, v: any, name: string = "", verb: rune = 'v') {
if is_enum {
enum_name: string
if ti_named, is_named := info.elem.variant.(runtime.Type_Info_Named); is_named {
if ti_named, is_named := info.elem.variant.(^runtime.Type_Info_Named); is_named {
enum_name = ti_named.name
}
for ev, evi in e.values {
@@ -1897,8 +1897,8 @@ fmt_write_array :: proc(fi: ^Info, array_data: rawptr, count: int, elem_size: in
// Returns: A boolean value indicating whether to continue processing the tag
//
@(private)
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) {
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..<size {
j := i+offset
@@ -2608,7 +2608,7 @@ fmt_bit_field :: proc(fi: ^Info, v: any, verb: rune, info: runtime.Type_Info_Bit
return
}
handle_bit_field_tag :: proc(data: rawptr, info: reflect.Type_Info_Bit_Field, idx: int, verb: ^rune) -> (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, "<nil>", &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, "<nil>", &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, "<nil>", &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..<info.count {
@@ -2947,7 +2947,7 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) {
}
case runtime.Type_Info_Map:
case ^runtime.Type_Info_Map:
switch verb {
case:
fmt_bad_verb(fi, verb)
@@ -3006,16 +3006,16 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) {
}
}
case runtime.Type_Info_Struct:
case ^runtime.Type_Info_Struct:
fmt_struct(fi, v, verb, info, "")
case runtime.Type_Info_Union:
case ^runtime.Type_Info_Union:
fmt_union(fi, v, verb, info, type_info.size)
case runtime.Type_Info_Enum:
case ^runtime.Type_Info_Enum:
fmt_enum(fi, v, verb)
case runtime.Type_Info_Procedure:
case ^runtime.Type_Info_Procedure:
ptr := (^rawptr)(v.data)^
if ptr == nil {
io.write_string(fi.writer, "nil", &fi.n)
@@ -3025,17 +3025,17 @@ fmt_value :: proc(fi: ^Info, v: any, verb: rune) {
fmt_pointer(fi, ptr, 'p')
}
case runtime.Type_Info_Type_Id:
case ^runtime.Type_Info_Type_Id:
id := (^typeid)(v.data)^
reflect.write_typeid(fi.writer, id, &fi.n)
case runtime.Type_Info_Bit_Set:
case ^runtime.Type_Info_Bit_Set:
fmt_bit_set(fi, v, verb = verb)
case runtime.Type_Info_Matrix:
case ^runtime.Type_Info_Matrix:
fmt_matrix(fi, v, verb, info)
case runtime.Type_Info_Bit_Field:
case ^runtime.Type_Info_Bit_Field:
fmt_bit_field(fi, v, verb, info, "")
}
}
@@ -3152,7 +3152,7 @@ fmt_arg :: proc(fi: ^Info, arg: any, verb: rune) {
}
arg_info := type_info_of(arg.id)
if info, ok := arg_info.variant.(runtime.Type_Info_Named); ok {
if info, ok := arg_info.variant.(^runtime.Type_Info_Named); ok {
fmt_named(fi, arg, verb, info)
return
}

View File

@@ -164,7 +164,7 @@ _error_string :: proc "contextless" (e: Platform_Error) -> 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]
}

View File

@@ -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
}

View File

@@ -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..<v.count {
x := rawptr(uintptr(a.data) + uintptr(v.elem_size*i))
y := rawptr(uintptr(b.data) + uintptr(v.elem_size*i))
@@ -1676,7 +1676,7 @@ equal :: proc(a, b: any, including_indirect_array_recursion := false, recursion_
}
}
return true
case Type_Info_Enumerated_Array:
case ^Type_Info_Enumerated_Array:
for i in 0..<v.count {
x := rawptr(uintptr(a.data) + uintptr(v.elem_size*i))
y := rawptr(uintptr(b.data) + uintptr(v.elem_size*i))
@@ -1685,7 +1685,7 @@ equal :: proc(a, b: any, including_indirect_array_recursion := false, recursion_
}
}
return true
case Type_Info_Struct:
case ^Type_Info_Struct:
if v.equal != nil {
return v.equal(a.data, b.data)
} else {
@@ -1699,12 +1699,12 @@ equal :: proc(a, b: any, including_indirect_array_recursion := false, recursion_
}
return true
}
case Type_Info_Union:
case ^Type_Info_Union:
if v.equal != nil {
return v.equal(a.data, b.data)
}
return false
case Type_Info_Slice:
case ^Type_Info_Slice:
if !including_indirect_array_recursion {
return false
}
@@ -1724,7 +1724,7 @@ equal :: proc(a, b: any, including_indirect_array_recursion := false, recursion_
}
}
return true
case Type_Info_Dynamic_Array:
case ^Type_Info_Dynamic_Array:
if !including_indirect_array_recursion {
return false
}
@@ -1749,7 +1749,7 @@ equal :: proc(a, b: any, including_indirect_array_recursion := false, recursion_
}
return true
case Type_Info_Bit_Field:
case ^Type_Info_Bit_Field:
x, y := a, b
x.id = v.backing_type.id
y.id = v.backing_type.id

View File

@@ -19,61 +19,61 @@ are_types_identical :: proc(a, b: ^Type_Info) -> 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
}

View File

@@ -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");

View File

@@ -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);

View File

@@ -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)));