Improved debug information on defer.

This commit is contained in:
Christoffer Lerno
2024-06-06 17:40:07 +02:00
parent f7e7e16c25
commit edd0a4022b
4 changed files with 29 additions and 11 deletions

View File

@@ -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;

View File

@@ -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);

View File

@@ -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:

View File

@@ -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;