aboutsummaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2018-08-25 12:11:48 +0100
committergingerBill <bill@gingerbill.org>2018-08-25 12:11:48 +0100
commit3365baee8f97bcabe462e4a6d0f46a76dd1ce7b3 (patch)
tree5c2e9013fc1181d274f8d254a4228c7d7e4d54ae /core
parentcc88dd0b71c831fdabb4378930da2f074ff11a17 (diff)
`runtime.Typeid_Bit_Field` layout to store more information into the typeid
Diffstat (limited to 'core')
-rw-r--r--core/fmt/fmt.odin55
-rw-r--r--core/runtime/core.odin36
2 files changed, 90 insertions, 1 deletions
diff --git a/core/fmt/fmt.odin b/core/fmt/fmt.odin
index 17b11d0c6..459d6e2ce 100644
--- a/core/fmt/fmt.odin
+++ b/core/fmt/fmt.odin
@@ -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);
}
diff --git a/core/runtime/core.odin b/core/runtime/core.odin
index db908530e..c6ccb7bf4 100644
--- a/core/runtime/core.odin
+++ b/core/runtime/core.odin
@@ -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;
}