Add explicit_underlying: bool RTTI field for bit_set; add runtime.type_info_underlying

This commit is contained in:
gingerBill
2026-03-03 12:26:42 +00:00
parent 6381f6c6cc
commit a5e1eb56ab
5 changed files with 52 additions and 27 deletions

View File

@@ -166,10 +166,11 @@ Type_Info_Map :: struct {
map_info: ^Map_Info,
}
Type_Info_Bit_Set :: struct {
elem: ^Type_Info,
underlying: ^Type_Info, // Possibly nil
lower: i64,
upper: i64,
elem: ^Type_Info,
underlying: ^Type_Info,
explicit_underlying: bool, // false = bit_set[T], true = bit_set[T, U]
lower: i64,
upper: i64,
}
Type_Info_Simd_Vector :: struct {
elem: ^Type_Info,
@@ -676,6 +677,26 @@ type_info_core :: proc "contextless" (info: ^Type_Info) -> ^Type_Info {
return base
}
@(require_results)
type_info_underlying :: proc "contextless" (info: ^Type_Info) -> ^Type_Info {
if info == nil {
return nil
}
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_Set: base = i.underlying
case Type_Info_Bit_Field: base = i.backing_type
case:
break loop
}
}
return base
}
// type_info_base_without_enum returns the core-type of a `^Type_Info` stripping the `distinct`ness from the first level AND/OR
// returns the backing integer type of an enum or bit_set `^Type_Info`.
// This is also aliased as `type_info_core`
@@ -713,6 +734,11 @@ when !ODIN_NO_RTTI {
// returns the backing integer type of an enum or bit_set `typeid`.
// This is also aliased as `typeid_core`
typeid_base_without_enum :: typeid_core
typeid_underlying :: proc "contextless" (id: typeid) -> typeid {
ti := type_info_underlying(type_info_of(id))
return ti.id
}
}

View File

@@ -478,7 +478,7 @@ print_type :: #force_no_inline proc "contextless" (ti: ^Type_Info) {
print_string("..")
print_i64(info.upper)
}
if info.underlying != nil {
if info.explicit_underlying {
print_string("; ")
print_type(info.underlying)
}
@@ -893,7 +893,7 @@ write_write_type :: #force_no_inline proc "contextless" (i: ^int, buf: []byte, t
write_string(i, buf, "..") or_return
write_i64 (i, buf, info.upper) or_return
}
if info.underlying != nil {
if info.explicit_underlying {
write_string (i, buf, "; ") or_return
write_write_type(i, buf, info.underlying) or_return
}

View File

@@ -405,9 +405,7 @@ walk :: proc(v: ^Visitor, node: ^Node) {
walk_expr_list(v, n.fields)
case ^Bit_Set_Type:
walk(v, n.elem)
if n.underlying != nil {
walk(v, n.underlying)
}
walk(v, n.underlying)
case ^Map_Type:
walk(v, n.key)
walk(v, n.value)

View File

@@ -442,10 +442,7 @@ is_endian_platform :: proc(info: ^Type_Info) -> bool {
case Type_Info_Integer:
return v.endianness == .Platform
case Type_Info_Bit_Set:
if v.underlying != nil {
return is_endian_platform(v.underlying)
}
return true
return is_endian_platform(v.underlying)
case Type_Info_Pointer:
return true
}
@@ -467,10 +464,7 @@ is_endian_little :: proc(info: ^Type_Info) -> bool {
}
return v.endianness == .Little
case Type_Info_Bit_Set:
if v.underlying != nil {
return is_endian_platform(v.underlying)
}
return ODIN_ENDIAN == .Little
return is_endian_little(v.underlying)
case Type_Info_Pointer:
return ODIN_ENDIAN == .Little
}
@@ -492,10 +486,7 @@ is_endian_big :: proc(info: ^Type_Info) -> bool {
}
return v.endianness == .Big
case Type_Info_Bit_Set:
if v.underlying != nil {
return is_endian_platform(v.underlying)
}
return ODIN_ENDIAN == .Big
return is_endian_big(v.underlying)
case Type_Info_Pointer:
return ODIN_ENDIAN == .Big
}
@@ -754,7 +745,7 @@ write_type_writer :: #force_no_inline proc(w: io.Writer, ti: ^Type_Info, n_writt
io.write_string(w, "..=", &n) or_return
io.write_i64(w, info.upper, 10, &n) or_return
}
if info.underlying != nil {
if info.explicit_underlying {
io.write_string(w, "; ", &n) or_return
write_type(w, info.underlying, &n) or_return
}

View File

@@ -923,15 +923,25 @@ gb_internal void lb_setup_type_info_data_giant_array(lbModule *m, i64 global_typ
GB_ASSERT(is_type_typed(t->BitSet.elem));
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,
LLVMValueRef vals[5] = {
get_type_info_ptr(m, t->BitSet.elem), // ^Type_Info
nullptr, // ^Type_Info
nullptr, // bool
lb_const_int(m, t_i64, t->BitSet.lower).value, // i64
lb_const_int(m, t_i64, t->BitSet.upper).value, // i64
};
Type *underlying = nullptr;
bool explicit_underlying = false;
if (t->BitSet.underlying != nullptr) {
underlying = t->BitSet.underlying;
explicit_underlying = true;
vals[1] = get_type_info_ptr(m, t->BitSet.underlying);
vals[2] = lb_const_bool(m, t_bool, true).value;
} else {
underlying = bit_set_to_int(t);
}
vals[1] = get_type_info_ptr(m, underlying);
vals[2] = lb_const_bool(m, t_bool, explicit_underlying).value;
variant_value = llvm_const_named_struct(m, tag_type, vals, gb_count_of(vals));
}