Make any use typeid rather than ^Type_Info

This commit is contained in:
gingerBill
2018-05-12 18:40:49 +01:00
parent 830f4f540f
commit 2ef22e86e0
8 changed files with 135 additions and 101 deletions
+29 -6
View File
@@ -239,10 +239,28 @@ type_info_base_without_enum :: proc(info: ^Type_Info) -> ^Type_Info {
return base; return base;
} }
typeid_from_type_info :: proc(ti: ^Type_Info) -> typeid {
id: uintptr = 0;
if ti != nil {
id = (uintptr(ti) - uintptr(&__type_table[0]))/size_of(Type_Info);
}
return transmute(typeid)id;
}
type_info_from_typeid :: proc(t: typeid) -> ^Type_Info { type_info_from_typeid :: proc(t: typeid) -> ^Type_Info {
index := transmute(uintptr)t; index := transmute(uintptr)t;
return &__type_table[index]; return &__type_table[index];
} }
typeid_base :: proc(id: typeid) -> typeid {
ti := type_info_from_typeid(id);
ti = type_info_base(ti);
return typeid_from_type_info(ti);
}
typeid_base_without_enum :: proc(id: typeid) -> typeid {
ti := type_info_from_typeid(id);
ti = type_info_base_without_enum(ti);
return typeid_from_type_info(ti);
}
@@ -649,7 +667,10 @@ __print_caller_location :: proc(fd: os.Handle, using loc: Source_Code_Location)
__print_u64(fd, u64(column)); __print_u64(fd, u64(column));
os.write_byte(fd, ')'); os.write_byte(fd, ')');
} }
__print_typeid :: proc(fd: os.Handle, id: typeid) {
ti := type_info_from_typeid(id);
__print_type(fd, ti);
}
__print_type :: proc(fd: os.Handle, ti: ^Type_Info) { __print_type :: proc(fd: os.Handle, ti: ^Type_Info) {
if ti == nil { if ti == nil {
os.write_string(fd, "nil"); os.write_string(fd, "nil");
@@ -660,7 +681,7 @@ __print_type :: proc(fd: os.Handle, ti: ^Type_Info) {
case Type_Info_Named: case Type_Info_Named:
os.write_string(fd, info.name); os.write_string(fd, info.name);
case Type_Info_Integer: case Type_Info_Integer:
a := any{type_info = ti}; a := any{typeid = typeid_from_type_info(ti)};
switch _ in a { switch _ in a {
case int: os.write_string(fd, "int"); case int: os.write_string(fd, "int");
case uint: os.write_string(fd, "uint"); case uint: os.write_string(fd, "uint");
@@ -680,7 +701,7 @@ __print_type :: proc(fd: os.Handle, ti: ^Type_Info) {
case Type_Info_String: case Type_Info_String:
os.write_string(fd, "string"); os.write_string(fd, "string");
case Type_Info_Boolean: case Type_Info_Boolean:
a := any{type_info = ti}; a := any{typeid = typeid_from_type_info(ti)};
switch _ in a { switch _ in a {
case bool: os.write_string(fd, "bool"); case bool: os.write_string(fd, "bool");
case: case:
@@ -689,6 +710,8 @@ __print_type :: proc(fd: os.Handle, ti: ^Type_Info) {
} }
case Type_Info_Any: case Type_Info_Any:
os.write_string(fd, "any"); os.write_string(fd, "any");
case Type_Info_Type_Id:
os.write_string(fd, "typeid");
case Type_Info_Pointer: case Type_Info_Pointer:
if info.elem == nil { if info.elem == nil {
@@ -941,15 +964,15 @@ __dynamic_array_expr_error :: proc "contextless" (file: string, line, column: in
__debug_trap(); __debug_trap();
} }
__type_assertion_check :: proc "contextless" (ok: bool, file: string, line, column: int, from, to: ^Type_Info) { __type_assertion_check :: proc "contextless" (ok: bool, file: string, line, column: int, from, to: typeid) {
if ok do return; if ok do return;
fd := os.stderr; fd := os.stderr;
__print_caller_location(fd, Source_Code_Location{file, line, column, ""}); __print_caller_location(fd, Source_Code_Location{file, line, column, ""});
os.write_string(fd, " Invalid type assertion from"); os.write_string(fd, " Invalid type assertion from");
__print_type(fd, from); __print_typeid(fd, from);
os.write_string(fd, " to "); os.write_string(fd, " to ");
__print_type(fd, to); __print_typeid(fd, to);
os.write_byte(fd, '\n'); os.write_byte(fd, '\n');
__debug_trap(); __debug_trap();
} }
+35 -30
View File
@@ -164,7 +164,7 @@ write_type :: proc(buf: ^String_Buffer, ti: ^Type_Info) {
case Type_Info_Named: case Type_Info_Named:
write_string(buf, info.name); write_string(buf, info.name);
case Type_Info_Integer: case Type_Info_Integer:
a := any{type_info = ti}; a := any{typeid = typeid_from_type_info(ti)};
switch _ in a { switch _ in a {
case int: write_string(buf, "int"); case int: write_string(buf, "int");
case uint: write_string(buf, "uint"); case uint: write_string(buf, "uint");
@@ -188,7 +188,7 @@ write_type :: proc(buf: ^String_Buffer, ti: ^Type_Info) {
write_string(buf, "string"); write_string(buf, "string");
} }
case Type_Info_Boolean: case Type_Info_Boolean:
a := any{type_info = ti}; a := any{typeid = typeid_from_type_info(ti)};
switch _ in a { switch _ in a {
case bool: write_string(buf, "bool"); case bool: write_string(buf, "bool");
case: case:
@@ -369,7 +369,7 @@ int_from_arg :: proc(args: []any, arg_index: int) -> (int, int, bool) {
ok := true; ok := true;
if arg_index < len(args) { if arg_index < len(args) {
arg := args[arg_index]; arg := args[arg_index];
arg.type_info = type_info_base(arg.type_info); arg.typeid = typeid_base(arg.typeid);
switch i in arg { switch i in arg {
case int: num = i; case int: num = i;
case i8: num = int(i); case i8: num = int(i);
@@ -394,8 +394,8 @@ fmt_bad_verb :: proc(using fi: ^Fmt_Info, verb: rune) {
write_string(buf, "%!"); write_string(buf, "%!");
write_rune(buf, verb); write_rune(buf, verb);
write_byte(buf, '('); write_byte(buf, '(');
if arg.type_info != nil { if arg.typeid != nil {
write_type(buf, arg.type_info); write_typeid(buf, arg.typeid);
write_byte(buf, '='); write_byte(buf, '=');
fmt_value(fi, arg, 'v'); fmt_value(fi, arg, 'v');
} else { } else {
@@ -628,9 +628,10 @@ fmt_pointer :: proc(fi: ^Fmt_Info, p: rawptr, verb: rune) {
} }
enum_value_to_string :: proc(v: any) -> (string, bool) { enum_value_to_string :: proc(v: any) -> (string, bool) {
v.type_info = type_info_base(v.type_info); v.typeid = typeid_base(v.typeid);
type_info := type_info_from_typeid(v.typeid);
switch e in v.type_info.variant { switch e in type_info.variant {
case: return "", false; case: return "", false;
case Type_Info_Enum: case Type_Info_Enum:
get_str :: proc(i: $T, e: Type_Info_Enum) -> (string, bool) { get_str :: proc(i: $T, e: Type_Info_Enum) -> (string, bool) {
@@ -652,7 +653,7 @@ enum_value_to_string :: proc(v: any) -> (string, bool) {
return "", false; return "", false;
} }
a := any{v.data, type_info_base(e.base)}; a := any{v.data, typeid_from_type_info(type_info_base(e.base))};
switch v in a { switch v in a {
case rune: return get_str(v, e); case rune: return get_str(v, e);
case i8: return get_str(v, e); case i8: return get_str(v, e);
@@ -690,18 +691,19 @@ string_to_enum_value :: proc(T: type, s: string) -> (T, bool) {
} }
fmt_enum :: proc(fi: ^Fmt_Info, v: any, verb: rune) { fmt_enum :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
if v.type_info == nil || v.data == nil { if v.typeid == nil || v.data == nil {
write_string(fi.buf, "<nil>"); write_string(fi.buf, "<nil>");
return; return;
} }
switch e in v.type_info.variant { type_info := type_info_from_typeid(v.typeid);
switch e in type_info.variant {
case: fmt_bad_verb(fi, verb); case: fmt_bad_verb(fi, verb);
case Type_Info_Enum: case Type_Info_Enum:
switch verb { switch verb {
case: fmt_bad_verb(fi, verb); case: fmt_bad_verb(fi, verb);
case 'd', 'f': case 'd', 'f':
fmt_arg(fi, any{v.data, type_info_base(e.base)}, verb); fmt_arg(fi, any{v.data, typeid_from_type_info(type_info_base(e.base))}, verb);
case 's', 'v': case 's', 'v':
str, ok := enum_value_to_string(v); str, ok := enum_value_to_string(v);
if !ok do str = "!%(BAD ENUM VALUE)"; if !ok do str = "!%(BAD ENUM VALUE)";
@@ -712,12 +714,13 @@ fmt_enum :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) { fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
if v.data == nil || v.type_info == nil { if v.data == nil || v.typeid == nil {
write_string(fi.buf, "<nil>"); write_string(fi.buf, "<nil>");
return; return;
} }
switch info in v.type_info.variant { type_info := type_info_from_typeid(v.typeid);
switch info in type_info.variant {
case Type_Info_Named: case Type_Info_Named:
switch b in info.base.variant { switch b in info.base.variant {
case Type_Info_Struct: case Type_Info_Struct:
@@ -751,8 +754,9 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
if t := b.types[i]; types.is_any(t) { if t := b.types[i]; types.is_any(t) {
write_string(fi.buf, "any{}"); write_string(fi.buf, "any{}");
} else { } else {
data := uintptr(v.data) + b.offsets[i]; data := rawptr(uintptr(v.data) + b.offsets[i]);
fmt_arg(fi, any{rawptr(data), t}, 'v'); id := typeid_from_type_info(t);
fmt_arg(fi, any{data, id}, 'v');
} }
if hash do write_string(fi.buf, ",\n"); if hash do write_string(fi.buf, ",\n");
@@ -762,7 +766,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
write_byte(fi.buf, '}'); write_byte(fi.buf, '}');
case: case:
fmt_value(fi, any{v.data, info.base}, verb); fmt_value(fi, any{v.data, typeid_from_type_info(info.base)}, verb);
} }
case Type_Info_Boolean: fmt_arg(fi, v, verb); case Type_Info_Boolean: fmt_arg(fi, v, verb);
@@ -773,7 +777,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
case Type_Info_String: fmt_arg(fi, v, verb); case Type_Info_String: fmt_arg(fi, v, verb);
case Type_Info_Pointer: case Type_Info_Pointer:
if v.type_info == type_info_of(^Type_Info) { if v.typeid == typeid_of(^Type_Info) {
write_type(fi.buf, (^^Type_Info)(v.data)^); write_type(fi.buf, (^^Type_Info)(v.data)^);
} else { } else {
fmt_pointer(fi, (^rawptr)(v.data)^, verb); fmt_pointer(fi, (^rawptr)(v.data)^, verb);
@@ -786,7 +790,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
if i > 0 do write_string(fi.buf, ", "); if i > 0 do write_string(fi.buf, ", ");
data := uintptr(v.data) + uintptr(i*info.elem_size); data := uintptr(v.data) + uintptr(i*info.elem_size);
fmt_arg(fi, any{rawptr(data), info.elem}, verb); fmt_arg(fi, any{rawptr(data), typeid_from_type_info(info.elem)}, verb);
} }
case Type_Info_Dynamic_Array: case Type_Info_Dynamic_Array:
@@ -797,7 +801,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
if i > 0 do write_string(fi.buf, ", "); if i > 0 do write_string(fi.buf, ", ");
data := uintptr(array.data) + uintptr(i*info.elem_size); data := uintptr(array.data) + uintptr(i*info.elem_size);
fmt_arg(fi, any{rawptr(data), info.elem}, verb); fmt_arg(fi, any{rawptr(data), typeid_from_type_info(info.elem)}, verb);
} }
case Type_Info_Slice: case Type_Info_Slice:
@@ -808,7 +812,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
if i > 0 do write_string(fi.buf, ", "); if i > 0 do write_string(fi.buf, ", ");
data := uintptr(slice.data) + uintptr(i*info.elem_size); data := uintptr(slice.data) + uintptr(i*info.elem_size);
fmt_arg(fi, any{rawptr(data), info.elem}, verb); fmt_arg(fi, any{rawptr(data), typeid_from_type_info(info.elem)}, verb);
} }
case Type_Info_Map: case Type_Info_Map:
@@ -839,13 +843,13 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
write_string(fi.buf, header.key.str); write_string(fi.buf, header.key.str);
} else { } else {
fi := Fmt_Info{buf = fi.buf}; fi := Fmt_Info{buf = fi.buf};
fmt_arg(&fi, any{rawptr(&header.key.hash), info.key}, 'v'); fmt_arg(&fi, any{rawptr(&header.key.hash), typeid_from_type_info(info.key)}, 'v');
} }
write_string(fi.buf, "="); write_string(fi.buf, "=");
value := data + entry_type.offsets[2]; value := data + entry_type.offsets[2];
fmt_arg(fi, any{rawptr(value), info.value}, 'v'); fmt_arg(fi, any{rawptr(value), typeid_from_type_info(info.value)}, 'v');
} }
} }
@@ -880,14 +884,15 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
write_string(fi.buf, "any{}"); write_string(fi.buf, "any{}");
} else { } else {
data := uintptr(v.data) + info.offsets[i]; data := uintptr(v.data) + info.offsets[i];
fmt_arg(fi, any{rawptr(data), t}, 'v'); id := typeid_from_type_info(t);
fmt_arg(fi, any{rawptr(data), id}, 'v');
} }
if hash do write_string(fi.buf, ",\n"); if hash do write_string(fi.buf, ",\n");
} }
case Type_Info_Union: case Type_Info_Union:
tag_ptr := uintptr(v.data) + info.tag_offset; tag_ptr := uintptr(v.data) + info.tag_offset;
tag_any := any{rawptr(tag_ptr), info.tag_type}; tag_any := any{rawptr(tag_ptr), typeid_from_type_info(info.tag_type)};
tag: i64 = -1; tag: i64 = -1;
switch i in tag_any { switch i in tag_any {
@@ -905,8 +910,8 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
if v.data == nil || tag == 0 { if v.data == nil || tag == 0 {
write_string(fi.buf, "nil"); write_string(fi.buf, "nil");
} else { } else {
ti := info.variants[tag-1]; id := typeid_from_type_info(info.variants[tag-1]);
fmt_arg(fi, any{v.data, ti}, verb); fmt_arg(fi, any{v.data, id}, verb);
} }
case Type_Info_Enum: case Type_Info_Enum:
@@ -917,7 +922,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
if ptr == nil { if ptr == nil {
write_string(fi.buf, "nil"); write_string(fi.buf, "nil");
} else { } else {
write_type(fi.buf, v.type_info); write_typeid(fi.buf, v.typeid);
write_string(fi.buf, " @ "); write_string(fi.buf, " @ ");
fmt_pointer(fi, ptr, 'p'); fmt_pointer(fi, ptr, 'p');
} }
@@ -953,7 +958,7 @@ fmt_arg :: proc(fi: ^Fmt_Info, arg: any, verb: rune) {
fi.arg = arg; fi.arg = arg;
if verb == 'T' { if verb == 'T' {
ti := arg.type_info; ti := type_info_from_typeid(arg.typeid);
switch a in arg { switch a in arg {
case ^Type_Info: ti = a; case ^Type_Info: ti = a;
} }
@@ -962,7 +967,7 @@ fmt_arg :: proc(fi: ^Fmt_Info, arg: any, verb: rune) {
} }
base_arg := arg; base_arg := arg;
base_arg.type_info = type_info_base(base_arg.type_info); base_arg.typeid = typeid_base(base_arg.typeid);
switch a in base_arg { switch a in base_arg {
case bool: fmt_bool(fi, bool(a), verb); case bool: fmt_bool(fi, bool(a), verb);
case b8: fmt_bool(fi, bool(a), verb); case b8: fmt_bool(fi, bool(a), verb);
@@ -1010,7 +1015,7 @@ sbprint :: proc(buf: ^String_Buffer, args: ...any) -> string {
fi.buf = buf; fi.buf = buf;
for arg, i in args { for arg, i in args {
is_string := arg != nil && types.is_string(arg.type_info); is_string := arg != nil && types.is_string(type_info_from_typeid(arg.typeid));
if i > 0 && !is_string && !prev_string { if i > 0 && !is_string && !prev_string {
write_byte(buf, ' '); write_byte(buf, ' ');
} }
+3 -1
View File
@@ -43,7 +43,9 @@ ptr_to_bytes :: proc "contextless" (ptr: ^$T, len := 1) -> []byte {
} }
any_to_bytes :: proc "contextless" (val: any) -> []byte { any_to_bytes :: proc "contextless" (val: any) -> []byte {
return transmute([]byte)raw.Slice{val.data, val.type_info.size}; ti := type_info_from_typeid(val.typeid);
size := ti != nil ? ti.size : 0;
return transmute([]byte)raw.Slice{val.data, size};
} }
+4 -4
View File
@@ -1,6 +1,6 @@
Any :: struct { Any :: struct {
data: rawptr, data: rawptr,
type_info: ^Type_Info, typeid: typeid,
} }
String :: struct { String :: struct {
@@ -30,8 +30,8 @@ Map :: struct {
} }
make_any :: inline proc(data: rawptr, type_info: ^Type_Info) -> any { make_any :: inline proc(data: rawptr, id: typeid) -> any {
return transmute(any)Any{data, type_info}; return transmute(any)Any{data, id};
} }
string_data :: inline proc(s: $T/string) -> ^byte { string_data :: inline proc(s: $T/string) -> ^byte {
+2 -2
View File
@@ -3428,7 +3428,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
} }
case BuiltinProc_typeid_of: { case BuiltinProc_typeid_of: {
// proc typeid_of(Type) -> ^Type_Info // proc typeid_of(Type) -> typeid
if (c->context.scope->is_global) { if (c->context.scope->is_global) {
compiler_error("'typeid_of' Cannot be declared within a #shared_global_scope due to how the internals of the compiler works"); compiler_error("'typeid_of' Cannot be declared within a #shared_global_scope due to how the internals of the compiler works");
} }
@@ -5701,7 +5701,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
break; // NOTE(bill): No need to init break; // NOTE(bill): No need to init
} }
{ // Checker values { // Checker values
Type *field_types[2] = {t_rawptr, t_type_info_ptr}; Type *field_types[2] = {t_rawptr, t_typeid};
isize field_count = 2; isize field_count = 2;
if (cl->elems[0]->kind == AstNode_FieldValue) { if (cl->elems[0]->kind == AstNode_FieldValue) {
bool fields_visited[2] = {}; bool fields_visited[2] = {};
+43 -35
View File
@@ -784,6 +784,7 @@ irValue *ir_emit_load (irProcedure *p, irValue *address);
void ir_emit_jump (irProcedure *proc, irBlock *block); void ir_emit_jump (irProcedure *proc, irBlock *block);
irValue *ir_emit_conv (irProcedure *proc, irValue *value, Type *t); irValue *ir_emit_conv (irProcedure *proc, irValue *value, Type *t);
irValue *ir_type_info (irProcedure *proc, Type *type); irValue *ir_type_info (irProcedure *proc, Type *type);
irValue *ir_typeid (irProcedure *proc, Type *type);
irValue *ir_build_expr (irProcedure *proc, AstNode *expr); irValue *ir_build_expr (irProcedure *proc, AstNode *expr);
void ir_build_stmt (irProcedure *proc, AstNode *node); void ir_build_stmt (irProcedure *proc, AstNode *node);
irValue *ir_build_cond (irProcedure *proc, AstNode *cond, irBlock *true_block, irBlock *false_block); irValue *ir_build_cond (irProcedure *proc, AstNode *cond, irBlock *true_block, irBlock *false_block);
@@ -2456,6 +2457,9 @@ irValue *ir_emit_comp_against_nil(irProcedure *proc, TokenKind op_kind, irValue
} else if (is_type_union(t)) { } else if (is_type_union(t)) {
irValue *tag = ir_emit_union_tag_value(proc, x); irValue *tag = ir_emit_union_tag_value(proc, x);
return ir_emit_comp(proc, op_kind, tag, v_zero); return ir_emit_comp(proc, op_kind, tag, v_zero);
} else if (is_type_typeid(t)) {
irValue *invalid_typeid = ir_value_constant(proc->module->allocator, t_typeid, exact_value_i64(0));
return ir_emit_comp(proc, op_kind, x, invalid_typeid);
} }
return nullptr; return nullptr;
} }
@@ -2619,8 +2623,8 @@ irValue *ir_emit_struct_ep(irProcedure *proc, irValue *s, i32 index) {
} }
} else if (is_type_any(t)) { } else if (is_type_any(t)) {
switch (index) { switch (index) {
case 0: result_type = alloc_type_pointer(t_rawptr); break; case 0: result_type = alloc_type_pointer(t_rawptr); break;
case 1: result_type = alloc_type_pointer(t_type_info_ptr); break; case 1: result_type = alloc_type_pointer(t_typeid); break;
} }
} else if (is_type_dynamic_array(t)) { } else if (is_type_dynamic_array(t)) {
switch (index) { switch (index) {
@@ -2668,8 +2672,8 @@ irValue *ir_emit_struct_ev(irProcedure *proc, irValue *s, i32 index) {
break; break;
case Basic_any: case Basic_any:
switch (index) { switch (index) {
case 0: result_type = t_rawptr; break; case 0: result_type = t_rawptr; break;
case 1: result_type = t_type_info_ptr; break; case 1: result_type = t_typeid; break;
} }
break; break;
case Basic_complex64: case Basic_complex128: case Basic_complex64: case Basic_complex128:
@@ -3350,10 +3354,10 @@ irValue *ir_emit_conv(irProcedure *proc, irValue *value, Type *t) {
data = ir_emit_conv(proc, data, t_rawptr); data = ir_emit_conv(proc, data, t_rawptr);
irValue *ti = ir_type_info(proc, st); irValue *id = ir_typeid(proc, st);
ir_emit_store(proc, ir_emit_struct_ep(proc, result, 0), data); ir_emit_store(proc, ir_emit_struct_ep(proc, result, 0), data);
ir_emit_store(proc, ir_emit_struct_ep(proc, result, 1), ti); ir_emit_store(proc, ir_emit_struct_ep(proc, result, 1), id);
return ir_emit_load(proc, result); return ir_emit_load(proc, result);
} }
@@ -3501,8 +3505,8 @@ irValue *ir_emit_union_cast(irProcedure *proc, irValue *value, Type *type, Token
args[2] = ir_const_int(a, pos.line); args[2] = ir_const_int(a, pos.line);
args[3] = ir_const_int(a, pos.column); args[3] = ir_const_int(a, pos.column);
args[4] = ir_type_info(proc, src_type); args[4] = ir_typeid(proc, src_type);
args[5] = ir_type_info(proc, dst_type); args[5] = ir_typeid(proc, dst_type);
ir_emit_global_call(proc, "__type_assertion_check", args); ir_emit_global_call(proc, "__type_assertion_check", args);
} }
@@ -3529,13 +3533,13 @@ irAddr ir_emit_any_cast_addr(irProcedure *proc, irValue *value, Type *type, Toke
irValue *v = ir_add_local_generated(proc, tuple); irValue *v = ir_add_local_generated(proc, tuple);
irValue *ti_ptr = ir_type_info(proc, dst_type); irValue *dst_typeid = ir_typeid(proc, dst_type);
irValue *any_ti = ir_emit_struct_ev(proc, value, 1); irValue *any_typeid = ir_emit_struct_ev(proc, value, 1);
irBlock *ok_block = ir_new_block(proc, nullptr, "any_cast.ok"); irBlock *ok_block = ir_new_block(proc, nullptr, "any_cast.ok");
irBlock *end_block = ir_new_block(proc, nullptr, "any_cast.end"); irBlock *end_block = ir_new_block(proc, nullptr, "any_cast.end");
irValue *cond = ir_emit_comp(proc, Token_CmpEq, any_ti, ti_ptr); irValue *cond = ir_emit_comp(proc, Token_CmpEq, any_typeid, dst_typeid);
ir_emit_if(proc, cond, ok_block, end_block); ir_emit_if(proc, cond, ok_block, end_block);
ir_start_block(proc, ok_block); ir_start_block(proc, ok_block);
@@ -3561,8 +3565,8 @@ irAddr ir_emit_any_cast_addr(irProcedure *proc, irValue *value, Type *type, Toke
args[2] = ir_const_int(a, pos.line); args[2] = ir_const_int(a, pos.line);
args[3] = ir_const_int(a, pos.column); args[3] = ir_const_int(a, pos.column);
args[4] = any_ti; args[4] = any_typeid;
args[5] = ti_ptr; args[5] = dst_typeid;
ir_emit_global_call(proc, "__type_assertion_check", args); ir_emit_global_call(proc, "__type_assertion_check", args);
return ir_addr(ir_emit_struct_ep(proc, v, 0)); return ir_addr(ir_emit_struct_ep(proc, v, 0));
@@ -3617,17 +3621,23 @@ isize ir_type_info_index(CheckerInfo *info, Type *type) {
irValue *ir_type_info(irProcedure *proc, Type *type) { irValue *ir_type_info(irProcedure *proc, Type *type) {
CheckerInfo *info = proc->module->info; CheckerInfo *info = proc->module->info;
type = default_type(type); type = default_type(type);
i32 entry_index = cast(i32)ir_type_info_index(info, type); i32 id = cast(i32)ir_type_info_index(info, type);
GB_ASSERT(entry_index >= 0); GB_ASSERT(id >= 0);
return ir_emit_array_ep(proc, ir_global_type_info_data, ir_const_i32(proc->module->allocator, id));
// gb_printf_err("%d %s\n", entry_index, type_to_string(type));
return ir_emit_array_ep(proc, ir_global_type_info_data, ir_const_i32(proc->module->allocator, entry_index));
} }
irValue *ir_typeid(irProcedure *proc, Type *type) {
CheckerInfo *info = proc->module->info;
type = default_type(type);
isize id = ir_type_info_index(info, type);
GB_ASSERT(id >= 0);
return ir_value_constant(proc->module->allocator, t_typeid, exact_value_i64(id));
}
irValue *ir_emit_logical_binary_expr(irProcedure *proc, TokenKind op, AstNode *left, AstNode *right, Type *type) { irValue *ir_emit_logical_binary_expr(irProcedure *proc, TokenKind op, AstNode *left, AstNode *right, Type *type) {
irBlock *rhs = ir_new_block(proc, nullptr, "logical.cmp.rhs"); irBlock *rhs = ir_new_block(proc, nullptr, "logical.cmp.rhs");
irBlock *done = ir_new_block(proc, nullptr, "logical.cmp.done"); irBlock *done = ir_new_block(proc, nullptr, "logical.cmp.done");
@@ -4205,9 +4215,7 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
case BuiltinProc_typeid_of: { case BuiltinProc_typeid_of: {
Type *t = default_type(type_of_expr(proc->module->info, ce->args[0])); Type *t = default_type(type_of_expr(proc->module->info, ce->args[0]));
i32 entry_index = cast(i32)ir_type_info_index(proc->module->info, t); return ir_typeid(proc, t);
GB_ASSERT(entry_index >= 0);
return ir_value_constant(proc->module->allocator, t_typeid, exact_value_i64(entry_index));
} }
case BuiltinProc_len: { case BuiltinProc_len: {
@@ -5032,8 +5040,8 @@ irValue *ir_build_expr_internal(irProcedure *proc, AstNode *expr) {
args[2] = ir_const_int(a, pos.line); args[2] = ir_const_int(a, pos.line);
args[3] = ir_const_int(a, pos.column); args[3] = ir_const_int(a, pos.column);
args[4] = ir_type_info(proc, src_type); args[4] = ir_typeid(proc, src_type);
args[5] = ir_type_info(proc, dst_type); args[5] = ir_typeid(proc, dst_type);
ir_emit_global_call(proc, "__type_assertion_check", args); ir_emit_global_call(proc, "__type_assertion_check", args);
irValue *data_ptr = v; irValue *data_ptr = v;
@@ -5045,11 +5053,11 @@ irValue *ir_build_expr_internal(irProcedure *proc, AstNode *expr) {
} }
irValue *data_ptr = ir_emit_struct_ev(proc, v, 0); irValue *data_ptr = ir_emit_struct_ev(proc, v, 0);
irValue *any_ti = ir_emit_struct_ev(proc, v, 1); irValue *any_id = ir_emit_struct_ev(proc, v, 1);
irValue *ti_ptr = ir_type_info(proc, type); irValue *id = ir_typeid(proc, type);
irValue *ok = ir_emit_comp(proc, Token_CmpEq, any_ti, ti_ptr); irValue *ok = ir_emit_comp(proc, Token_CmpEq, any_id, id);
auto args = array_make<irValue *>(proc->module->allocator, 6); auto args = array_make<irValue *>(proc->module->allocator, 6);
args[0] = ok; args[0] = ok;
@@ -5057,8 +5065,8 @@ irValue *ir_build_expr_internal(irProcedure *proc, AstNode *expr) {
args[2] = ir_const_int(a, pos.line); args[2] = ir_const_int(a, pos.line);
args[3] = ir_const_int(a, pos.column); args[3] = ir_const_int(a, pos.column);
args[4] = any_ti; args[4] = any_id;
args[5] = ti_ptr; args[5] = id;
ir_emit_global_call(proc, "__type_assertion_check", args); ir_emit_global_call(proc, "__type_assertion_check", args);
return ir_emit_conv(proc, data_ptr, tv.type); return ir_emit_conv(proc, data_ptr, tv.type);
@@ -6006,11 +6014,11 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
ir_emit_store(proc, v, ir_add_module_constant(proc->module, type, exact_value_compound(expr))); ir_emit_store(proc, v, ir_add_module_constant(proc->module, type, exact_value_compound(expr)));
String field_names[2] = { String field_names[2] = {
str_lit("data"), str_lit("data"),
str_lit("type_info"), str_lit("typeid"),
}; };
Type *field_types[2] = { Type *field_types[2] = {
t_rawptr, t_rawptr,
t_type_info_ptr, t_typeid,
}; };
for_array(field_index, cl->elems) { for_array(field_index, cl->elems) {
@@ -7237,9 +7245,9 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
irValue *variant_tag = ir_const_union_tag(proc->module->allocator, ut, case_type); irValue *variant_tag = ir_const_union_tag(proc->module->allocator, ut, case_type);
cond = ir_emit_comp(proc, Token_CmpEq, tag_index, variant_tag); cond = ir_emit_comp(proc, Token_CmpEq, tag_index, variant_tag);
} else if (switch_kind == TypeSwitch_Any) { } else if (switch_kind == TypeSwitch_Any) {
irValue *any_ti = ir_emit_load(proc, ir_emit_struct_ep(proc, parent_ptr, 1)); irValue *any_typeid = ir_emit_load(proc, ir_emit_struct_ep(proc, parent_ptr, 1));
irValue *case_ti = ir_type_info(proc, case_type); irValue *case_typeid = ir_typeid(proc, case_type);
cond = ir_emit_comp(proc, Token_CmpEq, any_ti, case_ti); cond = ir_emit_comp(proc, Token_CmpEq, any_typeid, case_typeid);
} }
GB_ASSERT(cond != nullptr); GB_ASSERT(cond != nullptr);
+8 -11
View File
@@ -319,6 +319,8 @@ void ir_print_type(irFileBuffer *f, irModule *m, Type *t, bool in_struct) {
case Basic_rune: ir_write_str_lit(f, "i32"); return; case Basic_rune: ir_write_str_lit(f, "i32"); return;
case Basic_typeid:
/* fallthrough */
case Basic_int: case Basic_int:
case Basic_uint: case Basic_uint:
case Basic_uintptr: case Basic_uintptr:
@@ -341,8 +343,6 @@ void ir_print_type(irFileBuffer *f, irModule *m, Type *t, bool in_struct) {
case Basic_rawptr: ir_write_str_lit(f, "%..rawptr"); return; case Basic_rawptr: ir_write_str_lit(f, "%..rawptr"); return;
case Basic_string: ir_write_str_lit(f, "%..string"); return; case Basic_string: ir_write_str_lit(f, "%..string"); return;
case Basic_cstring: ir_write_str_lit(f, "i8*"); return; case Basic_cstring: ir_write_str_lit(f, "i8*"); return;
case Basic_typeid: ir_write_str_lit(f, "%..typeid"); return;
} }
break; break;
@@ -538,7 +538,6 @@ void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type *
return; return;
} }
switch (value.kind) { switch (value.kind) {
case ExactValue_Bool: case ExactValue_Bool:
if (value.value_bool) { if (value.value_bool) {
@@ -653,7 +652,11 @@ void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type *
} }
case ExactValue_Pointer: case ExactValue_Pointer:
if (value.value_pointer == 0) { if (value.value_pointer == 0) {
ir_write_str_lit(f, "null"); if (is_type_typeid(type)) {
ir_write_str_lit(f, "0");
} else {
ir_write_str_lit(f, "null");
}
} else { } else {
ir_write_str_lit(f, "inttoptr ("); ir_write_str_lit(f, "inttoptr (");
ir_print_type(f, m, t_int); ir_print_type(f, m, t_int);
@@ -1748,15 +1751,9 @@ void print_llvm_ir(irGen *ir) {
ir_write_str_lit(f, " = type {"); ir_write_str_lit(f, " = type {");
ir_print_type(f, m, t_rawptr); ir_print_type(f, m, t_rawptr);
ir_write_str_lit(f, ", "); ir_write_str_lit(f, ", ");
ir_print_type(f, m, t_type_info_ptr); ir_print_type(f, m, t_typeid);
ir_write_str_lit(f, "} ; Basic_any\n"); ir_write_str_lit(f, "} ; Basic_any\n");
ir_print_encoded_local(f, str_lit("..typeid"));
ir_write_str_lit(f, " = type ");
ir_print_type(f, m, t_uintptr);
ir_write_str_lit(f, "; Basic_typeid\n");
ir_write_str_lit(f, "declare void @llvm.dbg.declare(metadata, metadata, metadata) nounwind readnone \n"); ir_write_str_lit(f, "declare void @llvm.dbg.declare(metadata, metadata, metadata) nounwind readnone \n");
ir_write_byte(f, '\n'); ir_write_byte(f, '\n');
+11 -12
View File
@@ -911,6 +911,10 @@ bool is_type_any(Type *t) {
t = base_type(t); t = base_type(t);
return (t->kind == Type_Basic && t->Basic.kind == Basic_any); return (t->kind == Type_Basic && t->Basic.kind == Basic_any);
} }
bool is_type_typeid(Type *t) {
t = base_type(t);
return (t->kind == Type_Basic && t->Basic.kind == Basic_typeid);
}
bool is_type_untyped_nil(Type *t) { bool is_type_untyped_nil(Type *t) {
t = base_type(t); t = base_type(t);
return (t->kind == Type_Basic && t->Basic.kind == Basic_UntypedNil); return (t->kind == Type_Basic && t->Basic.kind == Basic_UntypedNil);
@@ -1095,6 +1099,8 @@ bool type_has_nil(Type *t) {
return true; return true;
case Basic_cstring: case Basic_cstring:
return true; return true;
case Basic_typeid:
return true;
} }
return false; return false;
} break; } break;
@@ -1590,9 +1596,6 @@ Selection lookup_field_from_index(Type *type, i64 index) {
} }
gb_global Entity *entity__any_data = nullptr;
gb_global Entity *entity__any_type_info = nullptr;
Entity *current_scope_lookup_entity(Scope *s, String name); Entity *current_scope_lookup_entity(Scope *s, String name);
Selection lookup_field_with_selection(Type *type_, String field_name, bool is_type, Selection sel) { Selection lookup_field_with_selection(Type *type_, String field_name, bool is_type, Selection sel) {
@@ -1616,21 +1619,17 @@ Selection lookup_field_with_selection(Type *type_, String field_name, bool is_ty
// IMPORTANT TODO(bill): Should these members be available to should I only allow them with // IMPORTANT TODO(bill): Should these members be available to should I only allow them with
// `Raw_Any` type? // `Raw_Any` type?
String data_str = str_lit("data"); String data_str = str_lit("data");
String type_info_str = str_lit("type_info"); String typeid_str = str_lit("typeid");
if (entity__any_data == nullptr) { gb_local_persist Entity *entity__any_data = alloc_entity_field(nullptr, make_token_ident(data_str), t_rawptr, false, 0);
entity__any_data = alloc_entity_field(nullptr, make_token_ident(data_str), t_rawptr, false, 0); gb_local_persist Entity *entity__any_typeid = alloc_entity_field(nullptr, make_token_ident(typeid_str), t_typeid, false, 1);
}
if (entity__any_type_info == nullptr) {
entity__any_type_info = alloc_entity_field(nullptr, make_token_ident(type_info_str), t_type_info_ptr, false, 1);
}
if (field_name == data_str) { if (field_name == data_str) {
selection_add_index(&sel, 0); selection_add_index(&sel, 0);
sel.entity = entity__any_data;; sel.entity = entity__any_data;;
return sel; return sel;
} else if (field_name == type_info_str) { } else if (field_name == typeid_str) {
selection_add_index(&sel, 1); selection_add_index(&sel, 1);
sel.entity = entity__any_type_info; sel.entity = entity__any_typeid;
return sel; return sel;
} }
#endif #endif