gingerBill 7 years ago
parent
commit
830f4f540f
8 changed files with 88 additions and 3 deletions
  1. 7 0
      core/_preload.odin
  2. 14 1
      core/fmt.odin
  3. 29 0
      src/check_expr.cpp
  4. 4 0
      src/checker.cpp
  5. 2 0
      src/checker.hpp
  6. 11 0
      src/ir.cpp
  7. 7 0
      src/ir_print.cpp
  8. 14 2
      src/types.cpp

+ 7 - 0
core/_preload.odin

@@ -49,6 +49,7 @@ Type_Info_Complex  :: struct {};
 Type_Info_String   :: struct {is_cstring: bool};
 Type_Info_Boolean  :: struct {};
 Type_Info_Any      :: struct {};
+Type_Info_Type_Id  :: struct {};
 Type_Info_Pointer  :: struct {
 	elem: ^Type_Info // nil -> rawptr
 };
@@ -114,6 +115,7 @@ Type_Info :: struct {
 		Type_Info_String,
 		Type_Info_Boolean,
 		Type_Info_Any,
+		Type_Info_Type_Id,
 		Type_Info_Pointer,
 		Type_Info_Procedure,
 		Type_Info_Array,
@@ -237,6 +239,11 @@ type_info_base_without_enum :: proc(info: ^Type_Info) -> ^Type_Info {
 	return base;
 }
 
+type_info_from_typeid :: proc(t: typeid) -> ^Type_Info {
+	index := transmute(uintptr)t;
+	return &__type_table[index];
+}
+
 
 
 @(default_calling_convention = "c")

+ 14 - 1
core/fmt.odin

@@ -150,6 +150,10 @@ fprint_type :: proc(fd: os.Handle, info: ^Type_Info) {
 	os.write(fd, buf[..]);
 }
 
+write_typeid :: proc(buf: ^String_Buffer, id: typeid) {
+	write_type(buf, type_info_from_typeid(id));
+}
+
 write_type :: proc(buf: ^String_Buffer, ti: ^Type_Info) {
 	if ti == nil {
 		write_string(buf, "nil");
@@ -194,6 +198,9 @@ write_type :: proc(buf: ^String_Buffer, ti: ^Type_Info) {
 	case Type_Info_Any:
 		write_string(buf, "any");
 
+	case Type_Info_Type_Id:
+		write_string(buf, "typeid");
+
 	case Type_Info_Pointer:
 		if info.elem == nil {
 			write_string(buf, "rawptr");
@@ -914,6 +921,10 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
 			write_string(fi.buf, " @ ");
 			fmt_pointer(fi, ptr, 'p');
 		}
+
+	case Type_Info_Type_Id:
+		id := (^typeid)(v.data)^;
+		write_typeid(fi.buf, id);
 	}
 }
 
@@ -983,7 +994,9 @@ fmt_arg :: proc(fi: ^Fmt_Info, arg: any, verb: rune) {
 	case string:  fmt_string(fi, a, verb);
 	case cstring: fmt_cstring(fi, a, verb);
 
-	case:         fmt_value(fi, arg, verb);
+	case typeid:  write_typeid(fi.buf, a);
+
+	case: fmt_value(fi, arg, verb);
 	}
 
 }

+ 29 - 0
src/check_expr.cpp

@@ -2873,6 +2873,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
 	case BuiltinProc_align_of:
 	case BuiltinProc_offset_of:
 	case BuiltinProc_type_info_of:
+	case BuiltinProc_typeid_of:
 		// NOTE(bill): The first arg may be a Type, this will be checked case by case
 		break;
 	default:
@@ -3426,6 +3427,34 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
 		break;
 	}
 
