|
@@ -85,15 +85,24 @@ struct ssaTargetList {
|
|
ssaBlock * fallthrough_;
|
|
ssaBlock * fallthrough_;
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+enum ssaDeferExitKind {
|
|
|
|
+ ssaDeferExit_Default,
|
|
|
|
+ ssaDeferExit_Return,
|
|
|
|
+ ssaDeferExit_Branch,
|
|
|
|
+};
|
|
enum ssaDeferKind {
|
|
enum ssaDeferKind {
|
|
- ssaDefer_Default,
|
|
|
|
- ssaDefer_Return,
|
|
|
|
- ssaDefer_Branch,
|
|
|
|
|
|
+ ssaDefer_Node,
|
|
|
|
+ ssaDefer_Instr,
|
|
};
|
|
};
|
|
|
|
+
|
|
struct ssaDefer {
|
|
struct ssaDefer {
|
|
- AstNode *stmt;
|
|
|
|
|
|
+ ssaDeferKind kind;
|
|
isize scope_index;
|
|
isize scope_index;
|
|
ssaBlock *block;
|
|
ssaBlock *block;
|
|
|
|
+ union {
|
|
|
|
+ AstNode *stmt;
|
|
|
|
+ ssaValue *instr;
|
|
|
|
+ };
|
|
};
|
|
};
|
|
|
|
|
|
struct ssaProcedure {
|
|
struct ssaProcedure {
|
|
@@ -361,6 +370,26 @@ ssaDebugInfo *ssa_alloc_debug_info(gbAllocator a, ssaDebugInfoKind kind) {
|
|
return di;
|
|
return di;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+
|
|
|
|
+ssaDefer ssa_add_defer_node(ssaProcedure *proc, isize scope_index, AstNode *stmt) {
|
|
|
|
+ ssaDefer d = {ssaDefer_Node};
|
|
|
|
+ d.scope_index = scope_index;
|
|
|
|
+ d.block = proc->curr_block;
|
|
|
|
+ d.stmt = stmt;
|
|
|
|
+ gb_array_append(proc->defer_stmts, d);
|
|
|
|
+ return d;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ssaDefer ssa_add_defer_instr(ssaProcedure *proc, isize scope_index, ssaValue *instr) {
|
|
|
|
+ ssaDefer d = {ssaDefer_Instr};
|
|
|
|
+ d.scope_index = proc->scope_index;
|
|
|
|
+ d.block = proc->curr_block;
|
|
|
|
+ d.instr = cast(ssaValue *)gb_alloc_copy(proc->module->allocator, instr, gb_size_of(ssaValue));
|
|
|
|
+ gb_array_append(proc->defer_stmts, d);
|
|
|
|
+ return d;
|
|
|
|
+}
|
|
|
|
+
|
|
void ssa_init_module(ssaModule *m, Checker *c) {
|
|
void ssa_init_module(ssaModule *m, Checker *c) {
|
|
// TODO(bill): Determine a decent size for the arena
|
|
// TODO(bill): Determine a decent size for the arena
|
|
isize token_count = c->parser->total_token_count;
|
|
isize token_count = c->parser->total_token_count;
|
|
@@ -972,17 +1001,21 @@ void ssa_build_defer_stmt(ssaProcedure *proc, ssaDefer d) {
|
|
gb_array_append(proc->blocks, b);
|
|
gb_array_append(proc->blocks, b);
|
|
proc->curr_block = b;
|
|
proc->curr_block = b;
|
|
ssa_emit_comment(proc, make_string("defer"));
|
|
ssa_emit_comment(proc, make_string("defer"));
|
|
- ssa_build_stmt(proc, d.stmt);
|
|
|
|
|
|
+ if (d.kind == ssaDefer_Node) {
|
|
|
|
+ ssa_build_stmt(proc, d.stmt);
|
|
|
|
+ } else if (d.kind == ssaDefer_Instr) {
|
|
|
|
+ ssa_emit(proc, d.instr);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
-void ssa_emit_defer_stmts(ssaProcedure *proc, ssaDeferKind kind, ssaBlock *block) {
|
|
|
|
|
|
+void ssa_emit_defer_stmts(ssaProcedure *proc, ssaDeferExitKind kind, ssaBlock *block) {
|
|
isize count = gb_array_count(proc->defer_stmts);
|
|
isize count = gb_array_count(proc->defer_stmts);
|
|
isize i = count;
|
|
isize i = count;
|
|
while (i --> 0) {
|
|
while (i --> 0) {
|
|
ssaDefer d = proc->defer_stmts[i];
|
|
ssaDefer d = proc->defer_stmts[i];
|
|
- if (kind == ssaDefer_Return) {
|
|
|
|
|
|
+ if (kind == ssaDeferExit_Return) {
|
|
ssa_build_defer_stmt(proc, d);
|
|
ssa_build_defer_stmt(proc, d);
|
|
- } else if (kind == ssaDefer_Default) {
|
|
|
|
|
|
+ } else if (kind == ssaDeferExit_Default) {
|
|
if (proc->scope_index == d.scope_index &&
|
|
if (proc->scope_index == d.scope_index &&
|
|
d.scope_index > 1) {
|
|
d.scope_index > 1) {
|
|
ssa_build_defer_stmt(proc, d);
|
|
ssa_build_defer_stmt(proc, d);
|
|
@@ -991,7 +1024,7 @@ void ssa_emit_defer_stmts(ssaProcedure *proc, ssaDeferKind kind, ssaBlock *block
|
|
} else {
|
|
} else {
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
- } else if (kind == ssaDefer_Branch) {
|
|
|
|
|
|
+ } else if (kind == ssaDeferExit_Branch) {
|
|
GB_ASSERT(block != NULL);
|
|
GB_ASSERT(block != NULL);
|
|
isize lower_limit = block->scope_index+1;
|
|
isize lower_limit = block->scope_index+1;
|
|
if (lower_limit < d.scope_index) {
|
|
if (lower_limit < d.scope_index) {
|
|
@@ -1009,7 +1042,7 @@ void ssa_emit_unreachable(ssaProcedure *proc) {
|
|
}
|
|
}
|
|
|
|
|
|
void ssa_emit_ret(ssaProcedure *proc, ssaValue *v) {
|
|
void ssa_emit_ret(ssaProcedure *proc, ssaValue *v) {
|
|
- ssa_emit_defer_stmts(proc, ssaDefer_Return, NULL);
|
|
|
|
|
|
+ ssa_emit_defer_stmts(proc, ssaDeferExit_Return, NULL);
|
|
ssa_emit(proc, ssa_make_instr_ret(proc, v));
|
|
ssa_emit(proc, ssa_make_instr_ret(proc, v));
|
|
}
|
|
}
|
|
|
|
|
|
@@ -3316,7 +3349,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
|
|
case_ast_node(bs, BlockStmt, node);
|
|
case_ast_node(bs, BlockStmt, node);
|
|
proc->scope_index++;
|
|
proc->scope_index++;
|
|
ssa_build_stmt_list(proc, bs->stmts);
|
|
ssa_build_stmt_list(proc, bs->stmts);
|
|
- ssa_emit_defer_stmts(proc, ssaDefer_Default, NULL);
|
|
|
|
|
|
+ ssa_emit_defer_stmts(proc, ssaDeferExit_Default, NULL);
|
|
proc->scope_index--;
|
|
proc->scope_index--;
|
|
case_end;
|
|
case_end;
|
|
|
|
|
|
@@ -3325,8 +3358,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
|
|
isize scope_index = proc->scope_index;
|
|
isize scope_index = proc->scope_index;
|
|
if (ds->stmt->kind == AstNode_BlockStmt)
|
|
if (ds->stmt->kind == AstNode_BlockStmt)
|
|
scope_index--;
|
|
scope_index--;
|
|
- ssaDefer d = {ds->stmt, scope_index, proc->curr_block};
|
|
|
|
- gb_array_append(proc->defer_stmts, d);
|
|
|
|
|
|
+ ssa_add_defer_node(proc, scope_index, ds->stmt);
|
|
case_end;
|
|
case_end;
|
|
|
|
|
|
case_ast_node(rs, ReturnStmt, node);
|
|
case_ast_node(rs, ReturnStmt, node);
|
|
@@ -3377,7 +3409,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
|
|
|
|
|
|
proc->scope_index++;
|
|
proc->scope_index++;
|
|
ssa_build_stmt(proc, is->body);
|
|
ssa_build_stmt(proc, is->body);
|
|
- ssa_emit_defer_stmts(proc, ssaDefer_Default, NULL);
|
|
|
|
|
|
+ ssa_emit_defer_stmts(proc, ssaDeferExit_Default, NULL);
|
|
proc->scope_index--;
|
|
proc->scope_index--;
|
|
|
|
|
|
ssa_emit_jump(proc, done);
|
|
ssa_emit_jump(proc, done);
|
|
@@ -3387,7 +3419,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
|
|
|
|
|
|
proc->scope_index++;
|
|
proc->scope_index++;
|
|
ssa_build_stmt(proc, is->else_stmt);
|
|
ssa_build_stmt(proc, is->else_stmt);
|
|
- ssa_emit_defer_stmts(proc, ssaDefer_Default, NULL);
|
|
|
|
|
|
+ ssa_emit_defer_stmts(proc, ssaDeferExit_Default, NULL);
|
|
proc->scope_index--;
|
|
proc->scope_index--;
|
|
|
|
|
|
|
|
|
|
@@ -3429,7 +3461,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
|
|
|
|
|
|
proc->scope_index++;
|
|
proc->scope_index++;
|
|
ssa_build_stmt(proc, fs->body);
|
|
ssa_build_stmt(proc, fs->body);
|
|
- ssa_emit_defer_stmts(proc, ssaDefer_Default, NULL);
|
|
|
|
|
|
+ ssa_emit_defer_stmts(proc, ssaDeferExit_Default, NULL);
|
|
proc->scope_index--;
|
|
proc->scope_index--;
|
|
|
|
|
|
ssa_pop_target_list(proc);
|
|
ssa_pop_target_list(proc);
|
|
@@ -3524,7 +3556,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
|
|
proc->scope_index++;
|
|
proc->scope_index++;
|
|
ssa_push_target_list(proc, done, NULL, fall);
|
|
ssa_push_target_list(proc, done, NULL, fall);
|
|
ssa_build_stmt_list(proc, cc->stmts);
|
|
ssa_build_stmt_list(proc, cc->stmts);
|
|
- ssa_emit_defer_stmts(proc, ssaDefer_Default, body);
|
|
|
|
|
|
+ ssa_emit_defer_stmts(proc, ssaDeferExit_Default, body);
|
|
ssa_pop_target_list(proc);
|
|
ssa_pop_target_list(proc);
|
|
proc->scope_index--;
|
|
proc->scope_index--;
|
|
|
|
|
|
@@ -3541,7 +3573,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
|
|
proc->scope_index++;
|
|
proc->scope_index++;
|
|
ssa_push_target_list(proc, done, NULL, default_fall);
|
|
ssa_push_target_list(proc, done, NULL, default_fall);
|
|
ssa_build_stmt_list(proc, default_stmts);
|
|
ssa_build_stmt_list(proc, default_stmts);
|
|
- ssa_emit_defer_stmts(proc, ssaDefer_Default, default_block);
|
|
|
|
|
|
+ ssa_emit_defer_stmts(proc, ssaDeferExit_Default, default_block);
|
|
ssa_pop_target_list(proc);
|
|
ssa_pop_target_list(proc);
|
|
proc->scope_index--;
|
|
proc->scope_index--;
|
|
}
|
|
}
|
|
@@ -3631,7 +3663,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
|
|
proc->scope_index++;
|
|
proc->scope_index++;
|
|
ssa_push_target_list(proc, done, NULL, NULL);
|
|
ssa_push_target_list(proc, done, NULL, NULL);
|
|
ssa_build_stmt_list(proc, cc->stmts);
|
|
ssa_build_stmt_list(proc, cc->stmts);
|
|
- ssa_emit_defer_stmts(proc, ssaDefer_Default, body);
|
|
|
|
|
|
+ ssa_emit_defer_stmts(proc, ssaDeferExit_Default, body);
|
|
ssa_pop_target_list(proc);
|
|
ssa_pop_target_list(proc);
|
|
proc->scope_index--;
|
|
proc->scope_index--;
|
|
|
|
|
|
@@ -3647,7 +3679,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
|
|
proc->scope_index++;
|
|
proc->scope_index++;
|
|
ssa_push_target_list(proc, done, NULL, NULL);
|
|
ssa_push_target_list(proc, done, NULL, NULL);
|
|
ssa_build_stmt_list(proc, default_stmts);
|
|
ssa_build_stmt_list(proc, default_stmts);
|
|
- ssa_emit_defer_stmts(proc, ssaDefer_Default, default_block);
|
|
|
|
|
|
+ ssa_emit_defer_stmts(proc, ssaDeferExit_Default, default_block);
|
|
ssa_pop_target_list(proc);
|
|
ssa_pop_target_list(proc);
|
|
proc->scope_index--;
|
|
proc->scope_index--;
|
|
}
|
|
}
|
|
@@ -3671,7 +3703,7 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
|
|
// TODO(bill): Handle fallthrough scope exit correctly
|
|
// TODO(bill): Handle fallthrough scope exit correctly
|
|
// if (block != NULL && bs->token.kind != Token_fallthrough) {
|
|
// if (block != NULL && bs->token.kind != Token_fallthrough) {
|
|
if (block != NULL) {
|
|
if (block != NULL) {
|
|
- ssa_emit_defer_stmts(proc, ssaDefer_Branch, block);
|
|
|
|
|
|
+ ssa_emit_defer_stmts(proc, ssaDeferExit_Branch, block);
|
|
}
|
|
}
|
|
switch (bs->token.kind) {
|
|
switch (bs->token.kind) {
|
|
case Token_break: ssa_emit_comment(proc, make_string("break")); break;
|
|
case Token_break: ssa_emit_comment(proc, make_string("break")); break;
|
|
@@ -3686,35 +3718,39 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
|
|
|
|
|
|
case_ast_node(pa, PushAllocator, node);
|
|
case_ast_node(pa, PushAllocator, node);
|
|
ssa_emit_comment(proc, make_string("PushAllocator"));
|
|
ssa_emit_comment(proc, make_string("PushAllocator"));
|
|
|
|
+ proc->scope_index++;
|
|
|
|
+ defer (proc->scope_index--);
|
|
|
|
|
|
ssaValue *context_ptr = *map_get(&proc->module->members, hash_string(make_string("__context")));
|
|
ssaValue *context_ptr = *map_get(&proc->module->members, hash_string(make_string("__context")));
|
|
ssaValue *prev_context = ssa_add_local_generated(proc, t_context);
|
|
ssaValue *prev_context = ssa_add_local_generated(proc, t_context);
|
|
ssa_emit_store(proc, prev_context, ssa_emit_load(proc, context_ptr));
|
|
ssa_emit_store(proc, prev_context, ssa_emit_load(proc, context_ptr));
|
|
- defer (ssa_emit_store(proc, context_ptr, ssa_emit_load(proc, prev_context)));
|
|
|
|
|
|
+
|
|
|
|
+ ssa_add_defer_instr(proc, proc->scope_index, ssa_make_instr_store(proc, context_ptr, ssa_emit_load(proc, prev_context)));
|
|
|
|
|
|
ssaValue *gep = ssa_emit_struct_gep(proc, context_ptr, 1, t_allocator_ptr);
|
|
ssaValue *gep = ssa_emit_struct_gep(proc, context_ptr, 1, t_allocator_ptr);
|
|
ssa_emit_store(proc, gep, ssa_build_expr(proc, pa->expr));
|
|
ssa_emit_store(proc, gep, ssa_build_expr(proc, pa->expr));
|
|
|
|
|
|
- proc->scope_index++;
|
|
|
|
ssa_build_stmt(proc, pa->body);
|
|
ssa_build_stmt(proc, pa->body);
|
|
- proc->scope_index--;
|
|
|
|
|
|
+ ssa_emit_defer_stmts(proc, ssaDeferExit_Default, NULL);
|
|
|
|
|
|
case_end;
|
|
case_end;
|
|
|
|
|
|
|
|
|
|
case_ast_node(pa, PushContext, node);
|
|
case_ast_node(pa, PushContext, node);
|
|
ssa_emit_comment(proc, make_string("PushContext"));
|
|
ssa_emit_comment(proc, make_string("PushContext"));
|
|
|
|
+ proc->scope_index++;
|
|
|
|
+ defer (proc->scope_index--);
|
|
|
|
|
|
ssaValue *context_ptr = *map_get(&proc->module->members, hash_string(make_string("__context")));
|
|
ssaValue *context_ptr = *map_get(&proc->module->members, hash_string(make_string("__context")));
|
|
ssaValue *prev_context = ssa_add_local_generated(proc, t_context);
|
|
ssaValue *prev_context = ssa_add_local_generated(proc, t_context);
|
|
ssa_emit_store(proc, prev_context, ssa_emit_load(proc, context_ptr));
|
|
ssa_emit_store(proc, prev_context, ssa_emit_load(proc, context_ptr));
|
|
- defer (ssa_emit_store(proc, context_ptr, ssa_emit_load(proc, prev_context)));
|
|
|
|
|
|
+
|
|
|
|
+ ssa_add_defer_instr(proc, proc->scope_index, ssa_make_instr_store(proc, context_ptr, ssa_emit_load(proc, prev_context)));
|
|
|
|
|
|
ssa_emit_store(proc, context_ptr, ssa_build_expr(proc, pa->expr));
|
|
ssa_emit_store(proc, context_ptr, ssa_build_expr(proc, pa->expr));
|
|
|
|
|
|
- proc->scope_index++;
|
|
|
|
ssa_build_stmt(proc, pa->body);
|
|
ssa_build_stmt(proc, pa->body);
|
|
- proc->scope_index--;
|
|
|
|
|
|
+ ssa_emit_defer_stmts(proc, ssaDeferExit_Default, NULL);
|
|
case_end;
|
|
case_end;
|
|
|
|
|
|
|
|
|