Browse Source

Fix type info generation
The problem: entry's index != entry->value in info_type_map
But I was assuming this

Ginger Bill 9 years ago
parent
commit
6907951f1e
7 changed files with 118 additions and 50 deletions
  1. 49 21
      code/demo.odin
  2. 7 3
      core/fmt.odin
  3. 2 0
      src/checker/checker.cpp
  4. 45 23
      src/checker/expr.cpp
  5. 2 1
      src/checker/type.cpp
  6. 5 2
      src/codegen/codegen.cpp
  7. 8 0
      src/codegen/ssa.cpp

+ 49 - 21
code/demo.odin

@@ -8,7 +8,7 @@ main :: proc() {
 	// bounds_checking()
 	// type_introspection()
 	// any_type()
-	crazy_introspection()
+	// crazy_introspection()
 	// namespaces_and_files()
 	// miscellany()
 }
@@ -143,25 +143,51 @@ bounds_checking :: proc() {
 }
 
 type_introspection :: proc() {
+	{
+		info: ^Type_Info
+		x: int
+
+		info = type_info(int) // by type
+		info = type_info_of_val(x) // by value
+		// See: runtime.odin
+
+		match type i : info {
+		case Type_Info.Integer:
+			fmt.println("integer!")
+		case Type_Info.Float:
+			fmt.println("float!")
+		default:
+			fmt.println("potato!")
+		}
 
-	info: ^Type_Info
-	x: int
+		// Unsafe cast
+		integer_info := info as ^Type_Info.Integer
+	}
 
-	info = type_info(int) // by type
-	info = type_info(x) // by value
-	// See: runtime.odin
+	{
+		Vector2 :: struct { x, y: f32 }
+		Vector3 :: struct { x, y, z: f32 }
 
-	match type i : info {
-	case Type_Info.Integer:
-		fmt.println("integer!")
-	case Type_Info.Float:
-		fmt.println("float!")
-	default:
-		fmt.println("potato!")
-	}
+		v1: Vector2
+		v2: Vector3
+		v3: Vector3
 
-	// Unsafe cast
-	integer_info := info as ^Type_Info.Integer
+		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() {
@@ -174,14 +200,17 @@ any_type :: proc() {
 	a = x
 	a = y
 	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
 	// data      - rawptr to the data
 	// type_info - pointer to the type info
 
 	fmt.println(x, y, z)
-	// See: Implementation
+	// See: fmt.odin
+	// For variadic any procedures in action
 }
 
 crazy_introspection :: proc() {
@@ -204,6 +233,7 @@ crazy_introspection :: proc() {
 		fmt.println(s)
 
 		fmt.println(f)
+		// See: runtime.odin
 	}
 
 
@@ -225,9 +255,7 @@ crazy_introspection :: proc() {
 		name := (fruit_ti as ^Type_Info.Named).name // Unsafe casts
 		info := type_info_base(fruit_ti) as ^Type_Info.Enum // Unsafe casts
 
-		fmt.printf("% :: enum ", name);
-		fmt.fprint_type(os.stdout, info.base)
-		fmt.printf(" {\n")
+		fmt.printf("% :: enum % {", name, info.base);
 		for i := 0; i < info.values.count; i++ {
 			fmt.printf("\t%\t= %,\n", info.names[i], info.values[i])
 		}

+ 7 - 3
core/fmt.odin

@@ -419,11 +419,15 @@ print_any_to_buffer :: proc(buf: ^[]byte, arg: any)  {
 		print_bool_to_buffer(buf, v)
 
 	case Pointer:
-		v := 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:
 		value: i64 = 0

+ 2 - 0
src/checker/checker.cpp

@@ -142,6 +142,7 @@ enum BuiltinProcId {
 	BuiltinProc_type_of_val,
 
 	BuiltinProc_type_info,
+	BuiltinProc_type_info_of_val,
 
 	BuiltinProc_compile_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_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("assert"),           1, false, Expr_Stmt},

+ 45 - 23
src/checker/expr.cpp

@@ -1072,6 +1072,13 @@ Type *check_type(Checker *c, AstNode *e, Type *named_type, CycleChecker *cycle_c
 				type = o.type;
 				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);
@@ -2241,10 +2248,8 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
 
 	case BuiltinProc_size_of: {
 		// size_of :: proc(Type) -> int
-		Operand op = {};
-		check_expr_or_type(c, &op, ce->args[0]);
-		Type *type = op.type;
-		if (type == NULL || op.mode == Addressing_Builtin) {
+		Type *type = check_type(c, ce->args[0]);
+		if (type == NULL || type == t_invalid) {
 			error(ast_node_token(ce->args[0]), "Expected a type for `size_of`");
 			return false;
 		}
@@ -2269,10 +2274,8 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
 
 	case BuiltinProc_align_of: {
 		// align_of :: proc(Type) -> int
-		Operand op = {};
-		check_expr_or_type(c, &op, ce->args[0]);
-		Type *type = op.type;
-		if (type == NULL || op.mode == Addressing_Builtin) {
+		Type *type = check_type(c, ce->args[0]);
+		if (type == NULL || type == t_invalid) {
 			error(ast_node_token(ce->args[0]), "Expected a type for `align_of`");
 			return false;
 		}
@@ -2296,10 +2299,8 @@ b32 check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id)
 	case BuiltinProc_offset_of: {
 		// offset_val :: proc(Type, field) -> int
 		Operand op = {};
-		check_expr_or_type(c, &op, ce->args[0]);
-		Type *type = get_base_type(op.type);
-		AstNode *field_arg = unparen_expr(ce->args[1]);
-		if (type != NULL  || op.mode == Addressing_Builtin) {
+		Type *type = get_base_type(check_type(c, ce->args[0]));
+		if (type != NULL || type == t_invalid) {
 			error(ast_node_token(ce->args[0]), "Expected a type for `offset_of`");
 			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`");
 			return false;
 		}
+
+		AstNode *field_arg = unparen_expr(ce->args[1]);
 		if (field_arg == NULL ||
 		    field_arg->kind != AstNode_Ident) {
 			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: {
-		// type_info :: proc(val_or_type) -> ^Type_Info
+		// type_info :: proc(Type) -> ^Type_Info
+		AstNode *expr = ce->args[0];
+		Type *type = check_type(c, expr);
+		if (type == NULL || type == t_invalid) {
+			error(ast_node_token(expr), "Invalid argument to `type_info`");
+			return false;
+		}
+		add_type_info_type(c, type);
+
 		operand->mode = Addressing_Value;
 		operand->type = t_type_info_ptr;
+	} break;
 
-		Operand op = {};
-		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`");
+	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, op.type);
+		add_type_info_type(c, operand->type);
+
+		operand->mode = Addressing_Value;
+		operand->type = t_type_info_ptr;
 	} break;
 
+
+
 	case BuiltinProc_compile_assert:
 		// 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);
 		check_expr(c, o, ue->expr);
-		if (o->mode == Addressing_Invalid)
+		if (o->mode == Addressing_Invalid) {
 			goto error;
+		}
 		check_unary_expr(c, o, ue->op, node);
-		if (o->mode == Addressing_Invalid)
+		if (o->mode == Addressing_Invalid) {
 			goto error;
+		}
 	case_end;
 
 
 	case_ast_node(be, BinaryExpr, node);
 		check_binary_expr(c, o, node);
-		if (o->mode == Addressing_Invalid)
+		if (o->mode == Addressing_Invalid) {
 			goto error;
+		}
 	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);
 		check_expr(c, o, ie->expr);
-		if (o->mode == Addressing_Invalid)
+		if (o->mode == Addressing_Invalid) {
 			goto error;
+		}
 
 		b32 valid = false;
 		i64 max_count = -1;

+ 2 - 1
src/checker/type.cpp

@@ -1062,7 +1062,8 @@ i64 type_size_of(BaseTypeSizes s, gbAllocator allocator, Type *t) {
 				if (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;
 
 		case TypeRecord_RawUnion: {

+ 5 - 2
src/codegen/codegen.cpp

@@ -302,9 +302,12 @@ void ssa_gen_tree(ssaGen *s) {
 			};
 
 
-			gb_for_array(entry_index, info->type_info_map.entries) {
-				auto *entry = &info->type_info_map.entries[entry_index];
+			gb_for_array(type_info_map_index, info->type_info_map.entries) {
+				auto *entry = &info->type_info_map.entries[type_info_map_index];
 				Type *t = cast(Type *)cast(uintptr)entry->key.key;
+				t = default_type(t);
+				isize entry_index = entry->value;
+
 
 				ssaValue *tag = NULL;
 

+ 8 - 0
src/codegen/ssa.cpp

@@ -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) {
+	type = default_type(type);
+
 	isize entry_index = -1;
 	HashKey key = hash_pointer(type);
 	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);
 			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);
 
 
@@ -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]));
 					return ssa_type_info(proc, t);
 				} 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: {
 					ssa_emit_comment(proc, make_string("new"));