+	case BuiltinProc_typeid_of: {
+		// proc typeid_of(Type) -> ^Type_Info
+		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");
+		}
+
+		// NOTE(bill): The type information may not be setup yet
+		init_preload(c);
+		AstNode *expr = ce->args[0];
+		Operand o = {};
+		check_expr_or_type(c, &o, expr);
+		if (o.mode == Addressing_Invalid) {
+			return false;
+		}
+		Type *t = o.type;
+		if (t == nullptr || t == t_invalid || is_type_polymorphic(operand->type)) {
+			error(ce->args[0], "Invalid argument for 'typeid_of'");
+			return false;
+		}
+		t = default_type(t);
+
+		add_type_info_type(c, t);
+
+		operand->mode = Addressing_Value;
+		operand->type = t_typeid;
+		break;
+	}
+
 	case BuiltinProc_swizzle: {
 		// proc swizzle(v: [N]T, ...int) -> [M]T
 		Type *type = base_type(operand->type);

+ 4 - 0
src/checker.cpp

@@ -1023,6 +1023,8 @@ void add_type_info_type(Checker *c, Type *t) {
 			add_type_info_type(c, t_type_info_ptr);
 			add_type_info_type(c, t_rawptr);
 			break;
+		case Basic_typeid:
+			break;
 
 		case Basic_complex64:
 			add_type_info_type(c, t_type_info_float);
@@ -1564,6 +1566,7 @@ void init_preload(Checker *c) {
 		t_type_info_string        = find_core_type(c, str_lit("Type_Info_String"));
 		t_type_info_boolean       = find_core_type(c, str_lit("Type_Info_Boolean"));
 		t_type_info_any           = find_core_type(c, str_lit("Type_Info_Any"));
+		t_type_info_typeid        = find_core_type(c, str_lit("Type_Info_Type_Id"));
 		t_type_info_pointer       = find_core_type(c, str_lit("Type_Info_Pointer"));
 		t_type_info_procedure     = find_core_type(c, str_lit("Type_Info_Procedure"));
 		t_type_info_array         = find_core_type(c, str_lit("Type_Info_Array"));
@@ -1584,6 +1587,7 @@ void init_preload(Checker *c) {
 		t_type_info_string_ptr        = alloc_type_pointer(t_type_info_string);
 		t_type_info_boolean_ptr       = alloc_type_pointer(t_type_info_boolean);
 		t_type_info_any_ptr           = alloc_type_pointer(t_type_info_any);
+		t_type_info_typeid_ptr        = alloc_type_pointer(t_type_info_typeid);
 		t_type_info_pointer_ptr       = alloc_type_pointer(t_type_info_pointer);
 		t_type_info_procedure_ptr     = alloc_type_pointer(t_type_info_procedure);
 		t_type_info_array_ptr         = alloc_type_pointer(t_type_info_array);

+ 2 - 0
src/checker.hpp

@@ -86,6 +86,7 @@ enum BuiltinProcId {
 	BuiltinProc_offset_of,
 	BuiltinProc_type_of,
 	BuiltinProc_type_info_of,
+	BuiltinProc_typeid_of,
 
 	BuiltinProc_swizzle,
 
@@ -128,6 +129,7 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = {
 	{STR_LIT("offset_of"),        2, false, Expr_Expr},
 	{STR_LIT("type_of"),          1, false, Expr_Expr},
 	{STR_LIT("type_info_of"),     1, false, Expr_Expr},
+	{STR_LIT("typeid_of"),        1, false, Expr_Expr},
 
 	{STR_LIT("swizzle"),          1, true,  Expr_Expr},
 

+ 11 - 0
src/ir.cpp

@@ -4203,6 +4203,13 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
 		return ir_type_info(proc, t);
 	}
 
+	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));
+	}
+
 	case BuiltinProc_len: {
 		irValue *v = ir_build_expr(proc, ce->args[0]);
 		Type *t = base_type(ir_type(v));
@@ -7951,6 +7958,10 @@ void ir_setup_type_info_data(irProcedure *proc) { // NOTE(bill): Setup type_info
 			case Basic_any:
 				tag = ir_emit_conv(proc, variant_ptr, t_type_info_any_ptr);
 				break;
+
+			case Basic_typeid:
+				tag = ir_emit_conv(proc, variant_ptr, t_type_info_typeid_ptr);
+				break;
 			}
 			break;
 

+ 7 - 0
src/ir_print.cpp

@@ -342,6 +342,7 @@ void ir_print_type(irFileBuffer *f, irModule *m, Type *t, bool in_struct) {
 		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;
 
@@ -1750,6 +1751,12 @@ void print_llvm_ir(irGen *ir) {
 	ir_print_type(f, m, t_type_info_ptr);
 	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');
 

+ 14 - 2
src/types.cpp

@@ -38,6 +38,8 @@ enum BasicKind {
 	Basic_cstring, // ^u8
 	Basic_any,     // rawptr + ^Type_Info
 
+	Basic_typeid,
+
 	Basic_UntypedBool,
 	Basic_UntypedInteger,
 	Basic_UntypedFloat,
@@ -283,6 +285,8 @@ gb_global Type basic_types[] = {
 	{Type_Basic, {Basic_cstring,           BasicFlag_String,                          -1, STR_LIT("cstring")}},
 	{Type_Basic, {Basic_any,               0,                                         -1, STR_LIT("any")}},
 
+	{Type_Basic, {Basic_typeid,            0,                                         -1, STR_LIT("typeid")}},
+
 	{Type_Basic, {Basic_UntypedBool,       BasicFlag_Boolean    | BasicFlag_Untyped,   0, STR_LIT("untyped bool")}},
 	{Type_Basic, {Basic_UntypedInteger,    BasicFlag_Integer    | BasicFlag_Untyped,   0, STR_LIT("untyped integer")}},
 	{Type_Basic, {Basic_UntypedFloat,      BasicFlag_Float      | BasicFlag_Untyped,   0, STR_LIT("untyped float")}},
@@ -329,6 +333,8 @@ gb_global Type *t_string          = &basic_types[Basic_string];
 gb_global Type *t_cstring         = &basic_types[Basic_cstring];
 gb_global Type *t_any             = &basic_types[Basic_any];
 
+gb_global Type *t_typeid          = &basic_types[Basic_typeid];
+
 gb_global Type *t_untyped_bool       = &basic_types[Basic_UntypedBool];
 gb_global Type *t_untyped_integer    = &basic_types[Basic_UntypedInteger];
 gb_global Type *t_untyped_float      = &basic_types[Basic_UntypedFloat];
@@ -360,6 +366,7 @@ gb_global Type *t_type_info_rune              = nullptr;
 gb_global Type *t_type_info_float             = nullptr;
 gb_global Type *t_type_info_complex           = nullptr;
 gb_global Type *t_type_info_any               = nullptr;
+gb_global Type *t_type_info_typeid            = nullptr;
 gb_global Type *t_type_info_string            = nullptr;
 gb_global Type *t_type_info_boolean           = nullptr;
 gb_global Type *t_type_info_pointer           = nullptr;
@@ -381,6 +388,7 @@ gb_global Type *t_type_info_float_ptr         = nullptr;
 gb_global Type *t_type_info_complex_ptr       = nullptr;
 gb_global Type *t_type_info_quaternion_ptr    = nullptr;
 gb_global Type *t_type_info_any_ptr           = nullptr;
+gb_global Type *t_type_info_typeid_ptr        = nullptr;
 gb_global Type *t_type_info_string_ptr        = nullptr;
 gb_global Type *t_type_info_boolean_ptr       = nullptr;
 gb_global Type *t_type_info_pointer_ptr       = nullptr;
@@ -1128,6 +1136,8 @@ bool is_type_comparable(Type *t) {
 			return true;
 		case Basic_cstring:
 			return false;
+		case Basic_typeid:
+			return true;
 		}
 		return true;
 	case Type_Pointer:
@@ -1334,7 +1344,7 @@ Type *default_type(Type *type) {
 	return type;
 }
 
-
+/*
 // NOTE(bill): Valid Compile time execution #run type
 bool is_type_cte_safe(Type *type) {
 	type = default_type(base_type(type));
@@ -1392,7 +1402,7 @@ bool is_type_cte_safe(Type *type) {
 
 	return false;
 }
-
+ */
 i64 union_variant_index(Type *u, Type *v) {
 	u = base_type(u);
 	GB_ASSERT(u->kind == Type_Union);
@@ -1884,6 +1894,7 @@ i64 type_align_of_internal(Type *t, TypePath *path) {
 		case Basic_string:  return build_context.word_size;
 		case Basic_cstring: return build_context.word_size;
 		case Basic_any:     return build_context.word_size;
+		case Basic_typeid:  return build_context.word_size;
 
 		case Basic_int: case Basic_uint: case Basic_uintptr: case Basic_rawptr:
 			return build_context.word_size;
@@ -2085,6 +2096,7 @@ i64 type_size_of_internal(Type *t, TypePath *path) {
 		case Basic_string:  return 2*build_context.word_size;
 		case Basic_cstring: return build_context.word_size;
 		case Basic_any:     return 2*build_context.word_size;
+		case Basic_typeid:  return build_context.word_size;
 
 		case Basic_int: case Basic_uint: case Basic_uintptr: case Basic_rawptr:
 			return build_context.word_size;