Skip to content

Commit 42fb381

Browse files
author
Pascal Beyer
committed
Fix debug information for subscopes being very incorrect.
1 parent 034c7a5 commit 42fb381

File tree

6 files changed

+84
-50
lines changed

6 files changed

+84
-50
lines changed

src/ast.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -679,10 +679,9 @@ struct ast_scope{
679679
u32 amount_of_compound_types;
680680
u32 current_max_amount_of_compound_types;
681681

682-
// These are indices into the `function->line_information` array
683-
// and are used to determine which region of code holds which declarations.
684-
u32 start_line_index;
685-
u32 end_line_index;
682+
// These are offsets into the ir until code generation, then they are offsets into the function.
683+
u32 start_offset;
684+
u32 end_offset;
686685
};
687686

688687
static struct token *get_initializer_token(struct ast_declaration *decl){

src/coff_writer.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3146,7 +3146,7 @@ func void print_coff(struct string output_file_path, struct memory_arena *arena,
31463146

31473147
// vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
31483148

3149-
codeview_emit_debug_info_for_function(function, &module_stream, /*relocation_arena (used by obj_writer.c)*/null, /*debug_symbol_base (used by obj_writer.c)*/null, text_section_id);
3149+
codeview_emit_debug_info_for_function(function, &module_stream, /*relocation_arena (used by obj_writer.c)*/null, module_stream.base, text_section_id);
31503150

31513151
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
31523152

src/emit_x64.c

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2614,16 +2614,49 @@ void emit_code_for_function__internal(struct context *context, struct ast_functi
26142614
smm line_information_size = current_function->line_information.size;
26152615
smm line_information_at = 0;
26162616

2617+
// @cleanup: Is there a good way to fold that to the stuff below?
2618+
u32 **scope_offsets = push_data(&context->scratch, u32 *, 0);
2619+
for(struct ast_scope *scope = current_function->scope; scope; ){
2620+
*push_uninitialized_struct(&context->scratch, u32 *) = &scope->start_offset;
2621+
2622+
if(scope->subscopes.first){
2623+
scope = scope->subscopes.first;
2624+
}else{
2625+
while(1){
2626+
*push_uninitialized_struct(&context->scratch, u32 *) = &scope->end_offset;
2627+
if(scope->subscopes.next){
2628+
scope = scope->subscopes.next;
2629+
break;
2630+
}
2631+
2632+
if(scope->flags & SCOPE_FLAG_is_function_scope){
2633+
scope = null;
2634+
break;
2635+
}else{
2636+
scope = scope->parent;
2637+
}
2638+
}
2639+
}
2640+
}
2641+
smm amount_of_scopes = push_data(&context->scratch, u32 *, 0) - scope_offsets;
2642+
smm scope_at = 0;
2643+
26172644
for(u8 *ir_arena_at = current_function->start_in_ir_arena; ir_arena_at < current_function->end_in_ir_arena; ){
26182645
struct ir *ir = (struct ir *)ir_arena_at;
26192646

2620-
if((line_information_at < line_information_size) && (line_information[line_information_at].offset == (u32)(ir_arena_at - current_function->start_in_ir_arena))){
2647+
u32 current_offset = (u32)(ir_arena_at - current_function->start_in_ir_arena);
2648+
2649+
if((line_information_at < line_information_size) && (line_information[line_information_at].offset == current_offset)){
26212650
// :function_line_information
26222651
//
26232652
// Here we remap the offset from pointing into the ir_arena to pointing into the emit_pool.
26242653
line_information[line_information_at++].offset = to_s32(get_bytes_emitted(context));
26252654
}
26262655

2656+
while(scope_at < amount_of_scopes && *scope_offsets[scope_at] == current_offset){
2657+
*scope_offsets[scope_at++] = to_s32(get_bytes_emitted(context));
2658+
}
2659+
26272660
enum ir_kind ir_kind = ir->kind;
26282661

26292662
switch(ir_kind){
@@ -4701,6 +4734,14 @@ void emit_code_for_function__internal(struct context *context, struct ast_functi
47014734

47024735
assert_that_no_registers_are_allocated(context);
47034736

4737+
u32 ir_size = (u32)(current_function->end_in_ir_arena - current_function->start_in_ir_arena);
4738+
u32 asm_size = to_s32(get_bytes_emitted(context));
4739+
4740+
while(scope_at < amount_of_scopes){
4741+
assert(*scope_offsets[scope_at] == ir_size);
4742+
*scope_offsets[scope_at++] = asm_size;
4743+
}
4744+
47044745
assert(emit_location_stack_at == 0);
47054746

47064747
if(line_information_at < line_information_size){

src/main.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3412,6 +3412,8 @@ func void worker_parse_function(struct context *context, struct work_queue_entry
34123412

34133413
function->end_in_ir_arena = arena_current(&context->ir_arena);
34143414

3415+
scope->end_offset = (u32)(function->end_in_ir_arena - function->start_in_ir_arena);
3416+
34153417
context->current_function = null;
34163418
}
34173419

src/obj_writer.c

Lines changed: 18 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -709,35 +709,25 @@ struct debug_symbols_relocation_info{
709709

710710
void codeview_emit_debug_information_for_function__recursive(struct ast_function *function, struct memory_arena *arena, struct ast_scope *scope, struct memory_arena *relocation_arena, u8 *debug_symbols_base, u16 text_section_id, u32 parent_pointer){
711711

712+
struct codeview_block32{
713+
u16 length;
714+
u16 kind;
715+
u32 pointer_to_parent; // filled in by the linker
716+
u32 pointer_to_end; // filled in by the linker
717+
u32 scope_size;
718+
u32 offset_in_section;
719+
u16 section;
720+
} *block = null;
721+
712722
if(scope->amount_of_declarations){
713723

714724
if(function->scope != scope){
715-
struct codeview_block32{
716-
u16 length;
717-
u16 kind;
718-
u32 pointer_to_parent; // filled in by the linker
719-
u32 pointer_to_end; // filled in by the linker
720-
u32 scope_size;
721-
u32 offset_in_section;
722-
u16 section;
723-
} *block = push_struct(arena, struct codeview_block32);
725+
block = push_struct(arena, struct codeview_block32);
724726
block->length = sizeof(*block) - 2;
725727
block->kind = /*S_BLOCK32*/0x1103;
726728

727-
if(scope->start_line_index == -1){
728-
// Function is empty.
729-
block->scope_size = 0;
730-
block->offset_in_section = 0; // ?
731-
}else{
732-
733-
u32 start_offset = function->line_information.data[scope->start_line_index].offset;
734-
u32 end_offset = scope->end_line_index < function->line_information.size ? function->line_information.data[scope->end_line_index].offset : (u32)function->byte_size_without_prolog;
735-
736-
737-
// @cleanup: Does this correctly include function->size_of_prologue?
738-
block->scope_size = end_offset - start_offset;
739-
block->offset_in_section = start_offset; // relocated by relocation.
740-
}
729+
block->scope_size = scope->end_offset - scope->start_offset;
730+
block->offset_in_section = (u32)(scope->start_offset + function->size_of_prolog); // relocated by relocation.
741731

742732
block->section = 0; // filled in by relocation.
743733

@@ -750,7 +740,7 @@ void codeview_emit_debug_information_for_function__recursive(struct ast_function
750740
block->section = text_section_id;
751741
block->pointer_to_parent = parent_pointer;
752742

753-
parent_pointer = (u32)(arena_current(arena) - debug_symbols_base);
743+
parent_pointer = (u32)((u8 *)block - debug_symbols_base);
754744
}
755745
}
756746

@@ -808,6 +798,10 @@ void codeview_emit_debug_information_for_function__recursive(struct ast_function
808798
}
809799

810800
if(scope->amount_of_declarations && function->scope != scope){
801+
if(block && !relocation_arena){
802+
block->pointer_to_end = (u32)(arena_current(arena) - debug_symbols_base);
803+
}
804+
811805
*push_struct(arena, u16) = /*length*/2;
812806
*push_struct(arena, u16) = /*S_END*/6;
813807
}

src/parse.c

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -837,23 +837,22 @@ func void maybe_insert_cast_from_void_pointer(struct expr *lhs, struct expr *rhs
837837

838838
func struct ast_scope *parser_push_new_scope(struct context *context, struct token *token, enum scope_flags flags){
839839

840+
struct ast_scope *parent = context->current_scope;
841+
840842
struct ast_scope *scope = push_uninitialized_struct(context->arena, struct ast_scope);
841843
scope->flags = flags;
842844
scope->token = token;
845+
scope->start_offset = (u32)(arena_current(&context->ir_arena) - context->current_function->start_in_ir_arena); // kinda dumb, this is not true for function scopes. Maybe this function should not be called for function scopes.
846+
scope->parent = parent;
843847

844-
struct ast_scope *parent = context->current_scope;
845-
if(parent){
846-
if(parent->subscopes.last){ // @note: sll_push_back does not work because of the `subscopes` member.
847-
parent->subscopes.last->subscopes.next = scope;
848-
parent->subscopes.last = scope;
849-
}else{
850-
parent->subscopes.first = scope;
851-
parent->subscopes.last = scope;
852-
}
853-
parent->subscopes.count += 1;
854-
855-
scope->parent = parent;
848+
if(parent->subscopes.last){ // @note: sll_push_back does not work because of the `subscopes` member.
849+
parent->subscopes.last->subscopes.next = scope;
850+
parent->subscopes.last = scope;
851+
}else{
852+
parent->subscopes.first = scope;
853+
parent->subscopes.last = scope;
856854
}
855+
parent->subscopes.count += 1;
857856

858857
context->current_scope = scope;
859858

@@ -862,6 +861,7 @@ func struct ast_scope *parser_push_new_scope(struct context *context, struct tok
862861

863862
func void parser_scope_pop(struct context *context, struct ast_scope *scope){
864863
assert(context->current_scope == scope);
864+
scope->end_offset = (u32)(arena_current(&context->ir_arena) - context->current_function->start_in_ir_arena);
865865
context->current_scope = context->current_scope->parent;
866866
}
867867

@@ -8803,8 +8803,12 @@ func struct declaration_list parse_declaration_list(struct context *context, str
88038803
return ret;
88048804
}
88058805

8806-
scope = parser_push_new_scope(context, get_current_token(context), SCOPE_FLAG_is_function_scope);
8807-
parser_scope_pop(context, scope);
8806+
// @note: We don't want to use the general `parser_push_new_scope` function, as it is not designed for function scopes,
8807+
// and we would not want to add this scope to the scopes of the current function anyway (if it is local).
8808+
scope = push_struct(context->arena, struct ast_scope);
8809+
scope->flags = SCOPE_FLAG_is_function_scope;
8810+
scope->parent = context->current_scope;
8811+
scope->token = get_current_token(context);
88088812

88098813
ret.is_function_definition = scope;
88108814

@@ -9821,8 +9825,6 @@ func void parse_imperative_scope(struct context *context){
98219825
struct ast_scope *scope = context->current_scope;
98229826
assert(scope);
98239827

9824-
scope->start_line_index = (u32)context->current_function->line_information.size;
9825-
98269828
// Keep parsing inputs even after an error has occurred!
98279829
while(true){
98289830
// Statements only occur at function scope, so there should not be any sleeping.
@@ -9861,10 +9863,6 @@ func void parse_imperative_scope(struct context *context){
98619863
}
98629864
}
98639865

9864-
scope->end_line_index = (u32)context->current_function->line_information.size;
9865-
if(scope->start_line_index > scope->end_line_index){
9866-
scope->start_line_index = scope->end_line_index;
9867-
}
98689866
}
98699867

98709868
func struct declarator_return parse_declarator(struct context* context, struct ast_type *_initial_type, enum ast_kind *_initial_defined_type, enum declarator_kind_flags declarator_kind_flags){

0 commit comments

Comments
 (0)