Compiler segfault when modifying variable using an inline assembly block inside defer #2450.

This commit is contained in:
Christoffer Lerno
2025-09-12 20:01:28 +02:00
parent e6b10ee00c
commit 8fea6ee8ab
6 changed files with 97 additions and 46 deletions

View File

@@ -1000,6 +1000,7 @@ typedef struct
unsigned short index : 16;
AsmOffsetType offset_type : 6;
bool neg_offset : 1;
bool resolved : 1;
union
{
struct {

View File

@@ -18,6 +18,7 @@ static Decl *copy_decl(CopyStruct *c, Decl *decl);
static Decl **copy_decl_list(CopyStruct *c, Decl **decl_list);
static Methods *copy_decl_methods(CopyStruct *c, Methods *methods);
static TypeInfo *copy_type_info(CopyStruct *c, TypeInfo *source);
static void copy_expr_asm_arg(CopyStruct *c, ExprAsmArg *arg);
static inline void copy_reg_ref(CopyStruct *c, void *original, void *result)
{
@@ -464,20 +465,8 @@ Expr *copy_expr(CopyStruct *c, Expr *source_expr)
MACRO_COPY_EXPRID(expr->subscript_expr.index.expr);
return expr;
case EXPR_ASM:
switch (expr->expr_asm_arg.kind)
{
case ASM_ARG_REG:
case ASM_ARG_MEMADDR:
case ASM_ARG_REGVAR:
case ASM_ARG_INT:
case ASM_ARG_MEMVAR:
return expr;
case ASM_ARG_VALUE:
case ASM_ARG_ADDR:
MACRO_COPY_EXPRID(expr->expr_asm_arg.expr_id);
return expr;
}
UNREACHABLE
copy_expr_asm_arg(c, &expr->expr_asm_arg);
return expr;
case EXPR_CT_ASSIGNABLE:
MACRO_COPY_EXPRID(expr->assignable_expr.expr);
MACRO_COPY_EXPRID(expr->assignable_expr.type);
@@ -635,6 +624,41 @@ void doc_ast_copy(CopyStruct *c, AstContractStmt *doc)
}
}
static void copy_expr_asm_arg(CopyStruct *c, ExprAsmArg *arg)
{
switch (arg->kind)
{
case ASM_ARG_MEMADDR:
case ASM_ARG_REGVAR:
case ASM_ARG_MEMVAR:
if (arg->resolved) fixup_decl(c, &arg->ident.ident_decl);
return;
case ASM_ARG_REG:
case ASM_ARG_INT:
return;
case ASM_ARG_ADDR:
MACRO_COPY_EXPRID(arg->base);
MACRO_COPY_EXPRID(arg->idx);
return;
case ASM_ARG_VALUE:
MACRO_COPY_EXPRID(arg->expr_id);
return;
}
UNREACHABLE_VOID
}
static ExprAsmArg **copy_expr_asm_arg_list(CopyStruct *c, ExprAsmArg **args)
{
ExprAsmArg **new_args = NULL;
FOREACH(ExprAsmArg *, arg, args)
{
ExprAsmArg *new_arg = MALLOCS(ExprAsmArg);
*new_arg = *arg;
copy_expr_asm_arg(c, new_arg);
vec_add(new_args, new_arg);
}
return new_args;
}
Ast *ast_copy_deep(CopyStruct *c, Ast *source)
{
if (!source) return NULL;
@@ -681,6 +705,9 @@ RETRY:
*block = *ast->asm_block_stmt.block;
ast->asm_block_stmt.block = block;
MACRO_COPY_ASTID(block->asm_stmt);
MACRO_COPY_AST_LIST(block->labels);
block->input = copy_expr_asm_arg_list(c, block->input);
block->output_vars = copy_expr_asm_arg_list(c, block->output_vars);
}
break;
case AST_ASM_STMT:

View File

@@ -528,6 +528,7 @@ static inline bool sema_check_asm_arg_value(SemaContext *context, AsmInlineBlock
}
static inline bool sema_check_asm_arg(SemaContext *context, AsmInlineBlock *block, AsmInstruction *instr, AsmArgType arg_type, Expr *expr)
{
expr->expr_asm_arg.resolved = true;
switch (expr->expr_asm_arg.kind)
{
case ASM_ARG_INT:

View File

@@ -68,28 +68,33 @@ static void sema_trace_stmt_chain_liveness(AstId astid)
}
REMINDER("Optimize to ignore after return");
}
static void sema_trace_expr_asm_arg(ExprAsmArg *arg)
{
switch (arg->kind)
{
case ASM_ARG_ADDR:
sema_trace_exprid_liveness(arg->base);
sema_trace_exprid_liveness(arg->idx);
return;
case ASM_ARG_REG:
case ASM_ARG_INT:
return;
case ASM_ARG_MEMADDR:
case ASM_ARG_MEMVAR:
case ASM_ARG_REGVAR:
sema_trace_decl_liveness(arg->ident.ident_decl);
return;
case ASM_ARG_VALUE:
sema_trace_exprid_liveness(arg->expr_id);
return;
}
UNREACHABLE_VOID
}
static void sema_trace_asm_arg_list(ExprAsmArg **list)
{
FOREACH(ExprAsmArg *, asm_arg, list)
{
switch (asm_arg->kind)
{
case ASM_ARG_ADDR:
TODO
return;
case ASM_ARG_REG:
case ASM_ARG_INT:
continue;
case ASM_ARG_MEMADDR:
case ASM_ARG_MEMVAR:
case ASM_ARG_REGVAR:
sema_trace_decl_liveness(asm_arg->ident.ident_decl);
continue;
case ASM_ARG_VALUE:
sema_trace_exprid_liveness(asm_arg->expr_id);
continue;
}
UNREACHABLE_VOID
sema_trace_expr_asm_arg(asm_arg);
}
}
@@ -287,20 +292,8 @@ RETRY:
expr = expr->access_resolved_expr.parent;
goto RETRY;
case EXPR_ASM:
switch (expr->expr_asm_arg.kind)
{
case ASM_ARG_REG:
case ASM_ARG_MEMADDR:
case ASM_ARG_REGVAR:
case ASM_ARG_INT:
case ASM_ARG_MEMVAR:
return;
case ASM_ARG_VALUE:
case ASM_ARG_ADDR:
sema_trace_expr_liveness(exprptr(expr->expr_asm_arg.expr_id));
return;
}
UNREACHABLE_VOID
sema_trace_expr_asm_arg(&expr->expr_asm_arg);
return;
case EXPR_BINARY:
case EXPR_BITASSIGN:
sema_trace_expr_liveness(exprptr(expr->binary_expr.left));