mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Compiler segfault when modifying variable using an inline assembly block inside defer #2450.
This commit is contained in:
@@ -21,6 +21,7 @@
|
||||
- Compiler hang with unaligned load-store pair. #2470
|
||||
- `??` with void results on both sides cause a compiler crash #2472.
|
||||
- Stack object size limit error on a static object. #2476
|
||||
- Compiler segfault when modifying variable using an inline assembly block inside defer #2450.
|
||||
|
||||
### Stdlib changes
|
||||
- Added generic `InterfaceList` to store a list of values that implement a specific interface
|
||||
|
||||
@@ -1000,6 +1000,7 @@ typedef struct
|
||||
unsigned short index : 16;
|
||||
AsmOffsetType offset_type : 6;
|
||||
bool neg_offset : 1;
|
||||
bool resolved : 1;
|
||||
union
|
||||
{
|
||||
struct {
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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));
|
||||
|
||||
28
test/test_suite/asm/asm_defer.c3t
Normal file
28
test/test_suite/asm/asm_defer.c3t
Normal file
@@ -0,0 +1,28 @@
|
||||
// #target: macos-x64
|
||||
module test;
|
||||
fn int main(String[] args)
|
||||
{
|
||||
defer
|
||||
{
|
||||
int x;
|
||||
asm
|
||||
{
|
||||
movl [x], 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* #expect: test.ll
|
||||
|
||||
entry:
|
||||
%args = alloca %"char[][]", align 8
|
||||
%x = alloca i32, align 4
|
||||
store ptr %0, ptr %args, align 8
|
||||
%ptradd = getelementptr inbounds i8, ptr %args, i64 8
|
||||
store i64 %1, ptr %ptradd, align 8
|
||||
store i32 0, ptr %x, align 4
|
||||
%2 = load i32, ptr %x, align 4
|
||||
call void asm sideeffect alignstack "movl $$1, ($0)\0A", "r,~{flags},~{dirflag},~{fspr}"(i32 %2)
|
||||
ret i32 0
|
||||
}
|
||||
Reference in New Issue
Block a user