Browse Source

Fix missing `type_info` with manual linear search

Ginger Bill 9 years ago
parent
commit
c6d02e4778

+ 1 - 0
build.bat

@@ -10,6 +10,7 @@ set compiler_flags= -nologo -Oi -TP -W4 -fp:fast -fp:except- -Gm- -MP -FC -Z7 -G
 
 if %release_mode% EQU 0 ( rem Debug
 	set compiler_flags=%compiler_flags% -Od -MDd -Z7
+	rem -DDISPLAY_TIMING
 ) else ( rem Release
 	set compiler_flags=%compiler_flags% -O2 -MT
 )

+ 14 - 42
examples/basic.odin

@@ -63,8 +63,8 @@ print_nl_to_buffer    :: proc(buf: ^[]byte) { print_rune_to_buffer(buf, #rune "\
 print_int_to_buffer :: proc(buf: ^[]byte, i: int) {
 	print_int_base_to_buffer(buf, i, 10);
 }
+PRINT__NUM_TO_CHAR_TABLE :: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@$"
 print_int_base_to_buffer :: proc(buffer: ^[]byte, i, base: int) {
-	NUM_TO_CHAR_TABLE :: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@$"
 
 	buf: [65]byte
 	len := 0
@@ -78,7 +78,7 @@ print_int_base_to_buffer :: proc(buffer: ^[]byte, i, base: int) {
 		len++
 	}
 	for i > 0 {
-		buf[len] = NUM_TO_CHAR_TABLE[i % base]
+		buf[len] = PRINT__NUM_TO_CHAR_TABLE[i % base]
 		len++;
 		i /= base
 	}
@@ -96,8 +96,6 @@ print_uint_to_buffer :: proc(buffer: ^[]byte, i: uint) {
 	print_uint_base_to_buffer(buffer, i, 10, 0, #rune " ")
 }
 print_uint_base_to_buffer :: proc(buffer: ^[]byte, i, base: uint, min_width: int, pad_char: byte) {
-	NUM_TO_CHAR_TABLE :: "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@$"
-
 	buf: [65]byte
 	len := 0
 	if i == 0 {
@@ -105,7 +103,7 @@ print_uint_base_to_buffer :: proc(buffer: ^[]byte, i, base: uint, min_width: int
 		len++
 	}
 	for i > 0 {
-		buf[len] = NUM_TO_CHAR_TABLE[i % base]
+		buf[len] = PRINT__NUM_TO_CHAR_TABLE[i % base]
 		len++
 		i /= base
 	}
@@ -139,8 +137,6 @@ print__f64 :: proc(buffer: ^[]byte, f: f64, decimal_places: int) {
 	}
 
 	print_u64_to_buffer :: proc(buffer: ^[]byte, i: u64) {
-		NUM_TO_CHAR_TABLE :: "0123456789"
-
 		buf: [22]byte
 		len := 0
 		if i == 0 {
@@ -148,7 +144,7 @@ print__f64 :: proc(buffer: ^[]byte, f: f64, decimal_places: int) {
 			len++
 		}
 		for i > 0 {
-			buf[len] = NUM_TO_CHAR_TABLE[i % 10]
+			buf[len] = PRINT__NUM_TO_CHAR_TABLE[i % 10]
 			len++
 			i /= 10
 		}
@@ -173,13 +169,14 @@ print__f64 :: proc(buffer: ^[]byte, f: f64, decimal_places: int) {
 
 
 
-print_any_to_buffer :: proc(buf: ^[]byte ,arg: any)  {
+print_any_to_buffer :: proc(buf: ^[]byte, arg: any)  {
 	using Type_Info
 	match type arg.type_info -> info {
 	case Named:
-		print_string_to_buffer(buf, "(")
-		print_string_to_buffer(buf, info.name)
-		print_string_to_buffer(buf, ")")
+		a: any
+		a.type_info = info.base
+		a.data = arg.data
+		print_any_to_buffer(buf, a)
 
 	case Integer:
 		if info.signed {
@@ -250,7 +247,6 @@ print_any_to_buffer :: proc(buf: ^[]byte ,arg: any)  {
 	case Slice:     print_string_to_buffer(buf, "(slice)")
 	case Vector:    print_string_to_buffer(buf, "(vector)")
 
-
 	case Struct:    print_string_to_buffer(buf, "(struct)")
 	case Union:     print_string_to_buffer(buf, "(union)")
 	case Raw_Union: print_string_to_buffer(buf, "(raw_union)")
@@ -265,38 +261,22 @@ print_any_to_buffer :: proc(buf: ^[]byte ,arg: any)  {
 
 print_to_buffer :: proc(buf: ^[]byte, args: ..any) {
 	for i := 0; i < len(args); i++ {
-		arg := args[i]
-
 		if i > 0 {
 			print_space_to_buffer(buf)
 		}
-		print_any_to_buffer(buf, arg)
+		print_any_to_buffer(buf, args[i])
 	}
-	print_nl_to_buffer(buf)
 }
 
 println_to_buffer :: proc(buf: ^[]byte, args: ..any) {
-	for i := 0; i < len(args); i++ {
-		arg := args[i]
-
-		if i > 0 {
-			print_space_to_buffer(buf)
-		}
-		print_any_to_buffer(buf, arg)
-	}
+	print_to_buffer(buf, ..args)
+	print_nl_to_buffer(buf)
 }
 
 print :: proc(args: ..any) {
 	data: [4096]byte
 	buf := data[:0]
-	for i := 0; i < len(args); i++ {
-		arg := args[i]
-
-		if i > 0 {
-			print_space_to_buffer(^buf)
-		}
-		print_any_to_buffer(^buf, arg)
-	}
+	print_to_buffer(^buf, ..args)
 	file_write(file_get_standard(File_Standard.OUTPUT), buf)
 }
 
@@ -304,14 +284,6 @@ print :: proc(args: ..any) {
 println :: proc(args: ..any) {
 	data: [4096]byte
 	buf := data[:0]
-	for i := 0; i < len(args); i++ {
-		arg := args[i]
-
-		if i > 0 {
-			print_space_to_buffer(^buf)
-		}
-		print_any_to_buffer(^buf, arg)
-	}
-	print_nl_to_buffer(^buf)
+	println_to_buffer(^buf, ..args)
 	file_write(file_get_standard(File_Standard.OUTPUT), buf)
 }

+ 1 - 8
examples/demo.odin

@@ -2,13 +2,6 @@
 #load "math.odin"
 
 main :: proc() {
-	i: int
-	s: struct {
-		x, y, z: f32
-	}
-	p := ^s
-
-	a: any = i
-
+	a: any = 1
 	println(137, "Hello", 1.25, true)
 }

+ 3 - 3
examples/math.odin

@@ -95,9 +95,9 @@ cross :: proc(x, y: Vec3) -> Vec3 {
 }
 
 
-vec2_mag :: proc(v: Vec2) -> f32 { return fsqrt(v ''dot2 v) }
-vec3_mag :: proc(v: Vec3) -> f32 { return fsqrt(v ''dot3 v) }
-vec4_mag :: proc(v: Vec4) -> f32 { return fsqrt(v ''dot4 v) }
+vec2_mag :: proc(v: Vec2) -> f32 { return fsqrt(dot2(v, v)) }
+vec3_mag :: proc(v: Vec3) -> f32 { return fsqrt(dot3(v, v)) }
+vec4_mag :: proc(v: Vec4) -> f32 { return fsqrt(dot4(v, v)) }
 
 vec2_norm :: proc(v: Vec2) -> Vec2 { return v / Vec2{vec2_mag(v)} }
 vec3_norm :: proc(v: Vec3) -> Vec3 { return v / Vec3{vec3_mag(v)} }

+ 2 - 3
examples/runtime.odin

@@ -9,7 +9,7 @@ Type_Info :: union {
 		offset: int
 	}
 	Record :: struct {
-		fields: []Member
+		fields: []Member // NOTE(bill): This will need to be allocated on the heap
 	}
 
 
@@ -50,6 +50,7 @@ Type_Info :: union {
 }
 
 
+
 assume :: proc(cond: bool) #foreign "llvm.assume"
 
 __debug_trap           :: proc()        #foreign "llvm.debugtrap"
@@ -276,7 +277,5 @@ __default_allocator :: proc() -> Allocator {
 
 __assert :: proc(msg: string) {
 	file_write(file_get_standard(File_Standard.ERROR), msg as []byte)
-	// TODO(bill): Which is better?
-	// __trap()
 	__debug_trap()
 }

+ 2 - 1
src/checker/checker.cpp

@@ -866,7 +866,7 @@ void check_parsed_files(Checker *c) {
 		t_type_info_ptr = make_type_pointer(c->allocator, t_type_info);
 
 		auto *record = &get_base_type(e->type)->Record;
-		GB_ASSERT(record->field_count == 15);
+		GB_ASSERT_MSG(record->field_count == 15, "Internal Compiler Error: Invalid `Type_Info` layout");
 		t_type_info_named     = record->fields[ 1]->type;
 		t_type_info_integer   = record->fields[ 2]->type;
 		t_type_info_float     = record->fields[ 3]->type;
@@ -881,6 +881,7 @@ void check_parsed_files(Checker *c) {
 		t_type_info_union     = record->fields[12]->type;
 		t_type_info_raw_union = record->fields[13]->type;
 		t_type_info_enum      = record->fields[14]->type;
+		// t_type_info_any       = record->fields[15]->type;
 	}
 
 	check_global_entity(c, Entity_Constant);

+ 6 - 4
src/checker/entity.cpp

@@ -6,7 +6,6 @@ enum BuiltinProcId;
 	ENTITY_KIND(Invalid), \
 	ENTITY_KIND(Constant), \
 	ENTITY_KIND(Variable), \
-	ENTITY_KIND(UsingVariable), \
 	ENTITY_KIND(TypeName), \
 	ENTITY_KIND(Procedure), \
 	ENTITY_KIND(Builtin), \
@@ -46,10 +45,12 @@ struct Entity {
 			b8 used;      // Variable is used
 			b8 is_field;  // Is struct field
 			b8 anonymous; // Variable is an anonymous
+			b8 is_using;  // `using` variable
 		} Variable;
-		struct {} UsingVariable;
 		struct {} TypeName;
-		struct { b8 used; } Procedure;
+		struct {
+			b8 pure;
+		} Procedure;
 		struct { BuiltinProcId id; } Builtin;
 	};
 };
@@ -77,8 +78,9 @@ Entity *make_entity_variable(gbAllocator a, Scope *scope, Token token, Type *typ
 
 Entity *make_entity_using_variable(gbAllocator a, Entity *parent, Token token, Type *type) {
 	GB_ASSERT(parent != NULL);
-	Entity *entity = alloc_entity(a, Entity_UsingVariable, parent->scope, token, type);
+	Entity *entity = alloc_entity(a, Entity_Variable, parent->scope, token, type);
 	entity->using_parent = parent;
+	entity->Variable.is_using = true;
 	return entity;
 }
 

+ 1 - 7
src/checker/expr.cpp

@@ -91,8 +91,6 @@ b32 check_is_assignable_to(Checker *c, Operand *operand, Type *type, b32 is_argu
 
 	Type *s = operand->type;
 
-
-
 	if (are_types_identical(s, type)) {
 		return true;
 	}
@@ -179,6 +177,7 @@ void check_assignment(Checker *c, Operand *operand, Type *type, String context_n
 		Type *target_type = type;
 
 		if (type == NULL || is_type_any(type)) {
+			add_type_info_type(c, type);
 			target_type = default_type(operand->type);
 		}
 		convert_to_typed(c, operand, target_type);
@@ -795,11 +794,6 @@ void check_identifier(Checker *c, Operand *o, AstNode *n, Type *named_type, Cycl
 		o->mode = Addressing_Builtin;
 		break;
 
-	case Entity_UsingVariable:
-		// TODO(bill): Entity_UsingVariable: is this correct?
-		o->mode = Addressing_Variable;
-		break;
-
 	default:
 		GB_PANIC("Compiler error: Unknown EntityKind");
 		break;

+ 2 - 2
src/checker/stmt.cpp

@@ -452,6 +452,7 @@ void check_proc_decl(Checker *c, Entity *e, DeclInfo *d, b32 check_body_later) {
 	b32 is_foreign   = (pd->tags & ProcTag_foreign)   != 0;
 	b32 is_inline    = (pd->tags & ProcTag_inline)    != 0;
 	b32 is_no_inline = (pd->tags & ProcTag_no_inline) != 0;
+	b32 is_pure      = (pd->tags & ProcTag_pure)      != 0;
 
 
 
@@ -1283,8 +1284,7 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
 				error(&c->error_collector, us->token, "`using` cannot be applied to a procedure");
 				break;
 
-			case Entity_Variable:
-			case Entity_UsingVariable: {
+			case Entity_Variable: {
 				Type *t = get_base_type(type_deref(e->type));
 				if (is_type_struct(t) || is_type_raw_union(t)) {
 					Scope **found = map_get(&c->info.scopes, hash_pointer(t->Record.node));

+ 1 - 0
src/checker/type.cpp

@@ -369,6 +369,7 @@ gb_global Type *t_type_info_struct    = NULL;
 gb_global Type *t_type_info_union     = NULL;
 gb_global Type *t_type_info_raw_union = NULL;
 gb_global Type *t_type_info_enum      = NULL;
+gb_global Type *t_type_info_any       = NULL;
 
 
 

+ 17 - 7
src/codegen/ssa.cpp

@@ -1532,7 +1532,6 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t, b32 is_arg
 		ssaValue *type_info_data = *found;
 		CheckerInfo *info = proc->module->info;
 
-
 		ssaValue *result = ssa_add_local_generated(proc, t_any);
 
 		// NOTE(bill): Make copy on stack so I can reference it later
@@ -1542,8 +1541,20 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t, b32 is_arg
 
 
 		MapFindResult fr = map__find(&info->type_info_types, hash_pointer(src_type));
-		GB_ASSERT(fr.entry_index >= 0);
-		ssaValue *ti = ssa_emit_struct_gep(proc, type_info_data, fr.entry_index, t_type_info_ptr);
+		isize entry_index = fr.entry_index;
+		if (entry_index < 0) {
+			// NOTE(bill): Do manual search
+			// TODO(bill): This is O(n) and can be very slow
+			gb_for_array(i, info->type_info_types.entries){
+				auto *e = &info->type_info_types.entries[i];
+				Type *t = e->value;
+				if (are_types_identical(t, src_type)) {
+					entry_index = i;
+					break;
+				}
+			}
+		}
+		ssaValue *ti = ssa_emit_struct_gep(proc, type_info_data, entry_index, t_type_info_ptr);
 
 		ssaValue *gep0 = ssa_emit_struct_gep(proc, result, v_zero32, make_type_pointer(proc->module->allocator, t_type_info_ptr));
 		ssaValue *gep1 = ssa_emit_struct_gep(proc, result, v_one32,  make_type_pointer(proc->module->allocator, t_rawptr));
@@ -2396,11 +2407,11 @@ ssaValue *ssa_build_expr(ssaProcedure *proc, AstNode *expr) {
 
 
 ssaValue *ssa_add_using_variable(ssaProcedure *proc, Entity *e) {
-	GB_ASSERT(e->kind == Entity_UsingVariable);
+	GB_ASSERT(e->kind == Entity_Variable && e->Variable.is_using);
 	String name = e->token.string;
 	Entity *parent = e->using_parent;
 	ssaValue *p = NULL;
-	if (parent->kind == Entity_UsingVariable) {
+	if (parent->kind == Entity_Variable && parent->Variable.is_using) {
 		p = ssa_add_using_variable(proc, parent);
 	}
 
@@ -2432,7 +2443,7 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
 		ssaValue **found = map_get(&proc->module->values, hash_pointer(e));
 		if (found) {
 			v = *found;
-		} else if (e->kind == Entity_UsingVariable) {
+		} else if (e->kind == Entity_Variable && e->Variable.is_using) {
 			v = ssa_add_using_variable(proc, e);
 		}
 		if (v == NULL) {
@@ -2536,7 +2547,6 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
 
 		ssaValue *index = ssa_emit_conv(proc, ssa_build_expr(proc, ie->index), t_int);
 		v = ssa_emit_ptr_offset(proc, elem, index);
-		// gb_printf_err("HERE! %s -> %s\n", type_to_string(ssa_type(v)), expr_to_string(expr));
 		return ssa_make_addr(v, expr);
 	case_end;
 

+ 2 - 2
src/main.cpp

@@ -41,14 +41,14 @@ i32 win32_exec_command_line_app(char *fmt, ...) {
 }
 
 
-#if 1
+#if defined(DISPLAY_TIMING)
 #define INIT_TIMER() u64 start_time, end_time = 0, total_time = 0; start_time = gb_utc_time_now()
 #define PRINT_TIMER(section) do { \
 	u64 diff; \
 	end_time = gb_utc_time_now(); \
 	diff = end_time - start_time; \
 	total_time += diff; \
-	gb_printf_err("%s: %lld ms\n", section, diff/1000); \
+	gb_printf_err("%s: %.1f ms\n", section, diff/1000.0f); \
 	start_time = gb_utc_time_now(); \
 } while (0)
 

+ 3 - 0
src/parser.cpp

@@ -62,6 +62,7 @@ enum ProcTag {
 	ProcTag_foreign   = GB_BIT(0),
 	ProcTag_inline    = GB_BIT(1),
 	ProcTag_no_inline = GB_BIT(2),
+	ProcTag_pure      = GB_BIT(3),
 };
 
 enum VarDeclTag {
@@ -1157,6 +1158,8 @@ void parse_proc_tags(AstFile *f, u64 *tags, String *foreign_name) {
 			check_proc_add_tag(f, tag_expr, tags, ProcTag_inline, tag_name);
 		} else if (are_strings_equal(tag_name, make_string("no_inline"))) {
 			check_proc_add_tag(f, tag_expr, tags, ProcTag_no_inline, tag_name);
+		}  else if (are_strings_equal(tag_name, make_string("pure"))) {
+			check_proc_add_tag(f, tag_expr, tags, ProcTag_pure, tag_name);
 		} else {
 			ast_file_err(f, ast_node_token(tag_expr), "Unknown procedure tag");
 		}