mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 15:48:51 +00:00
Merge pull request #4860 from odin-lang/bill/typeid_hash_table
Change `typeid` definition to be based around the canonical type hash
This commit is contained in:
+11
-47
@@ -239,47 +239,6 @@ Type_Info :: struct {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE(bill): This must match the compiler's
|
|
||||||
Typeid_Kind :: enum u8 {
|
|
||||||
Invalid,
|
|
||||||
Integer,
|
|
||||||
Rune,
|
|
||||||
Float,
|
|
||||||
Complex,
|
|
||||||
Quaternion,
|
|
||||||
String,
|
|
||||||
Boolean,
|
|
||||||
Any,
|
|
||||||
Type_Id,
|
|
||||||
Pointer,
|
|
||||||
Multi_Pointer,
|
|
||||||
Procedure,
|
|
||||||
Array,
|
|
||||||
Enumerated_Array,
|
|
||||||
Dynamic_Array,
|
|
||||||
Slice,
|
|
||||||
Tuple,
|
|
||||||
Struct,
|
|
||||||
Union,
|
|
||||||
Enum,
|
|
||||||
Map,
|
|
||||||
Bit_Set,
|
|
||||||
Simd_Vector,
|
|
||||||
Matrix,
|
|
||||||
Soa_Pointer,
|
|
||||||
Bit_Field,
|
|
||||||
}
|
|
||||||
#assert(len(Typeid_Kind) < 32)
|
|
||||||
|
|
||||||
Typeid_Bit_Field :: bit_field uintptr {
|
|
||||||
index: uintptr | 8*size_of(uintptr) - 8,
|
|
||||||
kind: Typeid_Kind | 5, // Typeid_Kind
|
|
||||||
named: bool | 1,
|
|
||||||
special: bool | 1, // signed, cstring, etc
|
|
||||||
reserved: bool | 1,
|
|
||||||
}
|
|
||||||
#assert(size_of(Typeid_Bit_Field) == size_of(uintptr))
|
|
||||||
|
|
||||||
// NOTE(bill): only the ones that are needed (not all types)
|
// NOTE(bill): only the ones that are needed (not all types)
|
||||||
// This will be set by the compiler
|
// This will be set by the compiler
|
||||||
type_table: []^Type_Info
|
type_table: []^Type_Info
|
||||||
@@ -483,10 +442,12 @@ Raw_Any :: struct {
|
|||||||
data: rawptr,
|
data: rawptr,
|
||||||
id: typeid,
|
id: typeid,
|
||||||
}
|
}
|
||||||
|
#assert(size_of(Raw_Any) == size_of(any))
|
||||||
|
|
||||||
Raw_Cstring :: struct {
|
Raw_Cstring :: struct {
|
||||||
data: [^]byte,
|
data: [^]byte,
|
||||||
}
|
}
|
||||||
|
#assert(size_of(Raw_Cstring) == size_of(cstring))
|
||||||
|
|
||||||
Raw_Soa_Pointer :: struct {
|
Raw_Soa_Pointer :: struct {
|
||||||
data: rawptr,
|
data: rawptr,
|
||||||
@@ -686,13 +647,16 @@ type_info_core :: proc "contextless" (info: ^Type_Info) -> ^Type_Info {
|
|||||||
type_info_base_without_enum :: type_info_core
|
type_info_base_without_enum :: type_info_core
|
||||||
|
|
||||||
__type_info_of :: proc "contextless" (id: typeid) -> ^Type_Info #no_bounds_check {
|
__type_info_of :: proc "contextless" (id: typeid) -> ^Type_Info #no_bounds_check {
|
||||||
MASK :: 1<<(8*size_of(typeid) - 8) - 1
|
n := u64(len(type_table))
|
||||||
data := transmute(uintptr)id
|
i := transmute(u64)id % n
|
||||||
n := int(data & MASK)
|
for _ in 0..<n {
|
||||||
if n < 0 || n >= len(type_table) {
|
ptr := type_table[i]
|
||||||
n = 0
|
if ptr != nil && ptr.id == id {
|
||||||
|
return ptr
|
||||||
|
}
|
||||||
|
i = i+1 if i+1 < n else 0
|
||||||
}
|
}
|
||||||
return type_table[n]
|
return type_table[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
when !ODIN_NO_RTTI {
|
when !ODIN_NO_RTTI {
|
||||||
|
|||||||
+30
-17
@@ -6740,30 +6740,43 @@ gb_internal void check_parsed_files(Checker *c) {
|
|||||||
}
|
}
|
||||||
array_sort(c->info.type_info_types, type_info_pair_cmp);
|
array_sort(c->info.type_info_types, type_info_pair_cmp);
|
||||||
|
|
||||||
|
array_init(&c->info.type_info_types_hash_map, heap_allocator(), c->info.type_info_types.count*2 + 1);
|
||||||
map_reserve(&c->info.minimum_dependency_type_info_index_map, c->info.type_info_types.count);
|
map_reserve(&c->info.minimum_dependency_type_info_index_map, c->info.type_info_types.count);
|
||||||
|
|
||||||
for_array(i, c->info.type_info_types) {
|
isize hash_map_len = c->info.type_info_types_hash_map.count;
|
||||||
auto const &tt = c->info.type_info_types[i];
|
for (auto const &tt : c->info.type_info_types) {
|
||||||
bool exists = map_set_if_not_previously_exists(&c->info.minimum_dependency_type_info_index_map, tt.hash, i);
|
isize index = tt.hash % hash_map_len;
|
||||||
if (!exists) {
|
// NOTE(bill): no need for a sanity check since there
|
||||||
continue;
|
// will always be enough space for the entries
|
||||||
|
for (;;) {
|
||||||
|
if (index == 0 || c->info.type_info_types_hash_map[index].hash != 0) {
|
||||||
|
index = (index+1) % hash_map_len;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
for (auto const &entry : c->info.minimum_dependency_type_info_index_map) {
|
c->info.type_info_types_hash_map[index] = tt;
|
||||||
if (entry.key != tt.hash) {
|
|
||||||
continue;
|
bool exists = map_set_if_not_previously_exists(&c->info.minimum_dependency_type_info_index_map, tt.hash, index);
|
||||||
|
if (exists) {
|
||||||
|
for (auto const &entry : c->info.minimum_dependency_type_info_index_map) {
|
||||||
|
if (entry.key != tt.hash) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
auto const &other = c->info.type_info_types[entry.value];
|
||||||
|
if (are_types_identical_unique_tuples(tt.type, other.type)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
gbString t = temp_canonical_string(tt.type);
|
||||||
|
gbString o = temp_canonical_string(other.type);
|
||||||
|
GB_PANIC("%s (%s) %llu vs %s (%s) %llu",
|
||||||
|
type_to_string(tt.type, false), t, cast(unsigned long long)tt.hash,
|
||||||
|
type_to_string(other.type, false), o, cast(unsigned long long)other.hash);
|
||||||
}
|
}
|
||||||
auto const &other = c->info.type_info_types[entry.value];
|
|
||||||
if (are_types_identical_unique_tuples(tt.type, other.type)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
gbString t = temp_canonical_string(tt.type);
|
|
||||||
gbString o = temp_canonical_string(other.type);
|
|
||||||
GB_PANIC("%s (%s) %llu vs %s (%s) %llu",
|
|
||||||
type_to_string(tt.type, false), t, cast(unsigned long long)tt.hash,
|
|
||||||
type_to_string(other.type, false), o, cast(unsigned long long)other.hash);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
GB_ASSERT(c->info.minimum_dependency_type_info_index_map.count <= c->info.type_info_types.count);
|
GB_ASSERT(c->info.minimum_dependency_type_info_index_map.count <= c->info.type_info_types.count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -432,6 +432,7 @@ struct CheckerInfo {
|
|||||||
PtrMap</*type info hash*/u64, /*min dep index*/isize> minimum_dependency_type_info_index_map;
|
PtrMap</*type info hash*/u64, /*min dep index*/isize> minimum_dependency_type_info_index_map;
|
||||||
TypeSet min_dep_type_info_set;
|
TypeSet min_dep_type_info_set;
|
||||||
Array<TypeInfoPair> type_info_types; // sorted after filled
|
Array<TypeInfoPair> type_info_types; // sorted after filled
|
||||||
|
Array<TypeInfoPair> type_info_types_hash_map; // 2 * type_info_types.count
|
||||||
|
|
||||||
|
|
||||||
Array<Entity *> testing_procedures;
|
Array<Entity *> testing_procedures;
|
||||||
|
|||||||
@@ -3154,9 +3154,10 @@ gb_internal bool lb_generate_code(lbGenerator *gen) {
|
|||||||
lbModule *m = default_module;
|
lbModule *m = default_module;
|
||||||
|
|
||||||
{ // Add type info data
|
{ // Add type info data
|
||||||
GB_ASSERT_MSG(info->minimum_dependency_type_info_index_map.count == info->type_info_types.count, "%tu vs %tu", info->minimum_dependency_type_info_index_map.count, info->type_info_types.count);
|
// GB_ASSERT_MSG(info->minimum_dependency_type_info_index_map.count == info->type_info_types.count, "%tu vs %tu", info->minimum_dependency_type_info_index_map.count, info->type_info_types.count);
|
||||||
|
|
||||||
isize max_type_info_count = info->minimum_dependency_type_info_index_map.count+1;
|
// isize max_type_info_count = info->minimum_dependency_type_info_index_map.count+1;
|
||||||
|
isize max_type_info_count = info->type_info_types_hash_map.count;
|
||||||
Type *t = alloc_type_array(t_type_info_ptr, max_type_info_count);
|
Type *t = alloc_type_array(t_type_info_ptr, max_type_info_count);
|
||||||
|
|
||||||
// IMPORTANT NOTE(bill): As LLVM does not have a union type, an array of unions cannot be initialized
|
// IMPORTANT NOTE(bill): As LLVM does not have a union type, an array of unions cannot be initialized
|
||||||
|
|||||||
@@ -1784,15 +1784,24 @@ gb_internal LLVMTypeRef lb_type_internal(lbModule *m, Type *type) {
|
|||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
type = LLVMStructCreateNamed(ctx, name);
|
type = LLVMStructCreateNamed(ctx, name);
|
||||||
LLVMTypeRef fields[2] = {
|
if (build_context.ptr_size == 4) {
|
||||||
lb_type(m, t_rawptr),
|
LLVMTypeRef fields[3] = {
|
||||||
lb_type(m, t_typeid),
|
lb_type(m, t_rawptr),
|
||||||
};
|
lb_type_padding_filler(m, build_context.ptr_size, build_context.ptr_size), // padding
|
||||||
LLVMStructSetBody(type, fields, 2, false);
|
lb_type(m, t_typeid),
|
||||||
|
};
|
||||||
|
LLVMStructSetBody(type, fields, 3, false);
|
||||||
|
} else {
|
||||||
|
LLVMTypeRef fields[2] = {
|
||||||
|
lb_type(m, t_rawptr),
|
||||||
|
lb_type(m, t_typeid),
|
||||||
|
};
|
||||||
|
LLVMStructSetBody(type, fields, 2, false);
|
||||||
|
}
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
case Basic_typeid: return LLVMIntTypeInContext(m->ctx, 8*cast(unsigned)build_context.ptr_size);
|
case Basic_typeid: return LLVMIntTypeInContext(m->ctx, 64);
|
||||||
|
|
||||||
// Endian Specific Types
|
// Endian Specific Types
|
||||||
case Basic_i16le: return LLVMInt16TypeInContext(ctx);
|
case Basic_i16le: return LLVMInt16TypeInContext(ctx);
|
||||||
|
|||||||
+14
-38
@@ -2,13 +2,13 @@
|
|||||||
gb_internal isize lb_type_info_index(CheckerInfo *info, TypeInfoPair pair, bool err_on_not_found=true) {
|
gb_internal isize lb_type_info_index(CheckerInfo *info, TypeInfoPair pair, bool err_on_not_found=true) {
|
||||||
isize index = type_info_index(info, pair, err_on_not_found);
|
isize index = type_info_index(info, pair, err_on_not_found);
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
return index+1;
|
return index;
|
||||||
}
|
}
|
||||||
if (err_on_not_found) {
|
if (err_on_not_found) {
|
||||||
gb_printf_err("NOT FOUND lb_type_info_index:\n\t%s\n\t@ index %td\n\tmax count: %u\nFound:\n", type_to_string(pair.type), index, info->minimum_dependency_type_info_index_map.count);
|
gb_printf_err("NOT FOUND lb_type_info_index:\n\t%s\n\t@ index %td\n\tmax count: %u\nFound:\n", type_to_string(pair.type), index, info->minimum_dependency_type_info_index_map.count);
|
||||||
for (auto const &entry : info->minimum_dependency_type_info_index_map) {
|
for (auto const &entry : info->minimum_dependency_type_info_index_map) {
|
||||||
isize type_info_index = entry.key;
|
isize type_info_index = entry.key;
|
||||||
gb_printf_err("\t%s\n", type_to_string(info->type_info_types[type_info_index].type));
|
gb_printf_err("\t%s\n", type_to_string(info->type_info_types_hash_map[type_info_index].type));
|
||||||
}
|
}
|
||||||
GB_PANIC("NOT FOUND");
|
GB_PANIC("NOT FOUND");
|
||||||
}
|
}
|
||||||
@@ -73,37 +73,8 @@ gb_internal lbValue lb_typeid(lbModule *m, Type *type) {
|
|||||||
|
|
||||||
type = default_type(type);
|
type = default_type(type);
|
||||||
|
|
||||||
u64 id = cast(u64)lb_type_info_index(m->info, type);
|
u64 data = type_hash_canonical_type(type);
|
||||||
GB_ASSERT(id >= 0);
|
GB_ASSERT(data != 0);
|
||||||
|
|
||||||
u64 kind = lb_typeid_kind(m, type, id);
|
|
||||||
u64 named = is_type_named(type) && type->kind != Type_Basic;
|
|
||||||
u64 special = 0;
|
|
||||||
u64 reserved = 0;
|
|
||||||
|
|
||||||
if (is_type_cstring(type)) {
|
|
||||||
special = 1;
|
|
||||||
} else if (is_type_integer(type) && !is_type_unsigned(type)) {
|
|
||||||
special = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
u64 data = 0;
|
|
||||||
if (build_context.ptr_size == 4) {
|
|
||||||
GB_ASSERT(id <= (1u<<24u));
|
|
||||||
data |= (id &~ (1u<<24)) << 0u; // index
|
|
||||||
data |= (kind &~ (1u<<5)) << 24u; // kind
|
|
||||||
data |= (named &~ (1u<<1)) << 29u; // named
|
|
||||||
data |= (special &~ (1u<<1)) << 30u; // special
|
|
||||||
data |= (reserved &~ (1u<<1)) << 31u; // reserved
|
|
||||||
} else {
|
|
||||||
GB_ASSERT(build_context.ptr_size == 8);
|
|
||||||
GB_ASSERT(id <= (1ull<<56u));
|
|
||||||
data |= (id &~ (1ull<<56)) << 0ul; // index
|
|
||||||
data |= (kind &~ (1ull<<5)) << 56ull; // kind
|
|
||||||
data |= (named &~ (1ull<<1)) << 61ull; // named
|
|
||||||
data |= (special &~ (1ull<<1)) << 62ull; // special
|
|
||||||
data |= (reserved &~ (1ull<<1)) << 63ull; // reserved
|
|
||||||
}
|
|
||||||
|
|
||||||
lbValue res = {};
|
lbValue res = {};
|
||||||
res.value = LLVMConstInt(lb_type(m, t_typeid), data, false);
|
res.value = LLVMConstInt(lb_type(m, t_typeid), data, false);
|
||||||
@@ -279,8 +250,8 @@ gb_internal void lb_setup_type_info_data_giant_array(lbModule *m, i64 global_typ
|
|||||||
|
|
||||||
LLVMTypeRef *modified_types = lb_setup_modified_types_for_type_info(m, global_type_info_data_entity_count);
|
LLVMTypeRef *modified_types = lb_setup_modified_types_for_type_info(m, global_type_info_data_entity_count);
|
||||||
defer (gb_free(heap_allocator(), modified_types));
|
defer (gb_free(heap_allocator(), modified_types));
|
||||||
for_array(type_info_type_index, info->type_info_types) {
|
for_array(type_info_type_index, info->type_info_types_hash_map) {
|
||||||
auto const &tt = info->type_info_types[type_info_type_index];
|
auto const &tt = info->type_info_types_hash_map[type_info_type_index];
|
||||||
Type *t = tt.type;
|
Type *t = tt.type;
|
||||||
if (t == nullptr || t == t_invalid) {
|
if (t == nullptr || t == t_invalid) {
|
||||||
continue;
|
continue;
|
||||||
@@ -343,8 +314,8 @@ gb_internal void lb_setup_type_info_data_giant_array(lbModule *m, i64 global_typ
|
|||||||
return giant_const_values[index];
|
return giant_const_values[index];
|
||||||
};
|
};
|
||||||
|
|
||||||
for_array(type_info_type_index, info->type_info_types) {
|
for_array(type_info_type_index, info->type_info_types_hash_map) {
|
||||||
Type *t = info->type_info_types[type_info_type_index].type;
|
Type *t = info->type_info_types_hash_map[type_info_type_index].type;
|
||||||
if (t == nullptr || t == t_invalid) {
|
if (t == nullptr || t == t_invalid) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -1072,7 +1043,12 @@ gb_internal void lb_setup_type_info_data_giant_array(lbModule *m, i64 global_typ
|
|||||||
LLVMSetInitializer(giant_const_values[entry_index], LLVMConstNamedStruct(stype, small_const_values, variant_index+1));
|
LLVMSetInitializer(giant_const_values[entry_index], LLVMConstNamedStruct(stype, small_const_values, variant_index+1));
|
||||||
}
|
}
|
||||||
for (isize i = 0; i < global_type_info_data_entity_count; i++) {
|
for (isize i = 0; i < global_type_info_data_entity_count; i++) {
|
||||||
giant_const_values[i] = LLVMConstPointerCast(giant_const_values[i], lb_type(m, t_type_info_ptr));
|
auto *ptr = &giant_const_values[i];
|
||||||
|
if (*ptr != nullptr) {
|
||||||
|
*ptr = LLVMConstPointerCast(*ptr, lb_type(m, t_type_info_ptr));
|
||||||
|
} else {
|
||||||
|
*ptr = LLVMConstNull(lb_type(m, t_type_info_ptr));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -971,6 +971,13 @@ gb_internal i32 lb_convert_struct_index(lbModule *m, Type *t, i32 index) {
|
|||||||
if (t->kind == Type_Struct) {
|
if (t->kind == Type_Struct) {
|
||||||
auto field_remapping = lb_get_struct_remapping(m, t);
|
auto field_remapping = lb_get_struct_remapping(m, t);
|
||||||
return field_remapping[index];
|
return field_remapping[index];
|
||||||
|
} else if (is_type_any(t) && build_context.ptr_size == 4) {
|
||||||
|
GB_ASSERT(t->kind == Type_Basic);
|
||||||
|
GB_ASSERT(t->Basic.kind == Basic_any);
|
||||||
|
switch (index) {
|
||||||
|
case 0: return 0; // data
|
||||||
|
case 1: return 2; // id
|
||||||
|
}
|
||||||
} else if (build_context.ptr_size != build_context.int_size) {
|
} else if (build_context.ptr_size != build_context.int_size) {
|
||||||
switch (t->kind) {
|
switch (t->kind) {
|
||||||
case Type_Basic:
|
case Type_Basic:
|
||||||
|
|||||||
+11
-11
@@ -503,9 +503,9 @@ gb_global Type basic_types[] = {
|
|||||||
{Type_Basic, {Basic_rawptr, BasicFlag_Pointer, -1, STR_LIT("rawptr")}},
|
{Type_Basic, {Basic_rawptr, BasicFlag_Pointer, -1, STR_LIT("rawptr")}},
|
||||||
{Type_Basic, {Basic_string, BasicFlag_String, -1, STR_LIT("string")}},
|
{Type_Basic, {Basic_string, BasicFlag_String, -1, STR_LIT("string")}},
|
||||||
{Type_Basic, {Basic_cstring, BasicFlag_String, -1, STR_LIT("cstring")}},
|
{Type_Basic, {Basic_cstring, BasicFlag_String, -1, STR_LIT("cstring")}},
|
||||||
{Type_Basic, {Basic_any, 0, -1, STR_LIT("any")}},
|
{Type_Basic, {Basic_any, 0, 16, STR_LIT("any")}},
|
||||||
|
|
||||||
{Type_Basic, {Basic_typeid, 0, -1, STR_LIT("typeid")}},
|
{Type_Basic, {Basic_typeid, 0, 8, STR_LIT("typeid")}},
|
||||||
|
|
||||||
// Endian
|
// Endian
|
||||||
{Type_Basic, {Basic_i16le, BasicFlag_Integer | BasicFlag_EndianLittle, 2, STR_LIT("i16le")}},
|
{Type_Basic, {Basic_i16le, BasicFlag_Integer | BasicFlag_EndianLittle, 2, STR_LIT("i16le")}},
|
||||||
@@ -3700,8 +3700,8 @@ gb_internal i64 type_size_of(Type *t) {
|
|||||||
switch (t->Basic.kind) {
|
switch (t->Basic.kind) {
|
||||||
case Basic_string: size = 2*build_context.int_size; break;
|
case Basic_string: size = 2*build_context.int_size; break;
|
||||||
case Basic_cstring: size = build_context.ptr_size; break;
|
case Basic_cstring: size = build_context.ptr_size; break;
|
||||||
case Basic_any: size = 2*build_context.ptr_size; break;
|
case Basic_any: size = 16; break;
|
||||||
case Basic_typeid: size = build_context.ptr_size; break;
|
case Basic_typeid: size = 8; break;
|
||||||
|
|
||||||
case Basic_int: case Basic_uint:
|
case Basic_int: case Basic_uint:
|
||||||
size = build_context.int_size;
|
size = build_context.int_size;
|
||||||
@@ -3763,8 +3763,8 @@ gb_internal i64 type_align_of_internal(Type *t, TypePath *path) {
|
|||||||
switch (t->Basic.kind) {
|
switch (t->Basic.kind) {
|
||||||
case Basic_string: return build_context.int_size;
|
case Basic_string: return build_context.int_size;
|
||||||
case Basic_cstring: return build_context.ptr_size;
|
case Basic_cstring: return build_context.ptr_size;
|
||||||
case Basic_any: return build_context.ptr_size;
|
case Basic_any: return 8;
|
||||||
case Basic_typeid: return build_context.ptr_size;
|
case Basic_typeid: return 8;
|
||||||
|
|
||||||
case Basic_int: case Basic_uint:
|
case Basic_int: case Basic_uint:
|
||||||
return build_context.int_size;
|
return build_context.int_size;
|
||||||
@@ -4014,8 +4014,8 @@ gb_internal i64 type_size_of_internal(Type *t, TypePath *path) {
|
|||||||
switch (kind) {
|
switch (kind) {
|
||||||
case Basic_string: return 2*build_context.int_size;
|
case Basic_string: return 2*build_context.int_size;
|
||||||
case Basic_cstring: return build_context.ptr_size;
|
case Basic_cstring: return build_context.ptr_size;
|
||||||
case Basic_any: return 2*build_context.ptr_size;
|
case Basic_any: return 16;
|
||||||
case Basic_typeid: return build_context.ptr_size;
|
case Basic_typeid: return 8;
|
||||||
|
|
||||||
case Basic_int: case Basic_uint:
|
case Basic_int: case Basic_uint:
|
||||||
return build_context.int_size;
|
return build_context.int_size;
|
||||||
@@ -4251,7 +4251,7 @@ gb_internal i64 type_offset_of(Type *t, i64 index, Type **field_type_) {
|
|||||||
return 0; // data
|
return 0; // data
|
||||||
case 1:
|
case 1:
|
||||||
if (field_type_) *field_type_ = t_typeid;
|
if (field_type_) *field_type_ = t_typeid;
|
||||||
return build_context.ptr_size; // id
|
return 8; // id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -4322,8 +4322,8 @@ gb_internal i64 type_offset_of_from_selection(Type *type, Selection sel) {
|
|||||||
}
|
}
|
||||||
} else if (t->Basic.kind == Basic_any) {
|
} else if (t->Basic.kind == Basic_any) {
|
||||||
switch (index) {
|
switch (index) {
|
||||||
case 0: t = t_type_info_ptr; break;
|
case 0: t = t_rawptr; break;
|
||||||
case 1: t = t_rawptr; break;
|
case 1: t = t_typeid; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
Reference in New Issue
Block a user