aboutsummaryrefslogtreecommitdiff
path: root/src/tilde_stmt.cpp
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2023-07-19 15:24:07 +0100
committergingerBill <bill@gingerbill.org>2023-07-19 15:24:07 +0100
commit9abf43b0d29abf3c560cd26081fb4adf0b38a5c6 (patch)
tree31e1c494651e36a0a8a1310f3a57299f97868abd /src/tilde_stmt.cpp
parent7f97274ecc0cfe445988f87c8806d08618f6671a (diff)
Mock out `defer` handling logic (before handling `defer` statements)
Diffstat (limited to 'src/tilde_stmt.cpp')
-rw-r--r--src/tilde_stmt.cpp146
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;