mirror of
https://github.com/odin-lang/Odin.git
synced 2026-04-06 06:38:20 +00:00
Add explicit_underlying: bool RTTI field for bit_set; add runtime.type_info_underlying
This commit is contained in:
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user