mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Fix defer with static variables.
This commit is contained in:
@@ -2441,6 +2441,7 @@ typedef struct CopyStruct_
|
||||
{
|
||||
CopyFixup fixups[MAX_FIXUPS];
|
||||
CopyFixup *current_fixup;
|
||||
bool single_static;
|
||||
} CopyStruct;
|
||||
|
||||
#define MACRO_COPY_DECL(x) x = copy_decl(c, x)
|
||||
@@ -2460,6 +2461,7 @@ typedef struct CopyStruct_
|
||||
Expr *expr_macro_copy(Expr *source_expr);
|
||||
Decl **decl_copy_list(Decl **decl_list);
|
||||
Ast *ast_macro_copy(Ast *source_ast);
|
||||
Ast *ast_defer_copy(Ast *source_ast);
|
||||
|
||||
Expr **copy_expr_list(CopyStruct *c, Expr **expr_list);
|
||||
Expr *copy_expr(CopyStruct *c, Expr *source_expr);
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
#define SCOPE_FIXUP_START do { CopyFixup *current = c->current_fixup;
|
||||
#define SCOPE_FIXUP_END c->current_fixup = current; } while (0)
|
||||
|
||||
|
||||
|
||||
static inline void copy_reg_ref(CopyStruct *c, void *original, void *result)
|
||||
{
|
||||
c->current_fixup->new_ptr = result;
|
||||
@@ -146,12 +144,21 @@ static CopyStruct copy_struct;
|
||||
Ast *ast_macro_copy(Ast *source_ast)
|
||||
{
|
||||
copy_struct.current_fixup = copy_struct.fixups;
|
||||
copy_struct.single_static = false;
|
||||
return ast_copy_deep(©_struct, source_ast);
|
||||
}
|
||||
|
||||
Ast *ast_defer_copy(Ast *source_ast)
|
||||
{
|
||||
copy_struct.current_fixup = copy_struct.fixups;
|
||||
copy_struct.single_static = true;
|
||||
return ast_copy_deep(©_struct, source_ast);
|
||||
}
|
||||
|
||||
Expr *expr_macro_copy(Expr *source_expr)
|
||||
{
|
||||
copy_struct.current_fixup = copy_struct.fixups;
|
||||
copy_struct.single_static = false;
|
||||
return copy_expr(©_struct, source_expr);
|
||||
}
|
||||
|
||||
@@ -560,9 +567,19 @@ static Attr **copy_attributes(CopyStruct *c, Attr** attr_list)
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
static inline bool decl_is_resolved_static_var(Decl *decl)
|
||||
{
|
||||
if (decl->resolve_status != RESOLVE_DONE) return false;
|
||||
if (decl->decl_kind != DECL_VAR) return false;
|
||||
if (decl->var.kind != VARDECL_LOCAL) return false;
|
||||
return decl->var.is_static;
|
||||
}
|
||||
|
||||
Decl *copy_decl(CopyStruct *c, Decl *decl)
|
||||
{
|
||||
if (!decl) return NULL;
|
||||
if (c->single_static && decl_is_resolved_static_var(decl)) return decl;
|
||||
Decl *copy = decl_copy(decl);
|
||||
copy_reg_ref(c, decl, copy);
|
||||
copy->attributes = copy_attributes(c, copy->attributes);
|
||||
|
||||
@@ -34,6 +34,8 @@ LLVMValueRef llvm_emit_local_decl(GenContext *c, Decl *decl)
|
||||
// then we essentially treat this as a global.
|
||||
if (decl->var.is_static)
|
||||
{
|
||||
// In defers we might already have generated this variable.
|
||||
if (decl->backend_ref) return decl->backend_ref;
|
||||
void *builder = c->builder;
|
||||
c->builder = NULL;
|
||||
decl->backend_ref = LLVMAddGlobal(c->module, alloc_type, "tempglobal");
|
||||
@@ -48,6 +50,7 @@ LLVMValueRef llvm_emit_local_decl(GenContext *c, Decl *decl)
|
||||
c->builder = builder;
|
||||
return decl->backend_ref;
|
||||
}
|
||||
assert(!decl->backend_ref);
|
||||
llvm_emit_local_var_alloca(c, decl);
|
||||
Expr *init = decl->var.init_expr;
|
||||
if (IS_FAILABLE(decl))
|
||||
|
||||
@@ -88,7 +88,7 @@ AstId context_get_defers(SemaContext *context, AstId defer_top, AstId defer_bott
|
||||
while (defer_bottom != defer_top)
|
||||
{
|
||||
Ast *defer = astptr(defer_top);
|
||||
Ast *defer_body = ast_macro_copy(astptr(defer->defer_stmt.body));
|
||||
Ast *defer_body = ast_defer_copy(astptr(defer->defer_stmt.body));
|
||||
*next = astid(defer_body);
|
||||
next = &defer_body->next;
|
||||
defer_top = defer->defer_stmt.prev_defer;
|
||||
@@ -105,7 +105,7 @@ void context_pop_defers(SemaContext *context, AstId *next)
|
||||
while (defer_current != defer_start)
|
||||
{
|
||||
Ast *defer = astptr(defer_current);
|
||||
Ast *defer_body = ast_macro_copy(astptr(defer->defer_stmt.body));
|
||||
Ast *defer_body = ast_defer_copy(astptr(defer->defer_stmt.body));
|
||||
*next = astid(defer_body);
|
||||
next = &defer_body->next;
|
||||
defer_current = defer->defer_stmt.prev_defer;
|
||||
|
||||
205
test/test_suite/defer/defer_static_var.c3t
Normal file
205
test/test_suite/defer/defer_static_var.c3t
Normal file
@@ -0,0 +1,205 @@
|
||||
// #target: x64-darwin
|
||||
module foo;
|
||||
extern fn void printf(char*,...);
|
||||
|
||||
fn int foo(int x)
|
||||
{
|
||||
defer
|
||||
{
|
||||
static int y = 0;
|
||||
y++;
|
||||
printf("Here we go %d\n", y);
|
||||
}
|
||||
if (x > 0) return 2;
|
||||
return x;
|
||||
}
|
||||
|
||||
macro void foo2(int x)
|
||||
{
|
||||
printf("->%d\n", x);
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
defer
|
||||
{
|
||||
static int y = 0;
|
||||
y++;
|
||||
printf(">%d--%d\n", i, y);
|
||||
}
|
||||
if (i == x) break;
|
||||
printf("--");
|
||||
}
|
||||
}
|
||||
|
||||
fn void main()
|
||||
{
|
||||
foo(1);
|
||||
foo(2);
|
||||
foo(-2);
|
||||
@foo2(0);
|
||||
@foo2(1);
|
||||
@foo2(2);
|
||||
}
|
||||
|
||||
/* #expect: foo.ll
|
||||
|
||||
@foo.y = internal unnamed_addr global i32 0, align 4
|
||||
@main.y = internal unnamed_addr global i32 0, align 4
|
||||
@main.y.7 = internal unnamed_addr global i32 0, align 4
|
||||
@main.y.12 = internal unnamed_addr global i32 0, align 4
|
||||
|
||||
|
||||
define i32 @foo.foo(i32 %0) #0 {
|
||||
entry:
|
||||
%gt = icmp sgt i32 %0, 0
|
||||
br i1 %gt, label %if.then, label %if.exit
|
||||
|
||||
if.then: ; preds = %entry
|
||||
%1 = load i32, i32* @foo.y, align 4
|
||||
%add = add i32 %1, 1
|
||||
store i32 %add, i32* @foo.y, align 4
|
||||
%2 = load i32, i32* @foo.y, align 4
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str, i32 0, i32 0), i32 %2)
|
||||
ret i32 2
|
||||
|
||||
if.exit: ; preds = %entry
|
||||
%3 = load i32, i32* @foo.y, align 4
|
||||
%add1 = add i32 %3, 1
|
||||
store i32 %add1, i32* @foo.y, align 4
|
||||
%4 = load i32, i32* @foo.y, align 4
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str.1, i32 0, i32 0), i32 %4)
|
||||
ret i32 %0
|
||||
}
|
||||
|
||||
define void @foo.main() #0 {
|
||||
entry:
|
||||
%x = alloca i32, align 4
|
||||
%i = alloca i32, align 4
|
||||
%x3 = alloca i32, align 4
|
||||
%i4 = alloca i32, align 4
|
||||
%x15 = alloca i32, align 4
|
||||
%i16 = alloca i32, align 4
|
||||
%0 = call i32 @foo.foo(i32 1)
|
||||
%1 = call i32 @foo.foo(i32 2)
|
||||
%2 = call i32 @foo.foo(i32 -2)
|
||||
store i32 0, i32* %x, align 4
|
||||
%3 = load i32, i32* %x, align 4
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str.2, i32 0, i32 0), i32 %3)
|
||||
store i32 0, i32* %i, align 4
|
||||
br label %loop.cond
|
||||
|
||||
loop.cond: ; preds = %if.exit, %entry
|
||||
%4 = load i32, i32* %i, align 4
|
||||
%lt = icmp slt i32 %4, 100
|
||||
br i1 %lt, label %loop.body, label %loop.exit
|
||||
|
||||
loop.body: ; preds = %loop.cond
|
||||
%5 = load i32, i32* %i, align 4
|
||||
%6 = load i32, i32* %x, align 4
|
||||
%eq = icmp eq i32 %5, %6
|
||||
br i1 %eq, label %if.then, label %if.exit
|
||||
|
||||
if.then: ; preds = %loop.body
|
||||
%7 = load i32, i32* @main.y, align 4
|
||||
%add = add i32 %7, 1
|
||||
store i32 %add, i32* @main.y, align 4
|
||||
%8 = load i32, i32* %i, align 4
|
||||
%9 = load i32, i32* @main.y, align 4
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str.3, i32 0, i32 0), i32 %8, i32 %9)
|
||||
br label %loop.exit
|
||||
|
||||
if.exit: ; preds = %loop.body
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str.4, i32 0, i32 0))
|
||||
%10 = load i32, i32* @main.y, align 4
|
||||
%add1 = add i32 %10, 1
|
||||
store i32 %add1, i32* @main.y, align 4
|
||||
%11 = load i32, i32* %i, align 4
|
||||
%12 = load i32, i32* @main.y, align 4
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str.5, i32 0, i32 0), i32 %11, i32 %12)
|
||||
%13 = load i32, i32* %i, align 4
|
||||
%add2 = add i32 %13, 1
|
||||
store i32 %add2, i32* %i, align 4
|
||||
br label %loop.cond
|
||||
|
||||
loop.exit: ; preds = %if.then, %loop.cond
|
||||
store i32 1, i32* %x3, align 4
|
||||
%14 = load i32, i32* %x3, align 4
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str.6, i32 0, i32 0), i32 %14)
|
||||
store i32 0, i32* %i4, align 4
|
||||
br label %loop.cond5
|
||||
|
||||
loop.cond5: ; preds = %if.exit11, %loop.exit
|
||||
%15 = load i32, i32* %i4, align 4
|
||||
%lt6 = icmp slt i32 %15, 100
|
||||
br i1 %lt6, label %loop.body7, label %loop.exit14
|
||||
|
||||
loop.body7: ; preds = %loop.cond5
|
||||
%16 = load i32, i32* %i4, align 4
|
||||
%17 = load i32, i32* %x3, align 4
|
||||
%eq8 = icmp eq i32 %16, %17
|
||||
br i1 %eq8, label %if.then9, label %if.exit11
|
||||
|
||||
if.then9: ; preds = %loop.body7
|
||||
%18 = load i32, i32* @main.y.7, align 4
|
||||
%add10 = add i32 %18, 1
|
||||
store i32 %add10, i32* @main.y.7, align 4
|
||||
%19 = load i32, i32* %i4, align 4
|
||||
%20 = load i32, i32* @main.y.7, align 4
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str.8, i32 0, i32 0), i32 %19, i32 %20)
|
||||
br label %loop.exit14
|
||||
|
||||
if.exit11: ; preds = %loop.body7
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str.9, i32 0, i32 0))
|
||||
%21 = load i32, i32* @main.y.7, align 4
|
||||
%add12 = add i32 %21, 1
|
||||
store i32 %add12, i32* @main.y.7, align 4
|
||||
%22 = load i32, i32* %i4, align 4
|
||||
%23 = load i32, i32* @main.y.7, align 4
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str.10, i32 0, i32 0), i32 %22, i32 %23)
|
||||
%24 = load i32, i32* %i4, align 4
|
||||
%add13 = add i32 %24, 1
|
||||
store i32 %add13, i32* %i4, align 4
|
||||
br label %loop.cond5
|
||||
|
||||
loop.exit14: ; preds = %if.then9, %loop.cond5
|
||||
store i32 2, i32* %x15, align 4
|
||||
%25 = load i32, i32* %x15, align 4
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.str.11, i32 0, i32 0), i32 %25)
|
||||
store i32 0, i32* %i16, align 4
|
||||
br label %loop.cond17
|
||||
|
||||
loop.cond17: ; preds = %if.exit23, %loop.exit14
|
||||
%26 = load i32, i32* %i16, align 4
|
||||
%lt18 = icmp slt i32 %26, 100
|
||||
br i1 %lt18, label %loop.body19, label %loop.exit26
|
||||
|
||||
loop.body19: ; preds = %loop.cond17
|
||||
%27 = load i32, i32* %i16, align 4
|
||||
%28 = load i32, i32* %x15, align 4
|
||||
%eq20 = icmp eq i32 %27, %28
|
||||
br i1 %eq20, label %if.then21, label %if.exit23
|
||||
|
||||
if.then21: ; preds = %loop.body19
|
||||
%29 = load i32, i32* @main.y.12, align 4
|
||||
%add22 = add i32 %29, 1
|
||||
store i32 %add22, i32* @main.y.12, align 4
|
||||
%30 = load i32, i32* %i16, align 4
|
||||
%31 = load i32, i32* @main.y.12, align 4
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str.13, i32 0, i32 0), i32 %30, i32 %31)
|
||||
br label %loop.exit26
|
||||
|
||||
if.exit23: ; preds = %loop.body19
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str.14, i32 0, i32 0))
|
||||
%32 = load i32, i32* @main.y.12, align 4
|
||||
%add24 = add i32 %32, 1
|
||||
store i32 %add24, i32* @main.y.12, align 4
|
||||
%33 = load i32, i32* %i16, align 4
|
||||
%34 = load i32, i32* @main.y.12, align 4
|
||||
call void (i8*, ...) @printf(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str.15, i32 0, i32 0), i32 %33, i32 %34)
|
||||
%35 = load i32, i32* %i16, align 4
|
||||
%add25 = add i32 %35, 1
|
||||
store i32 %add25, i32* %i16, align 4
|
||||
br label %loop.cond17
|
||||
|
||||
loop.exit26: ; preds = %if.then21, %loop.cond17
|
||||
ret void
|
||||
}
|
||||
Reference in New Issue
Block a user