From 2ef22e86e0742d6dcf0e8c4796f126134e808086 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sat, 12 May 2018 18:40:49 +0100 Subject: [PATCH] Make `any` use `typeid` rather than `^Type_Info` --- core/_preload.odin | 35 +++++++++++++++++---- core/fmt.odin | 65 ++++++++++++++++++++------------------ core/mem.odin | 4 ++- core/raw.odin | 8 ++--- src/check_expr.cpp | 4 +-- src/ir.cpp | 78 +++++++++++++++++++++++++--------------------- src/ir_print.cpp | 19 +++++------ src/types.cpp | 23 +++++++------- 8 files changed, 135 insertions(+), 101 deletions(-) diff --git a/core/_preload.odin b/core/_preload.odin index a1d729649..cec6a59b4 100644 --- a/core/_preload.odin +++ b/core/_preload.odin @@ -239,10 +239,28 @@ type_info_base_without_enum :: proc(info: ^Type_Info) -> ^Type_Info { 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 { index := transmute(uintptr)t; 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)); 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) { if ti == nil { os.write_string(fd, "nil"); @@ -660,7 +681,7 @@ __print_type :: proc(fd: os.Handle, ti: ^Type_Info) { case Type_Info_Named: os.write_string(fd, info.name); case Type_Info_Integer: - a := any{type_info = ti}; + a := any{typeid = typeid_from_type_info(ti)}; switch _ in a { case int: os.write_string(fd, "int"); case uint: os.write_string(fd, "uint"); @@ -680,7 +701,7 @@ __print_type :: proc(fd: os.Handle, ti: ^Type_Info) { case Type_Info_String: os.write_string(fd, "string"); case Type_Info_Boolean: - a := any{type_info = ti}; + a := any{typeid = typeid_from_type_info(ti)}; switch _ in a { case bool: os.write_string(fd, "bool"); case: @@ -689,6 +710,8 @@ __print_type :: proc(fd: os.Handle, ti: ^Type_Info) { } case Type_Info_Any: os.write_string(fd, "any"); + case Type_Info_Type_Id: + os.write_string(fd, "typeid"); case Type_Info_Pointer: if info.elem == nil { @@ -941,15 +964,15 @@ __dynamic_array_expr_error :: proc "contextless" (file: string, line, column: in __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; fd := os.stderr; __print_caller_location(fd, Source_Code_Location{file, line, column, ""}); os.write_string(fd, " Invalid type assertion from"); - __print_type(fd, from); + __print_typeid(fd, from); os.write_string(fd, " to "); - __print_type(fd, to); + __print_typeid(fd, to); os.write_byte(fd, '\n'); __debug_trap(); } diff --git a/core/fmt.odin b/core/fmt.odin index 211ec69a2..0a2a30dbe 100644 --- a/core/fmt.odin +++ b/core/fmt.odin @@ -164,7 +164,7 @@ write_type :: proc(buf: ^String_Buffer, ti: ^Type_Info) { case Type_Info_Named: write_string(buf, info.name); case Type_Info_Integer: - a := any{type_info = ti}; + a := any{typeid = typeid_from_type_info(ti)}; switch _ in a { case int: write_string(buf, "int"); case uint: write_string(buf, "uint"); @@ -188,7 +188,7 @@ write_type :: proc(buf: ^String_Buffer, ti: ^Type_Info) { write_string(buf, "string"); } case Type_Info_Boolean: - a := any{type_info = ti}; + a := any{typeid = typeid_from_type_info(ti)}; switch _ in a { case bool: write_string(buf, "bool"); case: @@ -369,7 +369,7 @@ int_from_arg :: proc(args: []any, arg_index: int) -> (int, int, bool) { ok := true; if arg_index < len(args) { arg := args[arg_index]; - arg.type_info = type_info_base(arg.type_info); + arg.typeid = typeid_base(arg.typeid); switch i in arg { case int: num = i; case i8: num = int(i); @@ -394,8 +394,8 @@ fmt_bad_verb :: proc(using fi: ^Fmt_Info, verb: rune) { write_string(buf, "%!"); write_rune(buf, verb); write_byte(buf, '('); - if arg.type_info != nil { - write_type(buf, arg.type_info); + if arg.typeid != nil { + write_typeid(buf, arg.typeid); write_byte(buf, '='); fmt_value(fi, arg, 'v'); } else { @@ -628,9 +628,10 @@ fmt_pointer :: proc(fi: ^Fmt_Info, p: rawptr, verb: rune) { } 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 Type_Info_Enum: 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; } - 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 { case rune: 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) { - if v.type_info == nil || v.data == nil { + if v.typeid == nil || v.data == nil { write_string(fi.buf, ""); 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 Type_Info_Enum: switch verb { case: fmt_bad_verb(fi, verb); 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': str, ok := enum_value_to_string(v); 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) { - if v.data == nil || v.type_info == nil { + if v.data == nil || v.typeid == nil { write_string(fi.buf, ""); 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: switch b in info.base.variant { 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) { write_string(fi.buf, "any{}"); } else { - data := uintptr(v.data) + b.offsets[i]; - fmt_arg(fi, any{rawptr(data), t}, 'v'); + data := rawptr(uintptr(v.data) + b.offsets[i]); + id := typeid_from_type_info(t); + fmt_arg(fi, any{data, id}, 'v'); } 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, '}'); 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); @@ -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_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)^); } else { 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, ", "); 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: @@ -797,7 +801,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) { if i > 0 do write_string(fi.buf, ", "); 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: @@ -808,7 +812,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) { if i > 0 do write_string(fi.buf, ", "); 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: @@ -839,13 +843,13 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) { write_string(fi.buf, header.key.str); } else { 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, "="); 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{}"); } else { 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"); } case Type_Info_Union: 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; 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 { write_string(fi.buf, "nil"); } else { - ti := info.variants[tag-1]; - fmt_arg(fi, any{v.data, ti}, verb); + id := typeid_from_type_info(info.variants[tag-1]); + fmt_arg(fi, any{v.data, id}, verb); } case Type_Info_Enum: @@ -917,7 +922,7 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) { if ptr == nil { write_string(fi.buf, "nil"); } else { - write_type(fi.buf, v.type_info); + write_typeid(fi.buf, v.typeid); write_string(fi.buf, " @ "); fmt_pointer(fi, ptr, 'p'); } @@ -953,7 +958,7 @@ fmt_arg :: proc(fi: ^Fmt_Info, arg: any, verb: rune) { fi.arg = arg; if verb == 'T' { - ti := arg.type_info; + ti := type_info_from_typeid(arg.typeid); switch a in arg { case ^Type_Info: ti = a; } @@ -962,7 +967,7 @@ fmt_arg :: proc(fi: ^Fmt_Info, arg: any, verb: rune) { } 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 { case bool: 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; 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 { write_byte(buf, ' '); } diff --git a/core/mem.odin b/core/mem.odin index b9550a77b..d9d9669cc 100644 --- a/core/mem.odin +++ b/core/mem.odin @@ -43,7 +43,9 @@ ptr_to_bytes :: proc "contextless" (ptr: ^$T, len := 1) -> []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}; } diff --git a/core/raw.odin b/core/raw.odin index 47ee64632..fc3876eed 100644 --- a/core/raw.odin +++ b/core/raw.odin @@ -1,6 +1,6 @@ Any :: struct { - data: rawptr, - type_info: ^Type_Info, + data: rawptr, + typeid: typeid, } String :: struct { @@ -30,8 +30,8 @@ Map :: struct { } -make_any :: inline proc(data: rawptr, type_info: ^Type_Info) -> any { - return transmute(any)Any{data, type_info}; +make_any :: inline proc(data: rawptr, id: typeid) -> any { + return transmute(any)Any{data, id}; } string_data :: inline proc(s: $T/string) -> ^byte { diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 66c26dda4..a2510f56b 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -3428,7 +3428,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id } case BuiltinProc_typeid_of: { - // proc typeid_of(Type) -> ^Type_Info + // proc typeid_of(Type) -> typeid 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"); } @@ -5701,7 +5701,7 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t break; // NOTE(bill): No need to init } { // Checker values - Type *field_types[2] = {t_rawptr, t_type_info_ptr}; + Type *field_types[2] = {t_rawptr, t_typeid}; isize field_count = 2; if (cl->elems[0]->kind == AstNode_FieldValue) { bool fields_visited[2] = {}; diff --git a/src/ir.cpp b/src/ir.cpp index c5061b38e..4750f7c8d 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -784,6 +784,7 @@ irValue *ir_emit_load (irProcedure *p, irValue *address); void ir_emit_jump (irProcedure *proc, irBlock *block); irValue *ir_emit_conv (irProcedure *proc, irValue *value, Type *t); irValue *ir_type_info (irProcedure *proc, Type *type); +irValue *ir_typeid (irProcedure *proc, Type *type); irValue *ir_build_expr (irProcedure *proc, AstNode *expr); void ir_build_stmt (irProcedure *proc, AstNode *node); 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)) { irValue *tag = ir_emit_union_tag_value(proc, x); 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; } @@ -2619,8 +2623,8 @@ irValue *ir_emit_struct_ep(irProcedure *proc, irValue *s, i32 index) { } } else if (is_type_any(t)) { switch (index) { - case 0: result_type = alloc_type_pointer(t_rawptr); break; - case 1: result_type = alloc_type_pointer(t_type_info_ptr); break; + case 0: result_type = alloc_type_pointer(t_rawptr); break; + case 1: result_type = alloc_type_pointer(t_typeid); break; } } else if (is_type_dynamic_array(t)) { switch (index) { @@ -2668,8 +2672,8 @@ irValue *ir_emit_struct_ev(irProcedure *proc, irValue *s, i32 index) { break; case Basic_any: switch (index) { - case 0: result_type = t_rawptr; break; - case 1: result_type = t_type_info_ptr; break; + case 0: result_type = t_rawptr; break; + case 1: result_type = t_typeid; break; } break; 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); - 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, 1), ti); + ir_emit_store(proc, ir_emit_struct_ep(proc, result, 1), id); 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[3] = ir_const_int(a, pos.column); - args[4] = ir_type_info(proc, src_type); - args[5] = ir_type_info(proc, dst_type); + args[4] = ir_typeid(proc, src_type); + args[5] = ir_typeid(proc, dst_type); 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 *ti_ptr = ir_type_info(proc, dst_type); - irValue *any_ti = ir_emit_struct_ev(proc, value, 1); + irValue *dst_typeid = ir_typeid(proc, dst_type); + irValue *any_typeid = ir_emit_struct_ev(proc, value, 1); irBlock *ok_block = ir_new_block(proc, nullptr, "any_cast.ok"); 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_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[3] = ir_const_int(a, pos.column); - args[4] = any_ti; - args[5] = ti_ptr; + args[4] = any_typeid; + args[5] = dst_typeid; ir_emit_global_call(proc, "__type_assertion_check", args); 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) { CheckerInfo *info = proc->module->info; - type = default_type(type); - i32 entry_index = cast(i32)ir_type_info_index(info, type); - GB_ASSERT(entry_index >= 0); - - // 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)); + i32 id = cast(i32)ir_type_info_index(info, type); + GB_ASSERT(id >= 0); + return ir_emit_array_ep(proc, ir_global_type_info_data, ir_const_i32(proc->module->allocator, id)); } +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) { irBlock *rhs = ir_new_block(proc, nullptr, "logical.cmp.rhs"); 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: { 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); - GB_ASSERT(entry_index >= 0); - return ir_value_constant(proc->module->allocator, t_typeid, exact_value_i64(entry_index)); + return ir_typeid(proc, t); } 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[3] = ir_const_int(a, pos.column); - args[4] = ir_type_info(proc, src_type); - args[5] = ir_type_info(proc, dst_type); + args[4] = ir_typeid(proc, src_type); + args[5] = ir_typeid(proc, dst_type); ir_emit_global_call(proc, "__type_assertion_check", args); 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 *any_ti = ir_emit_struct_ev(proc, v, 1); - irValue *ti_ptr = ir_type_info(proc, type); + irValue *any_id = ir_emit_struct_ev(proc, v, 1); + 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(proc->module->allocator, 6); 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[3] = ir_const_int(a, pos.column); - args[4] = any_ti; - args[5] = ti_ptr; + args[4] = any_id; + args[5] = id; ir_emit_global_call(proc, "__type_assertion_check", args); 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))); String field_names[2] = { str_lit("data"), - str_lit("type_info"), + str_lit("typeid"), }; Type *field_types[2] = { t_rawptr, - t_type_info_ptr, + t_typeid, }; 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); cond = ir_emit_comp(proc, Token_CmpEq, tag_index, variant_tag); } else if (switch_kind == TypeSwitch_Any) { - irValue *any_ti = ir_emit_load(proc, ir_emit_struct_ep(proc, parent_ptr, 1)); - irValue *case_ti = ir_type_info(proc, case_type); - cond = ir_emit_comp(proc, Token_CmpEq, any_ti, case_ti); + irValue *any_typeid = ir_emit_load(proc, ir_emit_struct_ep(proc, parent_ptr, 1)); + irValue *case_typeid = ir_typeid(proc, case_type); + cond = ir_emit_comp(proc, Token_CmpEq, any_typeid, case_typeid); } GB_ASSERT(cond != nullptr); diff --git a/src/ir_print.cpp b/src/ir_print.cpp index 435924f06..862281a55 100644 --- a/src/ir_print.cpp +++ b/src/ir_print.cpp @@ -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_typeid: + /* fallthrough */ case Basic_int: case Basic_uint: 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_string: ir_write_str_lit(f, "%..string"); return; case Basic_cstring: ir_write_str_lit(f, "i8*"); return; - - case Basic_typeid: ir_write_str_lit(f, "%..typeid"); return; } break; @@ -538,7 +538,6 @@ void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type * return; } - switch (value.kind) { case ExactValue_Bool: if (value.value_bool) { @@ -653,7 +652,11 @@ void ir_print_exact_value(irFileBuffer *f, irModule *m, ExactValue value, Type * } case ExactValue_Pointer: 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 { ir_write_str_lit(f, "inttoptr ("); ir_print_type(f, m, t_int); @@ -1748,15 +1751,9 @@ void print_llvm_ir(irGen *ir) { ir_write_str_lit(f, " = type {"); ir_print_type(f, m, t_rawptr); 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_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_byte(f, '\n'); diff --git a/src/types.cpp b/src/types.cpp index b5ed0a885..55e569742 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -911,6 +911,10 @@ bool is_type_any(Type *t) { t = base_type(t); 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) { t = base_type(t); return (t->kind == Type_Basic && t->Basic.kind == Basic_UntypedNil); @@ -1095,6 +1099,8 @@ bool type_has_nil(Type *t) { return true; case Basic_cstring: return true; + case Basic_typeid: + return true; } return false; } 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); 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 // `Raw_Any` type? String data_str = str_lit("data"); - String type_info_str = str_lit("type_info"); - if (entity__any_data == nullptr) { - entity__any_data = alloc_entity_field(nullptr, make_token_ident(data_str), t_rawptr, false, 0); - } - 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); - } + String typeid_str = str_lit("typeid"); + gb_local_persist Entity *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 (field_name == data_str) { selection_add_index(&sel, 0); sel.entity = entity__any_data;; return sel; - } else if (field_name == type_info_str) { + } else if (field_name == typeid_str) { selection_add_index(&sel, 1); - sel.entity = entity__any_type_info; + sel.entity = entity__any_typeid; return sel; } #endif