Browse Source

Make `any` use `typeid` rather than `^Type_Info`

gingerBill 7 years ago
parent
commit
2ef22e86e0
8 changed files with 133 additions and 99 deletions
  1. 29 6
      core/_preload.odin
  2. 35 30
      core/fmt.odin
  3. 3 1
      core/mem.odin
  4. 4 4
      core/raw.odin
  5. 2 2
      src/check_expr.cpp
  6. 41 33
      src/ir.cpp
  7. 8 11
      src/ir_print.cpp
  8. 11 12
      src/types.cpp

+ 29 - 6
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();
 }

+ 35 - 30
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, "<nil>");
 		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, "<nil>");
 		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, ' ');
 		}

+ 3 - 1
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};
 }
 
 

+ 4 - 4
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 {

+ 2 - 2
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] = {};

+ 41 - 33
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);
+	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));
+}
 
-	// gb_printf_err("%d %s\n", entry_index, type_to_string(type));
+irValue *ir_typeid(irProcedure *proc, Type *type) {
+	CheckerInfo *info = proc->module->info;
+	type = default_type(type);
 
-	return ir_emit_array_ep(proc, ir_global_type_info_data, ir_const_i32(proc->module->allocator, entry_index));
+	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<irValue *>(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);
 

+ 8 - 11
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');
 

+ 11 - 12
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