Browse Source

Implement `assert` and `panic` in user side code
Removes 2 more built-in procedures!

Ginger Bill 8 years ago
parent
commit
04501c93fe
4 changed files with 57 additions and 114 deletions
  1. 23 15
      core/_preload.odin
  2. 0 27
      src/check_expr.cpp
  3. 1 5
      src/checker.cpp
  4. 33 67
      src/ir.cpp

+ 23 - 15
core/_preload.odin

@@ -187,12 +187,12 @@ type (
 
 
 type SourceCodeLocation struct {
 type SourceCodeLocation struct {
 	fully_pathed_filename: string,
 	fully_pathed_filename: string,
-	procedure:             string,
 	line, column:          i64,
 	line, column:          i64,
+	procedure:             string,
 }
 }
 
 
-proc make_source_code_location(file, procedure: string, line, column: i64) -> SourceCodeLocation {
-	return SourceCodeLocation{file, procedure, line, column};
+proc make_source_code_location(file: string, line, column: i64, procedure: string) -> SourceCodeLocation #inline {
+	return SourceCodeLocation{file, line, column, procedure};
 }
 }
 
 
 
 
@@ -305,9 +305,26 @@ proc default_allocator() -> Allocator {
 }
 }
 
 
 
 
+proc assert(condition: bool, message = "", using location = #caller_location) -> bool {
+	if !condition {
+		if len(message) > 0 {
+			fmt.printf("%s(%d:%d) Runtime assertion: %s\n", fully_pathed_filename, line, column, message);
+		} else {
+			fmt.printf("%s(%d:%d) Runtime assertion\n", fully_pathed_filename, line, column);
+		}
+		__debug_trap();
+	}
+	return condition;
+}
 
 
-
-
+proc panic(message = "", using location = #caller_location) {
+	if len(message) > 0 {
+		fmt.printf("%s(%d:%d) Panic: %s\n", fully_pathed_filename, line, column, message);
+	} else {
+		fmt.printf("%s(%d:%d) Panic\n", fully_pathed_filename, line, column);
+	}
+	__debug_trap();
+}
 
 
 
 
 
 
@@ -342,16 +359,7 @@ proc __complex64_ne (a, b: complex64)  -> bool #inline { return real(a) != real(
 proc __complex128_eq(a, b: complex128) -> bool #inline { return real(a) == real(b) && imag(a) == imag(b); }
 proc __complex128_eq(a, b: complex128) -> bool #inline { return real(a) == real(b) && imag(a) == imag(b); }
 proc __complex128_ne(a, b: complex128) -> bool #inline { return real(a) != real(b) || imag(a) != imag(b); }
 proc __complex128_ne(a, b: complex128) -> bool #inline { return real(a) != real(b) || imag(a) != imag(b); }
 
 
