mirror of
https://github.com/Ed94/Odin.git
synced 2026-06-26 23:44:58 -07:00
Add basic debug information needed for stepping over code
This commit is contained in:
+35
-23
@@ -59,7 +59,7 @@ struct irDomNode {
|
||||
struct irBlock {
|
||||
i32 index;
|
||||
String label;
|
||||
irProcedure *parent;
|
||||
irProcedure *proc;
|
||||
AstNode * node; // Can be nullptr
|
||||
Scope * scope;
|
||||
isize scope_index;
|
||||
@@ -114,11 +114,6 @@ struct irDebugLocation {
|
||||
irDebugInfo *debug_scope;
|
||||
};
|
||||
|
||||
struct irDebugScope {
|
||||
irDebugScope * parent;
|
||||
irDebugLocation loc;
|
||||
};
|
||||
|
||||
struct irProcedure {
|
||||
irProcedure * parent;
|
||||
Array<irProcedure *> children;
|
||||
@@ -319,7 +314,7 @@ String const ir_conv_strings[] = {
|
||||
struct irInstr {
|
||||
irInstrKind kind;
|
||||
|
||||
irBlock *parent;
|
||||
irBlock *block;
|
||||
Type *type;
|
||||
|
||||
union {
|
||||
@@ -743,9 +738,9 @@ void ir_add_edge(irBlock *from, irBlock *to) {
|
||||
}
|
||||
}
|
||||
|
||||
void ir_set_instr_parent(irValue *instr, irBlock *parent) {
|
||||
void ir_set_instr_block(irValue *instr, irBlock *block) {
|
||||
if (instr->kind == irValue_Instr) {
|
||||
instr->Instr.parent = parent;
|
||||
instr->Instr.block = block;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -783,7 +778,7 @@ Array<irValue *> *ir_value_referrers(irValue *v) {
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
void ir_module_add_value (irModule *m, Entity *e, irValue *v);
|
||||
irValue *ir_emit_zero_init (irProcedure *p, irValue *address);
|
||||
irValue *ir_emit_zero_init (irProcedure *p, irValue *address, AstNode *expr);
|
||||
irValue *ir_emit_comment (irProcedure *p, String text);
|
||||
irValue *ir_emit_store (irProcedure *p, irValue *address, irValue *value);
|
||||
irValue *ir_emit_load (irProcedure *p, irValue *address);
|
||||
@@ -1134,7 +1129,7 @@ irValue *ir_value_constant_slice(gbAllocator a, Type *type, irValue *backing_arr
|
||||
irValue *ir_emit(irProcedure *proc, irValue *instr) {
|
||||
GB_ASSERT(instr->kind == irValue_Instr);
|
||||
irBlock *b = proc->curr_block;
|
||||
instr->Instr.parent = b;
|
||||
instr->Instr.block = b;
|
||||
if (b != nullptr) {
|
||||
irInstr *i = ir_get_last_instr(b);
|
||||
if (!ir_is_instr_terminating(i)) {
|
||||
@@ -1230,7 +1225,7 @@ irBlock *ir_new_block(irProcedure *proc, AstNode *node, char *label) {
|
||||
v->Block.label = make_string_c(label);
|
||||
v->Block.node = node;
|
||||
v->Block.scope = scope;
|
||||
v->Block.parent = proc;
|
||||
v->Block.proc = proc;
|
||||
// TODO(bill): Is this correct or even needed?
|
||||
v->Block.scope_index = proc->scope_index;
|
||||
|
||||
@@ -1356,13 +1351,13 @@ irValue *ir_add_global_string_array(irModule *m, String string) {
|
||||
irValue *ir_add_local(irProcedure *proc, Entity *e, AstNode *expr, bool zero_initialized) {
|
||||
irBlock *b = proc->decl_block; // all variables must be in the first block
|
||||
irValue *instr = ir_instr_local(proc, e, true);
|
||||
instr->Instr.parent = b;
|
||||
instr->Instr.block = b;
|
||||
array_add(&b->instrs, instr);
|
||||
array_add(&b->locals, instr);
|
||||
proc->local_count++;
|
||||
|
||||
if (zero_initialized) {
|
||||
ir_emit_zero_init(proc, instr);
|
||||
ir_emit_zero_init(proc, instr, expr);
|
||||
}
|
||||
|
||||
if (expr != nullptr && proc->entity != nullptr) {
|
||||
@@ -1539,7 +1534,7 @@ irDebugInfo *ir_add_debug_info_proc(irProcedure *proc, Entity *entity, String na
|
||||
//
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
irValue *ir_emit_global_call(irProcedure *proc, char const *name_, irValue **args, isize arg_count);
|
||||
irValue *ir_emit_global_call(irProcedure *proc, char const *name_, irValue **args, isize arg_count, AstNode *expr = nullptr);
|
||||
|
||||
irValue *ir_emit_store(irProcedure *p, irValue *address, irValue *value) {
|
||||
Type *a = type_deref(ir_type(address));
|
||||
@@ -1567,13 +1562,20 @@ irValue *ir_emit_select(irProcedure *p, irValue *cond, irValue *t, irValue *f) {
|
||||
return ir_emit(p, ir_instr_select(p, cond, t, f));
|
||||
}
|
||||
|
||||
irValue *ir_emit_zero_init(irProcedure *p, irValue *address) {
|
||||
void ir_add_debug_location_to_value(irProcedure *proc, irValue *v, AstNode *e) {
|
||||
if (v != nullptr && e != nullptr) {
|
||||
v->loc.debug_scope = proc->debug_scope;
|
||||
v->loc.pos = ast_node_token(e).pos;
|
||||
}
|
||||
}
|
||||
|
||||
irValue *ir_emit_zero_init(irProcedure *p, irValue *address, AstNode *expr) {
|
||||
gbAllocator a = p->module->allocator;
|
||||
Type *t = type_deref(ir_type(address));
|
||||
irValue **args = gb_alloc_array(a, irValue *, 2);
|
||||
args[0] = ir_emit_conv(p, address, t_rawptr);
|
||||
args[1] = ir_const_int(a, type_size_of(a, t));
|
||||
return ir_emit_global_call(p, "__mem_zero", args, 2);
|
||||
return ir_emit_global_call(p, "__mem_zero", args, 2, expr);
|
||||
// return ir_emit(p, ir_instr_zero_init(p, address));
|
||||
}
|
||||
|
||||
@@ -1668,12 +1670,14 @@ irValue *ir_emit_call(irProcedure *p, irValue *value, irValue **args, isize arg_
|
||||
return result;
|
||||
}
|
||||
|
||||
irValue *ir_emit_global_call(irProcedure *proc, char const *name_, irValue **args, isize arg_count) {
|
||||
irValue *ir_emit_global_call(irProcedure *proc, char const *name_, irValue **args, isize arg_count, AstNode *expr) {
|
||||
String name = make_string_c(cast(char *)name_);
|
||||
irValue **found = map_get(&proc->module->members, hash_string(name));
|
||||
GB_ASSERT_MSG(found != nullptr, "%.*s", LIT(name));
|
||||
irValue *gp = *found;
|
||||
return ir_emit_call(proc, gp, args, arg_count);
|
||||
irValue *call = ir_emit_call(proc, gp, args, arg_count);
|
||||
ir_add_debug_location_to_value(proc, call, expr);
|
||||
return call;
|
||||
}
|
||||
|
||||
|
||||
@@ -4033,7 +4037,7 @@ void ir_emit_increment(irProcedure *proc, irValue *addr) {
|
||||
|
||||
}
|
||||
|
||||
void ir_init_data_with_defaults(irProcedure *proc, irValue *ptr, irValue *count) {
|
||||
void ir_init_data_with_defaults(irProcedure *proc, irValue *ptr, irValue *count, AstNode *expr) {
|
||||
Type *elem_type = type_deref(ir_type(ptr));
|
||||
GB_ASSERT(is_type_struct(elem_type) || is_type_array(elem_type));
|
||||
|
||||
@@ -4056,7 +4060,7 @@ void ir_init_data_with_defaults(irProcedure *proc, irValue *ptr, irValue *count)
|
||||
ir_start_block(proc, body);
|
||||
|
||||
irValue *offset_ptr = ir_emit_ptr_offset(proc, ptr, ir_emit_load(proc, index));
|
||||
ir_emit_zero_init(proc, offset_ptr);
|
||||
ir_emit_zero_init(proc, offset_ptr, expr);
|
||||
|
||||
ir_emit_increment(proc, index);
|
||||
|
||||
@@ -4229,7 +4233,7 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
|
||||
irValue *ptr = ir_emit_conv(proc, call, elem_ptr_type);
|
||||
|
||||
if (ir_type_has_default_values(elem_type)) {
|
||||
ir_init_data_with_defaults(proc, ptr, len);
|
||||
ir_init_data_with_defaults(proc, ptr, len, expr);
|
||||
}
|
||||
|
||||
irValue *slice = ir_add_local_generated(proc, type);
|
||||
@@ -4278,7 +4282,7 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
|
||||
ir_emit_global_call(proc, "__dynamic_array_make", args, 6);
|
||||
|
||||
if (ir_type_has_default_values(elem_type)) {
|
||||
ir_init_data_with_defaults(proc, ir_dynamic_array_elem(proc, ir_emit_load(proc, array)), len);
|
||||
ir_init_data_with_defaults(proc, ir_dynamic_array_elem(proc, ir_emit_load(proc, array)), len, expr);
|
||||
}
|
||||
|
||||
return ir_emit_load(proc, array);
|
||||
@@ -4708,7 +4712,15 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
irValue *ir_build_expr_internal(irProcedure *proc, AstNode *expr);
|
||||
|
||||
irValue *ir_build_expr(irProcedure *proc, AstNode *expr) {
|
||||
irValue *v = ir_build_expr_internal(proc, expr);
|
||||
ir_add_debug_location_to_value(proc, v, expr);
|
||||
return v;
|
||||
}
|
||||
|
||||
irValue *ir_build_expr_internal(irProcedure *proc, AstNode *expr) {
|
||||
expr = unparen_expr(expr);
|
||||
|
||||
TypeAndValue tv = type_and_value_of_expr(proc->module->info, expr);
|
||||
|
||||
+1
-1
@@ -232,7 +232,7 @@ bool ir_opt_block_fusion(irProcedure *proc, irBlock *a) {
|
||||
array_pop(&a->instrs); // Remove branch at end
|
||||
for_array(i, b->instrs) {
|
||||
array_add(&a->instrs, b->instrs[i]);
|
||||
ir_set_instr_parent(b->instrs[i], a);
|
||||
ir_set_instr_block(b->instrs[i], a);
|
||||
}
|
||||
|
||||
array_clear(&a->succs);
|
||||
|
||||
+44
-24
@@ -193,6 +193,33 @@ void ir_print_encoded_global(irFileBuffer *f, String name, bool remove_prefix) {
|
||||
ir_print_escape_string(f, name, true, !remove_prefix);
|
||||
}
|
||||
|
||||
|
||||
bool ir_print_debug_location(irFileBuffer *f, irModule *m, irValue *v, irProcedure *proc = nullptr) {
|
||||
#if 1
|
||||
if (m->generate_debug_info && v != nullptr) {
|
||||
TokenPos pos = v->loc.pos;
|
||||
irDebugInfo *scope = v->loc.debug_scope;
|
||||
i32 id = 0;
|
||||
if (scope != nullptr) {
|
||||
id = scope->id;
|
||||
} else if (proc != nullptr) {
|
||||
if (proc->debug_scope != nullptr) {
|
||||
id = proc->debug_scope->id;
|
||||
pos = proc->entity->token.pos;
|
||||
}
|
||||
}
|
||||
if (id > 0 && pos.line > 0) {
|
||||
ir_fprintf(f, ", !dbg !DILocation(line: %td, column: %td, scope: !%d)", pos.line, pos.column, id);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void ir_print_type(irFileBuffer *f, irModule *m, Type *t, bool in_struct = false);
|
||||
void ir_print_value(irFileBuffer *f, irModule *m, irValue *value, Type *type_hint);
|
||||
|
||||
@@ -964,6 +991,7 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
|
||||
ir_print_type(f, m, type);
|
||||
ir_write_string(f, "* ");
|
||||
ir_print_value(f, m, instr->Store.address, type);
|
||||
ir_print_debug_location(f, m, value);
|
||||
ir_write_byte(f, '\n');
|
||||
break;
|
||||
}
|
||||
@@ -976,7 +1004,9 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
|
||||
ir_print_type(f, m, type);
|
||||
ir_write_string(f, "* ");
|
||||
ir_print_value(f, m, instr->Load.address, type);
|
||||
ir_fprintf(f, ", align %lld\n", type_align_of(m->allocator, type));
|
||||
ir_fprintf(f, ", align %lld", type_align_of(m->allocator, type));
|
||||
ir_print_debug_location(f, m, value);
|
||||
ir_write_byte(f, '\n');
|
||||
break;
|
||||
}
|
||||
case irInstr_ArrayElementPtr: {
|
||||
@@ -1060,9 +1090,9 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
|
||||
|
||||
irValue *edge = instr->Phi.edges[i];
|
||||
irBlock *block = nullptr;
|
||||
if (instr->parent != nullptr &&
|
||||
i < instr->parent->preds.count) {
|
||||
block = instr->parent->preds[i];
|
||||
if (instr->block != nullptr &&
|
||||
i < instr->block->preds.count) {
|
||||
block = instr->block->preds[i];
|
||||
}
|
||||
|
||||
ir_write_string(f, "[ ");
|
||||
@@ -1131,6 +1161,7 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
|
||||
case irInstr_Jump: {;
|
||||
ir_write_string(f, "br label %");
|
||||
ir_print_block_name(f, instr->Jump.block);
|
||||
ir_print_debug_location(f, m, value);
|
||||
ir_write_byte(f, '\n');
|
||||
break;
|
||||
}
|
||||
@@ -1142,6 +1173,7 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
|
||||
ir_write_string(f, ", ");
|
||||
ir_write_string(f, "label %"); ir_print_block_name(f, instr->If.true_block);
|
||||
ir_write_string(f, ", label %"); ir_print_block_name(f, instr->If.false_block);
|
||||
ir_print_debug_location(f, m, value);
|
||||
ir_write_byte(f, '\n');
|
||||
break;
|
||||
}
|
||||
@@ -1157,7 +1189,7 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
|
||||
ir_write_byte(f, ' ');
|
||||
ir_print_value(f, m, ret->value, t);
|
||||
}
|
||||
|
||||
ir_print_debug_location(f, m, value);
|
||||
ir_write_byte(f, '\n');
|
||||
|
||||
break;
|
||||
@@ -1171,6 +1203,7 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
|
||||
ir_print_value(f, m, c->value, c->from);
|
||||
ir_write_string(f, " to ");
|
||||
ir_print_type(f, m, c->to);
|
||||
ir_print_debug_location(f, m, value);
|
||||
ir_write_byte(f, '\n');
|
||||
|
||||
break;
|
||||
@@ -1224,6 +1257,7 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
|
||||
}
|
||||
ir_write_string(f, str_lit(", "));
|
||||
ir_print_value(f, m, uo->expr, type);
|
||||
ir_print_debug_location(f, m, value);
|
||||
ir_write_byte(f, '\n');
|
||||
break;
|
||||
}
|
||||
@@ -1313,6 +1347,8 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
|
||||
ir_print_value(f, m, bo->left, type);
|
||||
ir_write_string(f, str_lit(", "));
|
||||
ir_print_value(f, m, bo->right, type);
|
||||
|
||||
ir_print_debug_location(f, m, value);
|
||||
ir_write_byte(f, '\n');
|
||||
break;
|
||||
}
|
||||
@@ -1417,25 +1453,7 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
|
||||
}
|
||||
ir_write_string(f, ")");
|
||||
|
||||
if (m->generate_debug_info) {
|
||||
TokenPos pos = value->loc.pos;
|
||||
irDebugInfo *scope = value->loc.debug_scope;
|
||||
i32 id = 0;
|
||||
irProcedure *proc = instr->parent->parent;
|
||||
if (scope != nullptr) {
|
||||
id = scope->id;
|
||||
} else if (proc->debug_scope != nullptr) {
|
||||
id = proc->debug_scope->id;
|
||||
}
|
||||
if (proc->entity != nullptr) {
|
||||
pos = proc->entity->token.pos;
|
||||
}
|
||||
|
||||
if (id > 0) {
|
||||
ir_fprintf(f, ", !dbg !DILocation(line: %td, column: %td, scope: !%d)", pos.line, pos.column, id);
|
||||
}
|
||||
}
|
||||
|
||||
ir_print_debug_location(f, m, value, instr->block->proc);
|
||||
ir_write_string(f, "\n");
|
||||
|
||||
break;
|
||||
@@ -1452,6 +1470,7 @@ void ir_print_instr(irFileBuffer *f, irModule *m, irValue *value) {
|
||||
ir_print_type(f, m, ir_type(instr->Select.false_value));
|
||||
ir_write_byte(f, ' ');
|
||||
ir_print_value(f, m, instr->Select.false_value, ir_type(instr->Select.false_value));
|
||||
ir_print_debug_location(f, m, value);
|
||||
ir_write_byte(f, '\n');
|
||||
break;
|
||||
}
|
||||
@@ -1809,6 +1828,7 @@ void ir_print_type_name(irFileBuffer *f, irModule *m, irValue *v) {
|
||||
|
||||
void print_llvm_ir(irGen *ir) {
|
||||
irModule *m = &ir->module;
|
||||
|
||||
irFileBuffer buf = {}, *f = &buf;
|
||||
ir_file_buffer_init(f, &ir->output_file);
|
||||
defer (ir_file_buffer_destroy(f));
|
||||
|
||||
Reference in New Issue
Block a user