mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-04 14:48:47 +00:00
Implement assert and panic in user side code
Removes 2 more built-in procedures!
This commit is contained in:
+23
-15
@@ -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 {
|
proc make_source_code_location(file: string, line, column: i64, procedure: string) -> SourceCodeLocation #inline {
|
||||||
return SourceCodeLocation{file, procedure, line, column};
|
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;
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -19,15 +19,20 @@ struct irModule {
|
|||||||
String layout;
|
String layout;
|
||||||
// String triple;
|
// String triple;
|
||||||
|
|
||||||
Map<Entity *> min_dep_map; // Key: Entity *
|
Map<Entity *> min_dep_map; // Key: Entity *
|
||||||
Map<irValue *> values; // Key: Entity *
|
Map<irValue *> values; // Key: Entity *
|
||||||
Map<irValue *> members; // Key: String
|
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[0] = ir_find_or_add_entity_string(proc->module, pos.file);
|
||||||
args[1] = ir_const_string(a, procedure);
|
args[1] = ir_const_i64(a, pos.line);
|
||||||
args[2] = ir_const_i64(a, pos.line);
|
args[2] = ir_const_i64(a, pos.column);
|
||||||
args[3] = 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);
|
||||||
|
|||||||
Reference in New Issue
Block a user