mirror of
https://github.com/odin-lang/Odin.git
synced 2026-01-19 11:07:01 +00:00
runtime.Typeid_Bit_Field layout to store more information into the typeid
This commit is contained in:
@@ -96,6 +96,11 @@ write_encoded_rune :: proc(buf: ^String_Buffer, r: rune) {
|
||||
write_byte(buf, '\'');
|
||||
}
|
||||
|
||||
write_u64 :: proc(buf: ^String_Buffer, i: u64, base: int) {
|
||||
b: [129]byte;
|
||||
s := strconv.append_bits(b[:], u64(i), base, false, 64, strconv.digits, nil);
|
||||
write_string(buf, s);
|
||||
}
|
||||
write_i64 :: proc(buf: ^String_Buffer, i: i64, base: int) {
|
||||
b: [129]byte;
|
||||
s := strconv.append_bits(b[:], u64(i), base, true, 64, strconv.digits, nil);
|
||||
@@ -833,6 +838,51 @@ fmt_bit_set :: proc(fi: ^Fmt_Info, v: any, name: string = "") {
|
||||
}
|
||||
}
|
||||
}
|
||||
fmt_bit_field :: proc(fi: ^Fmt_Info, v: any, name: string = "") {
|
||||
type_info := type_info_of(v.typeid);
|
||||
switch info in type_info.variant {
|
||||
case runtime.Type_Info_Named:
|
||||
val := v;
|
||||
val.typeid = info.base.id;
|
||||
fmt_bit_field(fi, val, info.name);
|
||||
case runtime.Type_Info_Bit_Field:
|
||||
data: u64 = 0;
|
||||
switch type_info.size {
|
||||
case 1: data = cast(u64) (^u8)(v.data)^;
|
||||
case 2: data = cast(u64)(^u16)(v.data)^;
|
||||
case 4: data = cast(u64)(^u32)(v.data)^;
|
||||
case 8: data = cast(u64)(^u64)(v.data)^;
|
||||
}
|
||||
|
||||
if name != "" {
|
||||
write_string(fi.buf, name);
|
||||
write_byte(fi.buf, '{');
|
||||
} else {
|
||||
write_string(fi.buf, "bit_field{");
|
||||
}
|
||||
for name, i in info.names {
|
||||
if i > 0 {
|
||||
write_string(fi.buf, ", ");
|
||||
}
|
||||
bits := u64(info.bits[i]);
|
||||
offset := u64(info.offsets[i]);
|
||||
write_string(fi.buf, name);
|
||||
write_string(fi.buf, " = ");
|
||||
|
||||
n := 8*u64(size_of(u64));
|
||||
sa := n - bits;
|
||||
u := data>>offset;
|
||||
u <<= sa;
|
||||
u >>= sa;
|
||||
|
||||
write_u64(fi.buf, u, 10);
|
||||
|
||||
}
|
||||
write_byte(fi.buf, '}');
|
||||
case:
|
||||
write_string(fi.buf, "HERE");
|
||||
}
|
||||
}
|
||||
|
||||
fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
||||
if v.data == nil || v.typeid == nil {
|
||||
@@ -887,6 +937,8 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
||||
|
||||
case runtime.Type_Info_Bit_Set:
|
||||
fmt_bit_set(fi, v);
|
||||
case runtime.Type_Info_Bit_Field:
|
||||
fmt_bit_field(fi, v);
|
||||
case:
|
||||
fmt_value(fi, any{v.data, typeid_of(info.base)}, verb);
|
||||
}
|
||||
@@ -1052,6 +1104,9 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
||||
id := (^typeid)(v.data)^;
|
||||
write_typeid(fi.buf, id);
|
||||
|
||||
case runtime.Type_Info_Bit_Field:
|
||||
fmt_bit_field(fi, v);
|
||||
|
||||
case runtime.Type_Info_Bit_Set:
|
||||
fmt_bit_set(fi, v);
|
||||
}
|
||||
|
||||
@@ -135,6 +135,39 @@ Type_Info :: struct {
|
||||
},
|
||||
}
|
||||
|
||||
// NOTE(bill): This must match the compiler's
|
||||
Typeid_Kind :: enum u8 {
|
||||
Invalid,
|
||||
Integer,
|
||||
Rune,
|
||||
Float,
|
||||
Complex,
|
||||
String,
|
||||
Boolean,
|
||||
Any,
|
||||
Type_Id,
|
||||
Pointer,
|
||||
Procedure,
|
||||
Array,
|
||||
Dynamic_Array,
|
||||
Slice,
|
||||
Tuple,
|
||||
Struct,
|
||||
Union,
|
||||
Enum,
|
||||
Map,
|
||||
Bit_Field,
|
||||
Bit_Set,
|
||||
}
|
||||
|
||||
Typeid_Bit_Field :: bit_field #align align_of(uintptr) {
|
||||
index: 8*size_of(align_of(uintptr)) - 8,
|
||||
kind: 5, // Typeid_Kind
|
||||
named: 1,
|
||||
special: 1, // signed, cstring, etc
|
||||
reserved: 1,
|
||||
}
|
||||
|
||||
// NOTE(bill): only the ones that are needed (not all types)
|
||||
// This will be set by the compiler
|
||||
type_table: []Type_Info;
|
||||
@@ -233,7 +266,8 @@ __typeid_of :: proc "contextless" (ti: ^Type_Info) -> typeid {
|
||||
return ti.id;
|
||||
}
|
||||
__type_info_of :: proc "contextless" (id: typeid) -> ^Type_Info {
|
||||
n := int(transmute(uintptr)id);
|
||||
data := transmute(Typeid_Bit_Field)id;
|
||||
n := int(data.index);
|
||||
if n < 0 || n >= len(type_table) {
|
||||
n = 0;
|
||||
}
|
||||
|
||||
87
src/ir.cpp
87
src/ir.cpp
@@ -3773,12 +3773,95 @@ irValue *ir_type_info(irProcedure *proc, Type *type) {
|
||||
return ir_emit_array_ep(proc, ir_global_type_info_data, ir_const_i32(id));
|
||||
}
|
||||
|
||||
// IMPORTANT NOTE(bill): This must match the same as the in core.odin
|
||||
enum Typeid_Kind : u8 {
|
||||
Typeid_Invalid,
|
||||
Typeid_Integer,
|
||||
Typeid_Rune,
|
||||
Typeid_Float,
|
||||
Typeid_Complex,
|
||||
Typeid_String,
|
||||
Typeid_Boolean,
|
||||
Typeid_Any,
|
||||
Typeid_Type_Id,
|
||||
Typeid_Pointer,
|
||||
Typeid_Procedure,
|
||||
Typeid_Array,
|
||||
Typeid_Dynamic_Array,
|
||||
Typeid_Slice,
|
||||
Typeid_Tuple,
|
||||
Typeid_Struct,
|
||||
Typeid_Union,
|
||||
Typeid_Enum,
|
||||
Typeid_Map,
|
||||
Typeid_Bit_Field,
|
||||
Typeid_Bit_Set,
|
||||
};
|
||||
|
||||
|
||||
irValue *ir_typeid(irModule *m, Type *type) {
|
||||
type = default_type(type);
|
||||
|
||||
isize id = ir_type_info_index(m->info, type);
|
||||
u64 id = cast(u64)ir_type_info_index(m->info, type);
|
||||
GB_ASSERT(id >= 0);
|
||||
return ir_value_constant(t_typeid, exact_value_i64(id));
|
||||
|
||||
u64 kind = Typeid_Invalid;
|
||||
u64 named = is_type_named(type) && type->kind != Type_Basic;
|
||||
u64 special = 0;
|
||||
u64 reserved = 0;
|
||||
|
||||
Type *bt = base_type(type);
|
||||
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;
|
||||
} break;
|
||||
case Type_Pointer: kind = Typeid_Pointer; break;
|
||||
case Type_Array: kind = Typeid_Array; break;
|
||||
case Type_Slice: kind = Typeid_Slice; break;
|
||||
case Type_DynamicArray: kind = Typeid_Dynamic_Array; break;
|
||||
case Type_Map: kind = Typeid_Map; break;
|
||||
case Type_Struct: kind = Typeid_Struct; break;
|
||||
case Type_Enum: kind = Typeid_Enum; break;
|
||||
case Type_Union: kind = Typeid_Union; break;
|
||||
case Type_Tuple: kind = Typeid_Tuple; break;
|
||||
case Type_Proc: kind = Typeid_Procedure; break;
|
||||
case Type_BitField: kind = Typeid_Bit_Field; break;
|
||||
case Type_BitSet: kind = Typeid_Bit_Set; break;
|
||||
}
|
||||
|
||||
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.word_size == 4) {
|
||||
data |= (id &~ (1u<<24)) << 0u; // index
|
||||
data |= (kind &~ (1u<<5)) << 24u; // kind
|
||||
data |= (named &~ (1u<<1)) << 29u; // kind
|
||||
data |= (special &~ (1u<<1)) << 30u; // kind
|
||||
data |= (reserved &~ (1u<<1)) << 31u; // kind
|
||||
} else {
|
||||
GB_ASSERT(build_context.word_size == 8);
|
||||
data |= (id &~ (1ull<<56)) << 0ul; // index
|
||||
data |= (kind &~ (1ull<<5)) << 56ull; // kind
|
||||
data |= (named &~ (1ull<<1)) << 61ull; // kind
|
||||
data |= (special &~ (1ull<<1)) << 62ull; // kind
|
||||
data |= (reserved &~ (1ull<<1)) << 63ull; // kind
|
||||
}
|
||||
|
||||
|
||||
return ir_value_constant(t_typeid, exact_value_u64(data));
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user