-proc __assert(file: string, line, column: int, msg: string) #inline {
-	fmt.fprintf(os.stderr, "%s(%d:%d) Runtime assertion: %s\n",
-	            file, line, column, msg);
-	__debug_trap();
-}
-proc __panic(file: string, line, column: int, msg: string) #inline {
-	fmt.fprintf(os.stderr, "%s(%d:%d) Panic: %s\n",
-	            file, line, column, msg);
-	__debug_trap();
-}
+
 proc __bounds_check_error(file: string, line, column: int, index, count: int) {
 proc __bounds_check_error(file: string, line, column: int, index, count: int) {
 	if 0 <= index && index < count {
 	if 0 <= index && index < count {
 		return;
 		return;

+ 0 - 27
src/check_expr.cpp

@@ -4144,33 +4144,6 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
 		operand->type = t_untyped_bool;
 		operand->type = t_untyped_bool;
 		break;
 		break;
 
 
-	case BuiltinProc_assert:
-		// proc assert(cond: bool) -> bool
-
-		if (!is_type_boolean(operand->type)) {
-			gbString str = expr_to_string(ce->args[0]);
-			error_node(call, "`%s` is not a boolean", str);
-			gb_string_free(str);
-			return false;
-		}
-
-		operand->mode = Addressing_Value;
-		operand->type = t_untyped_bool;
-		break;
-
-	case BuiltinProc_panic:
-		// proc panic(msg: string)
-
-		if (!is_type_string(operand->type)) {
-			gbString str = expr_to_string(ce->args[0]);
-			error_node(call, "`%s` is not a string", str);
-			gb_string_free(str);
-			return false;
-		}
-
-		operand->mode = Addressing_NoValue;
-		break;
-
 	case BuiltinProc_copy: {
 	case BuiltinProc_copy: {
 		// proc copy(x, y: []Type) -> int
 		// proc copy(x, y: []Type) -> int
 		Type *dest_type = NULL, *src_type = NULL;
 		Type *dest_type = NULL, *src_type = NULL;

+ 1 - 5
src/checker.cpp

@@ -43,8 +43,6 @@ enum BuiltinProcId {
 	BuiltinProc_type_info,
 	BuiltinProc_type_info,
 
 
 	BuiltinProc_compile_assert,
 	BuiltinProc_compile_assert,
-	BuiltinProc_assert,
-	BuiltinProc_panic,
 
 
 	BuiltinProc_copy,
 	BuiltinProc_copy,
 
 
@@ -65,7 +63,7 @@ enum BuiltinProcId {
 
 
 	BuiltinProc_transmute,
 	BuiltinProc_transmute,
 
 
-	BuiltinProc_DIRECTIVE,
+	BuiltinProc_DIRECTIVE, // NOTE(bill): This is used for specialized hash-prefixed procedures
 
 
 	BuiltinProc_COUNT,
 	BuiltinProc_COUNT,
 };
 };
@@ -91,8 +89,6 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = {
 	{STR_LIT("type_info"),        1, false, Expr_Expr},
 	{STR_LIT("type_info"),        1, false, Expr_Expr},
 
 
 	{STR_LIT("compile_assert"),   1, false, Expr_Expr},
 	{STR_LIT("compile_assert"),   1, false, Expr_Expr},
-	{STR_LIT("assert"),           1, false, Expr_Expr},
-	{STR_LIT("panic"),            1, false, Expr_Stmt},
 
 
 	{STR_LIT("copy"),             2, false, Expr_Expr},
 	{STR_LIT("copy"),             2, false, Expr_Expr},
 
 

+ 33 - 67
src/ir.cpp

@@ -19,15 +19,20 @@ struct irModule {
 	String layout;
 	String layout;
 	// String triple;
 	// String triple;
 
 
-	Map<Entity *>         min_dep_map; // Key: Entity *
-	Map<irValue *>        values;      // Key: Entity *
-	Map<irValue *>        members;     // Key: String
+	Map<Entity *>         min_dep_map;   // Key: Entity *
+	Map<irValue *>        values;        // Key: Entity *
+	Map<irValue *>        members;       // Key: String
 	Map<String>           entity_names;  // Key: Entity * of the typename
 	Map<String>           entity_names;  // Key: Entity * of the typename
-	Map<irDebugInfo *>    debug_info;  // Key: Unique pointer
+	Map<irDebugInfo *>    debug_info;    // Key: Unique pointer
 	i32                   global_string_index;
 	i32                   global_string_index;
 	i32                   global_array_index; // For ConstantSlice
 	i32                   global_array_index; // For ConstantSlice
 	i32                   global_generated_index;
 	i32                   global_generated_index;
 
 
+	// NOTE(bill): To prevent strings from being copied a lot
+	// Mainly used for file names
+	Map<irValue *>        const_strings; // Key: String
+
+
 	Entity *              entry_point_entity;
 	Entity *              entry_point_entity;
 
 
 	Array<irProcedure *>  procs;             // NOTE(bill): All procedures with bodies
 	Array<irProcedure *>  procs;             // NOTE(bill): All procedures with bodies
@@ -2686,6 +2691,19 @@ irValue *ir_add_local_slice(irProcedure *proc, Type *slice_type, irValue *base,
 
 
 
 
 
 
+irValue *ir_find_or_add_entity_string(irModule *m, String str) {
+	irValue **found = map_get(&m->const_strings, hash_string(str));
+	if (found != NULL) {
+		return *found;
+	}
+	irValue *v = ir_const_string(m->allocator, str);
+	map_set(&m->const_strings, hash_string(str), v);
+	return v;
+
+}
+
+
+
 String ir_lookup_polymorphic_field(CheckerInfo *info, Type *dst, Type *src) {
 String ir_lookup_polymorphic_field(CheckerInfo *info, Type *dst, Type *src) {
 	Type *prev_src = src;
 	Type *prev_src = src;
 	// Type *prev_dst = dst;
 	// Type *prev_dst = dst;
@@ -3212,7 +3230,7 @@ irValue *ir_emit_union_cast(irProcedure *proc, irValue *value, Type *type, Token
 		irValue **args = gb_alloc_array(a, irValue *, 6);
 		irValue **args = gb_alloc_array(a, irValue *, 6);
 		args[0] = ok;
 		args[0] = ok;
 
 
-		args[1] = ir_const_string(a, pos.file);
+		args[1] = ir_find_or_add_entity_string(proc->module, pos.file);
 		args[2] = ir_const_int(a, pos.line);
 		args[2] = ir_const_int(a, pos.line);
 		args[3] = ir_const_int(a, pos.column);
 		args[3] = ir_const_int(a, pos.column);
 
 
@@ -3266,7 +3284,7 @@ irAddr ir_emit_any_cast_addr(irProcedure *proc, irValue *value, Type *type, Toke
 		irValue **args = gb_alloc_array(a, irValue *, 6);
 		irValue **args = gb_alloc_array(a, irValue *, 6);
 		args[0] = ok;
 		args[0] = ok;
 
 
-		args[1] = ir_const_string(a, pos.file);
+		args[1] = ir_find_or_add_entity_string(proc->module, pos.file);
 		args[2] = ir_const_int(a, pos.line);
 		args[2] = ir_const_int(a, pos.line);
 		args[3] = ir_const_int(a, pos.column);
 		args[3] = ir_const_int(a, pos.column);
 
 
@@ -3629,13 +3647,14 @@ bool is_double_pointer(Type *t) {
 	return is_type_pointer(td);
 	return is_type_pointer(td);
 }
 }
 
 
+
 irValue *ir_emit_source_code_location(irProcedure *proc, String procedure, TokenPos pos) {
 irValue *ir_emit_source_code_location(irProcedure *proc, String procedure, TokenPos pos) {
 	gbAllocator a = proc->module->allocator;
 	gbAllocator a = proc->module->allocator;
 	irValue **args = gb_alloc_array(a, irValue *, 4);
 	irValue **args = gb_alloc_array(a, irValue *, 4);
-	args[0] = ir_const_string(a, pos.file);
-	args[1] = ir_const_string(a, procedure);
-	args[2] = ir_const_i64(a, pos.line);
-	args[3] = ir_const_i64(a, pos.column);
+	args[0] = ir_find_or_add_entity_string(proc->module, pos.file);
+	args[1] = ir_const_i64(a, pos.line);
+	args[2] = ir_const_i64(a, pos.column);
+	args[3] = ir_find_or_add_entity_string(proc->module, procedure);
 	return ir_emit_global_call(proc, "make_source_code_location", args, 4);
 	return ir_emit_global_call(proc, "make_source_code_location", args, 4);
 }
 }
 
 
@@ -4107,62 +4126,6 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
 		return ir_emit_global_call(proc, "__dynamic_map_delete", args, 2);
 		return ir_emit_global_call(proc, "__dynamic_map_delete", args, 2);
 	} break;
 	} break;
 
 
-
-	case BuiltinProc_assert: {
-		ir_emit_comment(proc, str_lit("assert"));
-		irValue *cond = ir_build_expr(proc, ce->args[0]);
-		GB_ASSERT(is_type_boolean(ir_type(cond)));
-
-		cond = ir_emit_comp(proc, Token_CmpEq, cond, v_false);
-		irBlock *err  = ir_new_block(proc, NULL, "builtin.assert.err");
-		irBlock *done = ir_new_block(proc, NULL, "builtin.assert.done");
-
-		ir_emit_if(proc, cond, err, done);
-		ir_start_block(proc, err);
-
-		// TODO(bill): Cleanup allocations here
-		Token token = ast_node_token(ce->args[0]);
-		TokenPos pos = token.pos;
-		gbString expr = expr_to_string(ce->args[0]);
-		isize expr_len = gb_string_length(expr);
-		String expr_str = {};
-		expr_str.text = cast(u8 *)gb_alloc_copy_align(proc->module->allocator, expr, expr_len, 1);
-		expr_str.len = expr_len;
-		gb_string_free(expr);
-
-
-		irValue **args = gb_alloc_array(proc->module->allocator, irValue *, 4);
-		args[0] = ir_const_string(proc->module->allocator, pos.file);
-		args[1] = ir_const_int(proc->module->allocator, pos.line);
-		args[2] = ir_const_int(proc->module->allocator, pos.column);
-		args[3] = ir_const_string(proc->module->allocator, expr_str);
-		ir_emit_global_call(proc, "__assert", args, 4);
-
-		ir_emit_jump(proc, done);
-		ir_start_block(proc, done);
-
-		return cond;
-	} break;
-
-	case BuiltinProc_panic: {
-		ir_emit_comment(proc, str_lit("panic"));
-		irValue *msg = ir_build_expr(proc, ce->args[0]);
-		GB_ASSERT(is_type_string(ir_type(msg)));
-
-		Token token = ast_node_token(ce->args[0]);
-		TokenPos pos = token.pos;
-
-		irValue **args = gb_alloc_array(proc->module->allocator, irValue *, 4);
-		args[0] = ir_const_string(proc->module->allocator, pos.file);
-		args[1] = ir_const_int(proc->module->allocator, pos.line);
-		args[2] = ir_const_int(proc->module->allocator, pos.column);
-		args[3] = msg;
-		ir_emit_global_call(proc, "__panic", args, 4);
-
-		return NULL;
-	} break;
-
-
 	case BuiltinProc_copy: {
 	case BuiltinProc_copy: {
 		ir_emit_comment(proc, str_lit("copy"));
 		ir_emit_comment(proc, str_lit("copy"));
 		// proc copy(dst, src: []Type) -> int
 		// proc copy(dst, src: []Type) -> int
@@ -5318,7 +5281,8 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
 						elem = fv->value;
 						elem = fv->value;
 					} else {
 					} else {
 						TypeAndValue tav = type_and_value_of_expr(proc->module->info, elem);
 						TypeAndValue tav = type_and_value_of_expr(proc->module->info, elem);
-						Selection sel = lookup_field_from_index(proc->module->allocator, bt, st->fields_in_src_order[field_index]->Variable.field_index);
+						Selection sel = lookup_field_from_index(proc->module->allocator, bt,
+						                                        st->fields_in_src_order[field_index]->Variable.field_src_index);
 						index = sel.index[0];
 						index = sel.index[0];
 					}
 					}
 
 
@@ -6966,6 +6930,7 @@ void ir_init_module(irModule *m, Checker *c) {
 	array_init(&m->procs,    heap_allocator());
 	array_init(&m->procs,    heap_allocator());
 	array_init(&m->procs_to_generate, heap_allocator());
 	array_init(&m->procs_to_generate, heap_allocator());
 	array_init(&m->foreign_library_paths, heap_allocator());
 	array_init(&m->foreign_library_paths, heap_allocator());
+	map_init(&m->const_strings, heap_allocator());
 
 
 	// Default states
 	// Default states
 	m->stmt_state_flags = 0;
 	m->stmt_state_flags = 0;
@@ -7077,6 +7042,7 @@ void ir_destroy_module(irModule *m) {
 	map_destroy(&m->members);
 	map_destroy(&m->members);
 	map_destroy(&m->entity_names);
 	map_destroy(&m->entity_names);
 	map_destroy(&m->debug_info);
 	map_destroy(&m->debug_info);
+	map_destroy(&m->const_strings);
 	array_free(&m->procs);
 	array_free(&m->procs);
 	array_free(&m->procs_to_generate);
 	array_free(&m->procs_to_generate);
 	array_free(&m->foreign_library_paths);
 	array_free(&m->foreign_library_paths);