diff options
| author | gingerBill <bill@gingerbill.org> | 2023-07-19 15:24:07 +0100 |
|---|---|---|
| committer | gingerBill <bill@gingerbill.org> | 2023-07-19 15:24:07 +0100 |
| commit | 9abf43b0d29abf3c560cd26081fb4adf0b38a5c6 (patch) | |
| tree | 31e1c494651e36a0a8a1310f3a57299f97868abd /src/tilde_stmt.cpp | |
| parent | 7f97274ecc0cfe445988f87c8806d08618f6671a (diff) | |
Mock out `defer` handling logic (before handling `defer` statements)
Diffstat (limited to 'src/tilde_stmt.cpp')
| -rw-r--r-- | src/tilde_stmt.cpp | 146 |
1 files changed, 122 insertions, 24 deletions
diff --git a/src/tilde_stmt.cpp b/src/tilde_stmt.cpp index 0f12ddf9c..85e719f29 100644 --- a/src/tilde_stmt.cpp +++ b/src/tilde_stmt.cpp @@ -6,6 +6,23 @@ gb_internal bool cg_emit_goto(cgProcedure *p, TB_Node *control_region) { return false; } +gb_internal TB_Node *cg_control_region(cgProcedure *p, char const *name) { + TEMPORARY_ALLOCATOR_GUARD(); + + isize n = gb_strlen(name); + + char *new_name = gb_alloc_array(temporary_allocator(), char, n+12); + n = -1 + gb_snprintf(new_name, n+11, "%.*s_%u", cast(int)n, name, p->control_regions.count); + + TB_Node *region = tb_inst_region(p->func); + tb_inst_set_region_name(region, n, new_name); + + GB_ASSERT(p->scope_index >= 0); + array_add(&p->control_regions, cgControlRegion{region, p->scope_index}); + + return region; +} + gb_internal cgValue cg_emit_load(cgProcedure *p, cgValue const &ptr, bool is_volatile) { GB_ASSERT(is_type_pointer(ptr.type)); Type *type = type_deref(ptr.type); @@ -604,18 +621,18 @@ gb_internal cgValue cg_emit_deep_field_gep(cgProcedure *p, cgValue e, Selection -gb_internal cgBranchBlocks cg_lookup_branch_blocks(cgProcedure *p, Ast *ident) { +gb_internal cgBranchRegions cg_lookup_branch_regions(cgProcedure *p, Ast *ident) { GB_ASSERT(ident->kind == Ast_Ident); Entity *e = entity_of_node(ident); GB_ASSERT(e->kind == Entity_Label); - for (cgBranchBlocks const &b : p->branch_blocks) { + for (cgBranchRegions const &b : p->branch_regions) { if (b.label == e->Label.node) { return b; } } GB_PANIC("Unreachable"); - cgBranchBlocks empty = {}; + cgBranchRegions empty = {}; return empty; } @@ -630,7 +647,7 @@ gb_internal cgTargetList *cg_push_target_list(cgProcedure *p, Ast *label, TB_Nod if (label != nullptr) { // Set label blocks GB_ASSERT(label->kind == Ast_Label); - for (cgBranchBlocks &b : p->branch_blocks) { + for (cgBranchRegions &b : p->branch_regions) { GB_ASSERT(b.label != nullptr && label != nullptr); GB_ASSERT(b.label->kind == Ast_Label); if (b.label == label) { @@ -701,16 +718,97 @@ gb_internal cgValue cg_address_from_load_or_generate_local(cgProcedure *p, cgVal } -gb_internal void cg_scope_open(cgProcedure *p, Scope *scope) { - // TODO(bill): cg_scope_open -} +gb_internal void cg_build_defer_stmt(cgProcedure *p, cgDefer const &d) { + TB_Node *curr_region = tb_inst_get_control(p->func); + if (curr_region == nullptr) { + return; + } + + // NOTE(bill): The prev block may defer injection before it's terminator + TB_Node *last_instr = nullptr; + if (curr_region->input_count) { + last_instr = *(curr_region->inputs + curr_region->input_count); + } + if (last_instr && TB_IS_NODE_TERMINATOR(last_instr->type)) { + // NOTE(bill): ReturnStmt defer stuff will be handled previously + return; + } -gb_internal void cg_scope_close(cgProcedure *p, cgDeferExitKind kind, TB_Node *control_region, bool pop_stack=true) { - // TODO(bill): cg_scope_close + isize prev_context_stack_count = p->context_stack.count; + GB_ASSERT(prev_context_stack_count <= p->context_stack.capacity); + defer (p->context_stack.count = prev_context_stack_count); + p->context_stack.count = d.context_stack_count; + + TB_Node *b = cg_control_region(p, "defer"); + if (last_instr == nullptr) { + cg_emit_goto(p, b); + } + + tb_inst_set_control(p->func, b); + if (d.kind == cgDefer_Node) { + cg_build_stmt(p, d.stmt); + } else if (d.kind == cgDefer_Proc) { + cg_emit_call(p, d.proc.deferred, d.proc.result_as_args); + } } + gb_internal void cg_emit_defer_stmts(cgProcedure *p, cgDeferExitKind kind, TB_Node *control_region) { - // TODO(bill): cg_emit_defer_stmts + isize count = p->defer_stack.count; + isize i = count; + while (i --> 0) { + cgDefer const &d = p->defer_stack[i]; + + if (kind == cgDeferExit_Default) { + if (p->scope_index == d.scope_index && + d.scope_index > 0) { + cg_build_defer_stmt(p, d); + array_pop(&p->defer_stack); + continue; + } else { + break; + } + } else if (kind == cgDeferExit_Return) { + cg_build_defer_stmt(p, d); + } else if (kind == cgDeferExit_Branch) { + GB_PANIC("TODO(bill): cgDeferExit_Branch"); + GB_ASSERT(control_region != nullptr); + isize lower_limit = -1; + for (auto const &cr : p->control_regions) { + if (cr.control_region == control_region) { + lower_limit = cr.scope_index; + break; + } + } + GB_ASSERT(lower_limit >= 0); + if (lower_limit < d.scope_index) { + cg_build_defer_stmt(p, d); + } + } + } +} + +gb_internal void cg_scope_open(cgProcedure *p, Scope *scope) { + // TODO(bill): debug scope information + + p->scope_index += 1; + array_add(&p->scope_stack, scope); +} + +gb_internal void cg_scope_close(cgProcedure *p, cgDeferExitKind kind, TB_Node *control_region) { + cg_emit_defer_stmts(p, kind, control_region); + GB_ASSERT(p->scope_index > 0); + + while (p->context_stack.count > 0) { + auto *ctx = &p->context_stack[p->context_stack.count-1]; + if (ctx->scope_index < p->scope_index) { + break; + } + array_pop(&p->context_stack); + } + + p->scope_index -= 1; + array_pop(&p->scope_stack); } @@ -864,17 +962,17 @@ gb_internal void cg_build_if_stmt(cgProcedure *p, Ast *node) { defer (cg_scope_close(p, cgDeferExit_Default, nullptr)); if (is->init != nullptr) { - TB_Node *init = tb_inst_region_with_name(p->func, -1, "if_init"); + TB_Node *init = cg_control_region(p, "if_init"); cg_emit_goto(p, init); tb_inst_set_control(p->func, init); cg_build_stmt(p, is->init); } - TB_Node *then = tb_inst_region_with_name(p->func, -1, "if_then"); - TB_Node *done = tb_inst_region_with_name(p->func, -1, "if_done"); + TB_Node *then = cg_control_region(p, "if_then"); + TB_Node *done = cg_control_region(p, "if_done"); TB_Node *else_ = done; if (is->else_stmt != nullptr) { - else_ = tb_inst_region_with_name(p->func, -1, "if_else"); + else_ = cg_control_region(p, "if_else"); } cgValue cond = cg_build_cond(p, is->cond, then, else_); @@ -916,20 +1014,20 @@ gb_internal void cg_build_for_stmt(cgProcedure *p, Ast *node) { defer (cg_scope_close(p, cgDeferExit_Default, nullptr)); if (fs->init != nullptr) { - TB_Node *init = tb_inst_region_with_name(p->func, -1, "for_init"); + TB_Node *init = cg_control_region(p, "for_init"); cg_emit_goto(p, init); tb_inst_set_control(p->func, init); cg_build_stmt(p, fs->init); } - TB_Node *body = tb_inst_region_with_name(p->func, -1, "for_body"); - TB_Node *done = tb_inst_region_with_name(p->func, -1, "for_done"); + TB_Node *body = cg_control_region(p, "for_body"); + TB_Node *done = cg_control_region(p, "for_done"); TB_Node *loop = body; if (fs->cond != nullptr) { - loop = tb_inst_region_with_name(p->func, -1, "for_loop"); + loop = cg_control_region(p, "for_loop"); } TB_Node *post = loop; if (fs->post != nullptr) { - post = tb_inst_region_with_name(p->func, -1, "for_post"); + post = cg_control_region(p, "for_post"); } cg_emit_goto(p, loop); @@ -1018,7 +1116,7 @@ gb_internal void cg_build_switch_stmt(cgProcedure *p, Ast *node) { tag = cg_const_bool(p, t_bool, true); } - TB_Node *done = tb_inst_region_with_name(p->func, -1, "switch_done"); + TB_Node *done = cg_control_region(p, "switch_done"); ast_node(body, BlockStmt, ss->body); @@ -1036,7 +1134,7 @@ gb_internal void cg_build_switch_stmt(cgProcedure *p, Ast *node) { Ast *clause = body->stmts[i]; ast_node(cc, CaseClause, clause); - body_regions[i] = tb_inst_region_with_name(p->func, -1, cc->list.count == 0 ? "switch_default_body" : "switch_case_body"); + body_regions[i] = cg_control_region(p, cc->list.count == 0 ? "switch_default_body" : "switch_case_body"); body_scopes[i] = cc->scope; if (cc->list.count == 0) { default_block = body_regions[i]; @@ -1110,7 +1208,7 @@ gb_internal void cg_build_switch_stmt(cgProcedure *p, Ast *node) { if (!is_trivial) for (Ast *expr : cc->list) { expr = unparen_expr(expr); - next_cond = tb_inst_region_with_name(p->func, -1, "switch_case_next"); + next_cond = cg_control_region(p, "switch_case_next"); cgValue cond = {}; if (is_ast_range(expr)) { @@ -1231,7 +1329,7 @@ gb_internal void cg_build_stmt(cgProcedure *p, Ast *node) { case_ast_node(bs, BlockStmt, node); TB_Node *done = nullptr; if (bs->label != nullptr) { - done = tb_inst_region_with_name(p->func, -1, "block_done"); + done = cg_control_region(p, "block_done"); cgTargetList *tl = cg_push_target_list(p, bs->label, done, nullptr, nullptr); tl->is_block = true; } @@ -1316,7 +1414,7 @@ gb_internal void cg_build_stmt(cgProcedure *p, Ast *node) { TB_Node *block = nullptr; if (bs->label != nullptr) { - cgBranchBlocks bb = cg_lookup_branch_blocks(p, bs->label); + cgBranchRegions bb = cg_lookup_branch_regions(p, bs->label); switch (bs->token.kind) { case Token_break: block = bb.break_; break; case Token_continue: block = bb.continue_; break; |