mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-05 15:18:49 +00:00
Fix type info generation
The problem: entry's index != entry->value in info_type_map But I was assuming this
This commit is contained in:
+48
-20
@@ -8,7 +8,7 @@ main :: proc() {
|
|||||||
// bounds_checking()
|
// bounds_checking()
|
||||||
// type_introspection()
|
// type_introspection()
|
||||||
// any_type()
|
// any_type()
|
||||||
crazy_introspection()
|
// crazy_introspection()
|
||||||
// namespaces_and_files()
|
// namespaces_and_files()
|
||||||
// miscellany()
|
// miscellany()
|
||||||
}
|
}
|
||||||
@@ -143,25 +143,51 @@ bounds_checking :: proc() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type_introspection :: proc() {
|
type_introspection :: proc() {
|
||||||
|
{
|
||||||
|
info: ^Type_Info
|
||||||
|
x: int
|
||||||
|
|
||||||
info: ^Type_Info
|
info = type_info(int) // by type
|
||||||
x: int
|
info = type_info_of_val(x) // by value
|
||||||
|
// See: runtime.odin
|
||||||
|
|
||||||
info = type_info(int) // by type
|
match type i : info {
|
||||||
info = type_info(x) // by value
|
case Type_Info.Integer:
|
||||||
// See: runtime.odin
|
fmt.println("integer!")
|
||||||
|
case Type_Info.Float:
|
||||||
|
fmt.println("float!")
|
||||||
|
default:
|
||||||
|
fmt.println("potato!")
|
||||||
|
}
|
||||||
|
|
||||||
match type i : info {
|
// Unsafe cast
|
||||||
case Type_Info.Integer:
|
integer_info := info as ^Type_Info.Integer
|
||||||
fmt.println("integer!")
|
|
||||||
case Type_Info.Float:
|
|
||||||
fmt.println("float!")
|
|
||||||
default:
|
|
||||||
fmt.println("potato!")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unsafe cast
|
{
|
||||||
integer_info := info as ^Type_Info.Integer
|
Vector2 :: struct { x, y: f32 }
|
||||||
|
Vector3 :: struct { x, y, z: f32 }
|
||||||
|
|
||||||
|
v1: Vector2
|
||||||
|
v2: Vector3
|
||||||
|
v3: Vector3
|
||||||
|
|
||||||
|
t1 := type_info_of_val(v1)
|
||||||
|
t2 := type_info_of_val(v2)
|
||||||
|
t3 := type_info_of_val(v3)
|
||||||
|
|
||||||
|
fmt.println()
|
||||||
|
fmt.print("Type of v1 is:\n\t", t1)
|
||||||
|
// fmt.fprint_type(os.stdout, t1)
|
||||||
|
|
||||||
|
fmt.println()
|
||||||
|
fmt.print("Type of v2 is:\n\t")
|
||||||
|
fmt.fprint_type(os.stdout, t2)
|
||||||
|
|
||||||
|
fmt.println("\n")
|
||||||
|
fmt.println("t1 == t2:", t1 == t2)
|
||||||
|
fmt.println("t2 == t3:", t2 == t3)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
any_type :: proc() {
|
any_type :: proc() {
|
||||||
@@ -174,14 +200,17 @@ any_type :: proc() {
|
|||||||
a = x
|
a = x
|
||||||
a = y
|
a = y
|
||||||
a = z
|
a = z
|
||||||
a = a
|
a = a // This the "identity" type, it doesn't get converted
|
||||||
|
|
||||||
|
a = 123 // Literals are copied onto the stack first
|
||||||
|
|
||||||
// any has two members
|
// any has two members
|
||||||
// data - rawptr to the data
|
// data - rawptr to the data
|
||||||
// type_info - pointer to the type info
|
// type_info - pointer to the type info
|
||||||
|
|
||||||
fmt.println(x, y, z)
|
fmt.println(x, y, z)
|
||||||
// See: Implementation
|
// See: fmt.odin
|
||||||
|
// For variadic any procedures in action
|
||||||
}
|
}
|
||||||
|
|
||||||
crazy_introspection :: proc() {
|
crazy_introspection :: proc() {
|
||||||
@@ -204,6 +233,7 @@ crazy_introspection :: proc() {
|
|||||||
fmt.println(s)
|
fmt.println(s)
|
||||||
|
|
||||||
fmt.println(f)
|
fmt.println(f)
|
||||||
|
// See: runtime.odin
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -225,9 +255,7 @@ crazy_introspection :: proc() {
|
|||||||
name := (fruit_ti as ^Type_Info.Named).name // Unsafe casts
|
name := (fruit_ti as ^Type_Info.Named).name // Unsafe casts
|
||||||
info := type_info_base(fruit_ti) as ^Type_Info.Enum // Unsafe casts
|
info := type_info_base(fruit_ti) as ^Type_Info.Enum // Unsafe casts
|
||||||
|
|
||||||
fmt.printf("% :: enum ", name);
|
fmt.printf("% :: enum % {", name, info.base);
|
||||||
fmt.fprint_type(os.stdout, info.base)
|
|
||||||
fmt.printf(" {\n")
|
|
||||||
for i := 0; i < info.values.count; i++ {
|
for i := 0; i < info.values.count; i++ {
|
||||||
fmt.printf("\t%\t= %,\n", info.names[i], info.values[i])
|
fmt.printf("\t%\t= %,\n", info.names[i], info.values[i])
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-3
@@ -419,11 +419,15 @@ print_any_to_buffer :: proc(buf: ^[]byte, arg: any) {
|
|||||||
print_bool_to_buffer(buf, v)
|
print_bool_to_buffer(buf, v)
|
||||||
|
|
||||||
case Pointer:
|
case Pointer:
|
||||||
v := null;
|
|
||||||
if arg.data != null {
|
if arg.data != null {
|
||||||
v = (arg.data as ^rawptr)^
|
if arg.type_info == type_info(^Type_Info) {
|
||||||
|
print_type_to_buffer(buf, (arg.data as ^^Type_Info)^)
|
||||||
|
} else {
|
||||||
|
print_pointer_to_buffer(buf, (arg.data as ^rawptr)^)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
print_pointer_to_buffer(buf, null)
|
||||||
}
|
}
|
||||||
print_pointer_to_buffer(buf, v)
|
|
||||||
|
|
||||||
case Enum:
|
case Enum:
|
||||||
value: i64 = 0
|
value: i64 = 0
|
||||||
|
|||||||
@@ -142,6 +142,7 @@ enum BuiltinProcId {
|
|||||||
BuiltinProc_type_of_val,
|
BuiltinProc_type_of_val,
|
||||||
|
|
||||||
BuiltinProc_type_info,
|
BuiltinProc_type_info,
|
||||||
|
BuiltinProc_type_info_of_val,
|
||||||
|
|
||||||
BuiltinProc_compile_assert,
|
BuiltinProc_compile_assert,
|
||||||
BuiltinProc_assert,
|
BuiltinProc_assert,
|
||||||
@@ -186,6 +187,7 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_Count] = {
|
|||||||
{STR_LIT("type_of_val"), 1, false, Expr_Expr},
|
{STR_LIT("type_of_val"), 1, false, Expr_Expr},
|
||||||
|
|
||||||
{STR_LIT("type_info"), 1, false, Expr_Expr},
|
{STR_LIT("type_info"), 1, false, Expr_Expr},
|
||||||
|
{STR_LIT("type_info_of_val"), 1, false, Expr_Expr},
|
||||||
|
|
||||||
{STR_LIT("compile_assert"), 1, false, Expr_Stmt},
|
{STR_LIT("compile_assert"), 1, false, Expr_Stmt},
|
||||||
{STR_LIT("assert"), 1, false, Expr_Stmt},
|
{STR_LIT("assert"), 1, false, Expr_Stmt},
|
||||||
|
|||||||
+47
-25
@@ -1072,6 +1072,13 @@ Type *check_type(Checker *c, AstNode *e, Type *named_type, CycleChecker *cycle_c
|
|||||||
type = o.type;
|
type = o.type;
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
} else if (e->kind == AstNode_UnaryExpr) {
|
||||||
|
ast_node(ue, UnaryExpr, e);
|
||||||
|
if (ue->op.kind == Token_Pointer) {
|
||||||
|
type = make_type_pointer(c->allocator, check_type(c, ue->expr));
|
||||||
|
set_base_type(named_type, type);
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err_str = expr_to_string(e);
|
err_str = expr_to_string(e);
|
||||||
@@ -2241,10 +2248,8 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
|
|||||||
|
|
||||||
case BuiltinProc_size_of: {
|
case BuiltinProc_size_of: {
|
||||||
// size_of :: proc(Type) -> int
|
// size_of :: proc(Type) -> int
|
||||||
Operand op = {};
|
Type *type = check_type(c, ce->args[0]);
|
||||||
check_expr_or_type(c, &op, ce->args[0]);
|
if (type == NULL || type == t_invalid) {
|
||||||
Type *type = op.type;
|
|
||||||
if (type == NULL || op.mode == Addressing_Builtin) {
|
|
||||||
error(ast_node_token(ce->args[0]), "Expected a type for `size_of`");
|
error(ast_node_token(ce->args[0]), "Expected a type for `size_of`");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -2269,10 +2274,8 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
|
|||||||
|
|
||||||
case BuiltinProc_align_of: {
|
case BuiltinProc_align_of: {
|
||||||
// align_of :: proc(Type) -> int
|
// align_of :: proc(Type) -> int
|
||||||
Operand op = {};
|
Type *type = check_type(c, ce->args[0]);
|
||||||
check_expr_or_type(c, &op, ce->args[0]);
|
if (type == NULL || type == t_invalid) {
|
||||||
Type *type = op.type;
|
|
||||||
if (type == NULL || op.mode == Addressing_Builtin) {
|
|
||||||
error(ast_node_token(ce->args[0]), "Expected a type for `align_of`");
|
error(ast_node_token(ce->args[0]), "Expected a type for `align_of`");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -2296,10 +2299,8 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
|
|||||||
case BuiltinProc_offset_of: {
|
case BuiltinProc_offset_of: {
|
||||||
// offset_val :: proc(Type, field) -> int
|
// offset_val :: proc(Type, field) -> int
|
||||||
Operand op = {};
|
Operand op = {};
|
||||||
check_expr_or_type(c, &op, ce->args[0]);
|
Type *type = get_base_type(check_type(c, ce->args[0]));
|
||||||
Type *type = get_base_type(op.type);
|
if (type != NULL || type == t_invalid) {
|
||||||
AstNode *field_arg = unparen_expr(ce->args[1]);
|
|
||||||
if (type != NULL || op.mode == Addressing_Builtin) {
|
|
||||||
error(ast_node_token(ce->args[0]), "Expected a type for `offset_of`");
|
error(ast_node_token(ce->args[0]), "Expected a type for `offset_of`");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -2307,6 +2308,8 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
|
|||||||
error(ast_node_token(ce->args[0]), "Expected a structure type for `offset_of`");
|
error(ast_node_token(ce->args[0]), "Expected a structure type for `offset_of`");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AstNode *field_arg = unparen_expr(ce->args[1]);
|
||||||
if (field_arg == NULL ||
|
if (field_arg == NULL ||
|
||||||
field_arg->kind != AstNode_Ident) {
|
field_arg->kind != AstNode_Ident) {
|
||||||
error(ast_node_token(field_arg), "Expected an identifier for field argument");
|
error(ast_node_token(field_arg), "Expected an identifier for field argument");
|
||||||
@@ -2377,19 +2380,34 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
|
|||||||
|
|
||||||
|
|
||||||
case BuiltinProc_type_info: {
|
case BuiltinProc_type_info: {
|
||||||
// type_info :: proc(val_or_type) -> ^Type_Info
|
// type_info :: proc(Type) -> ^Type_Info
|
||||||
operand->mode = Addressing_Value;
|
AstNode *expr = ce->args[0];
|
||||||
operand->type = t_type_info_ptr;
|
Type *type = check_type(c, expr);
|
||||||
|
if (type == NULL || type == t_invalid) {
|
||||||
Operand op = {};
|
error(ast_node_token(expr), "Invalid argument to `type_info`");
|
||||||
check_expr_or_type(c, &op, ce->args[0]);
|
|
||||||
if (op.type == NULL || op.type == t_invalid || operand->mode == Addressing_Builtin) {
|
|
||||||
error(ast_node_token(op.expr), "Invalid argument to `type_info`");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
add_type_info_type(c, op.type);
|
add_type_info_type(c, type);
|
||||||
|
|
||||||
|
operand->mode = Addressing_Value;
|
||||||
|
operand->type = t_type_info_ptr;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case BuiltinProc_type_info_of_val: {
|
||||||
|
// type_info_of_val :: proc(val: Type) -> ^Type_Info
|
||||||
|
AstNode *expr = ce->args[0];
|
||||||
|
|
||||||
|
check_assignment(c, operand, NULL, make_string("argument of `type_info_of_val`"));
|
||||||
|
if (operand->mode == Addressing_Invalid || operand->mode == Addressing_Builtin)
|
||||||
|
return false;
|
||||||
|
add_type_info_type(c, operand->type);
|
||||||
|
|
||||||
|
operand->mode = Addressing_Value;
|
||||||
|
operand->type = t_type_info_ptr;
|
||||||
|
} break;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
case BuiltinProc_compile_assert:
|
case BuiltinProc_compile_assert:
|
||||||
// compile_assert :: proc(cond: bool)
|
// compile_assert :: proc(cond: bool)
|
||||||
|
|
||||||
@@ -3379,18 +3397,21 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
|
|||||||
|
|
||||||
case_ast_node(ue, UnaryExpr, node);
|
case_ast_node(ue, UnaryExpr, node);
|
||||||
check_expr(c, o, ue->expr);
|
check_expr(c, o, ue->expr);
|
||||||
if (o->mode == Addressing_Invalid)
|
if (o->mode == Addressing_Invalid) {
|
||||||
goto error;
|
goto error;
|
||||||
|
}
|
||||||
check_unary_expr(c, o, ue->op, node);
|
check_unary_expr(c, o, ue->op, node);
|
||||||
if (o->mode == Addressing_Invalid)
|
if (o->mode == Addressing_Invalid) {
|
||||||
goto error;
|
goto error;
|
||||||
|
}
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
|
|
||||||
case_ast_node(be, BinaryExpr, node);
|
case_ast_node(be, BinaryExpr, node);
|
||||||
check_binary_expr(c, o, node);
|
check_binary_expr(c, o, node);
|
||||||
if (o->mode == Addressing_Invalid)
|
if (o->mode == Addressing_Invalid) {
|
||||||
goto error;
|
goto error;
|
||||||
|
}
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
|
|
||||||
@@ -3402,8 +3423,9 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
|
|||||||
|
|
||||||
case_ast_node(ie, IndexExpr, node);
|
case_ast_node(ie, IndexExpr, node);
|
||||||
check_expr(c, o, ie->expr);
|
check_expr(c, o, ie->expr);
|
||||||
if (o->mode == Addressing_Invalid)
|
if (o->mode == Addressing_Invalid) {
|
||||||
goto error;
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
b32 valid = false;
|
b32 valid = false;
|
||||||
i64 max_count = -1;
|
i64 max_count = -1;
|
||||||
|
|||||||
@@ -1062,7 +1062,8 @@ i64 type_size_of(BaseTypeSizes s, gbAllocator allocator, Type *t) {
|
|||||||
if (max < size)
|
if (max < size)
|
||||||
max = size;
|
max = size;
|
||||||
}
|
}
|
||||||
return align_formula(max, s.max_align) + type_size_of(s, allocator, t_int);
|
// NOTE(bill): Align to int
|
||||||
|
return align_formula(max, s.word_size) + type_size_of(s, allocator, t_int);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case TypeRecord_RawUnion: {
|
case TypeRecord_RawUnion: {
|
||||||
|
|||||||
@@ -302,9 +302,12 @@ void ssa_gen_tree(ssaGen *s) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
gb_for_array(entry_index, info->type_info_map.entries) {
|
gb_for_array(type_info_map_index, info->type_info_map.entries) {
|
||||||
auto *entry = &info->type_info_map.entries[entry_index];
|
auto *entry = &info->type_info_map.entries[type_info_map_index];
|
||||||
Type *t = cast(Type *)cast(uintptr)entry->key.key;
|
Type *t = cast(Type *)cast(uintptr)entry->key.key;
|
||||||
|
t = default_type(t);
|
||||||
|
isize entry_index = entry->value;
|
||||||
|
|
||||||
|
|
||||||
ssaValue *tag = NULL;
|
ssaValue *tag = NULL;
|
||||||
|
|
||||||
|
|||||||
@@ -1327,6 +1327,8 @@ ssaValue *ssa_emit_deep_field_ev(ssaProcedure *proc, Type *type, ssaValue *e, Se
|
|||||||
|
|
||||||
|
|
||||||
isize ssa_type_info_index(CheckerInfo *info, Type *type) {
|
isize ssa_type_info_index(CheckerInfo *info, Type *type) {
|
||||||
|
type = default_type(type);
|
||||||
|
|
||||||
isize entry_index = -1;
|
isize entry_index = -1;
|
||||||
HashKey key = hash_pointer(type);
|
HashKey key = hash_pointer(type);
|
||||||
auto *found_entry_index = map_get(&info->type_info_map, key);
|
auto *found_entry_index = map_get(&info->type_info_map, key);
|
||||||
@@ -1763,6 +1765,8 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t, b32 is_arg
|
|||||||
data = ssa_add_local_generated(proc, src_type);
|
data = ssa_add_local_generated(proc, src_type);
|
||||||
ssa_emit_store(proc, data, value);
|
ssa_emit_store(proc, data, value);
|
||||||
}
|
}
|
||||||
|
GB_ASSERT(is_type_pointer(ssa_type(data)));
|
||||||
|
GB_ASSERT(is_type_typed(src_type));
|
||||||
data = ssa_emit_conv(proc, data, t_rawptr);
|
data = ssa_emit_conv(proc, data, t_rawptr);
|
||||||
|
|
||||||
|
|
||||||
@@ -2157,6 +2161,10 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
|
|||||||
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]));
|
||||||
return ssa_type_info(proc, t);
|
return ssa_type_info(proc, t);
|
||||||
} break;
|
} break;
|
||||||
|
case BuiltinProc_type_info_of_val: {
|
||||||
|
Type *t = default_type(type_of_expr(proc->module->info, ce->args[0]));
|
||||||
|
return ssa_type_info(proc, t);
|
||||||
|
} break;
|
||||||
|
|
||||||
case BuiltinProc_new: {
|
case BuiltinProc_new: {
|
||||||
ssa_emit_comment(proc, make_string("new"));
|
ssa_emit_comment(proc, make_string("new"));
|
||||||
|
|||||||
Reference in New Issue
Block a user