mirror of
https://github.com/odin-lang/Odin.git
synced 2026-04-19 21:10:30 +00:00
typeid
This commit is contained in:
@@ -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")
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
src/ir.cpp
11
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;
|
||||
|
||||
|
||||
@@ -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');
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user