From edd0a4022ba86f2ddbccdd3dcc05e22aab4b5bc3 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Thu, 6 Jun 2024 17:40:07 +0200 Subject: [PATCH] Improved debug information on defer. --- src/compiler/compiler_internal.h | 2 ++ src/compiler/copying.c | 1 + src/compiler/llvm_codegen_stmt.c | 10 ++++++++++ src/compiler/sema_stmts.c | 27 ++++++++++++++++----------- 4 files changed, 29 insertions(+), 11 deletions(-) diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index 7679d326e..2eb78c097 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -1213,6 +1213,7 @@ static_assert(sizeof(Expr) == 56, "Expr not expected size"); typedef struct { AstId first_stmt; + AstId parent_defer; } AstCompoundStmt; @@ -1338,6 +1339,7 @@ typedef struct { AstId prev_defer; AstId body; // Compound statement + void *scope; bool is_try : 1; bool is_catch : 1; } AstDeferStmt; diff --git a/src/compiler/copying.c b/src/compiler/copying.c index af78a842c..35d0f5903 100644 --- a/src/compiler/copying.c +++ b/src/compiler/copying.c @@ -625,6 +625,7 @@ RETRY: break; case AST_COMPOUND_STMT: MACRO_COPY_ASTID(ast->compound_stmt.first_stmt); + fixup_astid(c, &ast->compound_stmt.parent_defer); break; case AST_CT_IF_STMT: MACRO_COPY_EXPR(ast->ct_if_stmt.expr); diff --git a/src/compiler/llvm_codegen_stmt.c b/src/compiler/llvm_codegen_stmt.c index e10325643..46767d9c6 100644 --- a/src/compiler/llvm_codegen_stmt.c +++ b/src/compiler/llvm_codegen_stmt.c @@ -11,6 +11,13 @@ void llvm_emit_compound_stmt(GenContext *c, Ast *ast) { assert(ast->ast_kind == AST_COMPOUND_STMT); + DebugScope *old_block = NULL; + if (ast->compound_stmt.parent_defer && llvm_use_debug(c)) + { + old_block = c->debug.block_stack; + assert(ast->compound_stmt.parent_defer); + c->debug.block_stack = astptr(ast->compound_stmt.parent_defer)->defer_stmt.scope; + } // Push the lexical scope if in debug. DEBUG_PUSH_LEXICAL_SCOPE(c, ast->span); @@ -19,6 +26,7 @@ void llvm_emit_compound_stmt(GenContext *c, Ast *ast) // Pop lexical scope. DEBUG_POP_LEXICAL_SCOPE(c); + if (old_block) c->debug.block_stack = old_block; } void llvm_emit_local_static(GenContext *c, Decl *decl, BEValue *value) @@ -1616,6 +1624,8 @@ void llvm_emit_stmt(GenContext *c, Ast *ast) gencontext_emit_next_stmt(c, ast); break; case AST_DEFER_STMT: + if (llvm_use_debug(c)) ast->defer_stmt.scope = c->debug.block_stack; + break; case AST_NOP_STMT: break; case AST_ASM_BLOCK_STMT: diff --git a/src/compiler/sema_stmts.c b/src/compiler/sema_stmts.c index 761b7baf3..7ef5be45c 100644 --- a/src/compiler/sema_stmts.c +++ b/src/compiler/sema_stmts.c @@ -26,7 +26,7 @@ static inline bool sema_analyse_switch_stmt(SemaContext *context, Ast *statement static inline bool sema_return_optional_check_is_valid_in_scope(SemaContext *context, Expr *ret_expr); static inline bool sema_defer_by_result(AstId defer_top, AstId defer_bottom); static inline bool sema_analyse_block_exit_stmt(SemaContext *context, Ast *statement); -static inline bool sema_analyse_defer_stmt_body(SemaContext *context, Ast *statement, Ast *body); +static inline bool sema_analyse_defer_stmt_body(SemaContext *context, Ast *statement); static inline bool sema_analyse_for_cond(SemaContext *context, ExprId *cond_ref, bool *infinite); static inline bool assert_create_from_contract(SemaContext *context, Ast *directive, AstId **asserts, SourceSpan evaluation_location); static bool sema_analyse_asm_string_stmt(SemaContext *context, Ast *stmt); @@ -1241,13 +1241,21 @@ static inline bool sema_analyse_expr_stmt(SemaContext *context, Ast *statement) return true; } -bool sema_analyse_defer_stmt_body(SemaContext *context, Ast *statement, Ast *body) +bool sema_analyse_defer_stmt_body(SemaContext *context, Ast *statement) { + Ast *body = astptr(statement->defer_stmt.body); if (body->ast_kind == AST_DEFER_STMT) { - SEMA_ERROR(body, "A defer may not have a body consisting of a raw 'defer', this looks like a mistake."); - return false; + RETURN_SEMA_ERROR(body, "A defer may not have a body consisting of a raw 'defer', this looks like a mistake."); } + if (body->ast_kind != AST_COMPOUND_STMT) + { + Ast *new_body = new_ast(AST_COMPOUND_STMT, body->span); + new_body->compound_stmt.first_stmt = astid(body); + body = new_body; + statement->defer_stmt.body = astid(body); + } + body->compound_stmt.parent_defer = astid(statement); bool success = true; SCOPE_START @@ -1276,7 +1284,7 @@ bool sema_analyse_defer_stmt_body(SemaContext *context, Ast *statement, Ast *bod static inline bool sema_analyse_defer_stmt(SemaContext *context, Ast *statement) { - if (!sema_analyse_defer_stmt_body(context, statement, astptr(statement->defer_stmt.body))) return false; + if (!sema_analyse_defer_stmt_body(context, statement)) return false; statement->defer_stmt.prev_defer = context->active_scope.defer_last; context->active_scope.defer_last = astid(statement); @@ -1328,14 +1336,12 @@ static inline bool sema_analyse_for_stmt(SemaContext *context, Ast *statement) assert(body); if (body->ast_kind == AST_DEFER_STMT) { - SEMA_ERROR(body, "Looping over a raw 'defer' is not allowed, was this a mistake?"); - return false; + RETURN_SEMA_ERROR(body, "Looping over a raw 'defer' is not allowed, was this a mistake?"); } bool do_loop = statement->for_stmt.flow.skip_first; if (body->ast_kind != AST_COMPOUND_STMT && do_loop) { - SEMA_ERROR(body, "A do loop must use { } around its body."); - return false; + RETURN_SEMA_ERROR(body, "A do loop must use { } around its body."); } // Enter for scope SCOPE_OUTER_START @@ -1825,8 +1831,7 @@ static inline bool sema_analyse_if_stmt(SemaContext *context, Ast *statement) Ast *then = astptr(statement->if_stmt.then_body); if (then->ast_kind == AST_DEFER_STMT) { - SEMA_ERROR(then, "An 'if' statement may not be followed by a raw 'defer' statement, this looks like a mistake."); - return false; + RETURN_SEMA_ERROR(then, "An 'if' statement may not be followed by a raw 'defer' statement, this looks like a mistake."); } AstId else_id = statement->if_stmt.else_body; Ast *else_body = else_id ? astptr(else_id) : NULL;