Skip to content

[BREAKING CHANGE] Subtyping based runtime.Type_Info #4913

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 11 commits into
base: master
Choose a base branch
from
120 changes: 74 additions & 46 deletions base/runtime/core.odin
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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

Expand All @@ -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"`,
Expand All @@ -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,
Expand All @@ -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
Expand All @@ -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"`,
Expand All @@ -200,7 +228,7 @@ Type_Info_Flag :: enum u8 {
Comparable = 0,
Simple_Compare = 1,
}
Type_Info_Flags :: distinct bit_set[Type_Info_Flag; u32]
Type_Info_Flags :: distinct bit_set[Type_Info_Flag; u64]

Type_Info :: struct {
size: int,
Expand All @@ -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,
},
}

Expand Down Expand Up @@ -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
}
}
Expand All @@ -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
}
}
Expand Down
31 changes: 15 additions & 16 deletions base/runtime/core_builtin_soa.odin
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand All @@ -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)

Expand Down Expand Up @@ -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)
Expand All @@ -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
Expand All @@ -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)
Expand Down Expand Up @@ -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)^
Expand All @@ -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)
Expand Down Expand Up @@ -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)^
Expand All @@ -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)
Expand Down Expand Up @@ -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))
Expand All @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions base/runtime/error_checks.odin
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
Loading
Loading