diff --git a/src/tilde_proc.cpp b/src/tilde_proc.cpp index 2bb18a2de..e2764bc50 100644 --- a/src/tilde_proc.cpp +++ b/src/tilde_proc.cpp @@ -181,11 +181,8 @@ gb_internal void cg_procedure_begin(cgProcedure *p) { GB_ASSERT(p->type->kind == Type_Proc); TypeProc *pt = &p->type->Proc; - if (pt->params == nullptr) { - return; - } int param_index = 0; - for (Entity *e : pt->params->Tuple.variables) { + if (pt->params != nullptr) for (Entity *e : pt->params->Tuple.variables) { if (e->kind != Entity_Variable) { continue; } @@ -247,6 +244,28 @@ gb_internal void cg_procedure_begin(cgProcedure *p) { // } // } } + + if (p->type->Proc.calling_convention == ProcCC_Odin) { + // NOTE(bill): Push context on to stack from implicit parameter + + String name = str_lit("__.context_ptr"); + + Entity *e = alloc_entity_param(nullptr, make_token_ident(name), t_context_ptr, false, false); + e->flags |= EntityFlag_NoAlias; + + TB_Node *param = p->param_nodes[p->param_nodes.count-1]; + param = tb_inst_load(p->func, TB_TYPE_PTR, param, cast(TB_CharUnits)build_context.ptr_size, false); + + cgValue local = cg_value(param, t_context_ptr); + cgAddr addr = cg_addr(local); + map_set(&p->variable_map, e, addr); + + + cgContextData *cd = array_add_and_get(&p->context_stack); + cd->ctx = addr; + cd->scope_index = -1; + cd->uses = +1; // make sure it has been used already + } } gb_internal void cg_procedure_end(cgProcedure *p) { diff --git a/src/tilde_stmt.cpp b/src/tilde_stmt.cpp index 85e719f29..996506c84 100644 --- a/src/tilde_stmt.cpp +++ b/src/tilde_stmt.cpp @@ -725,14 +725,14 @@ gb_internal void cg_build_defer_stmt(cgProcedure *p, cgDefer const &d) { } // 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; - } + TB_Node *last_inst = nullptr; + // if (curr_region->input_count) { + // last_inst = *(curr_region->inputs + curr_region->input_count); + // } + // if (last_inst && TB_IS_NODE_TERMINATOR(last_inst->type)) { + // // NOTE(bill): ReturnStmt defer stuff will be handled previously + // return; + // } isize prev_context_stack_count = p->context_stack.count; GB_ASSERT(prev_context_stack_count <= p->context_stack.capacity); @@ -740,7 +740,7 @@ gb_internal void cg_build_defer_stmt(cgProcedure *p, cgDefer const &d) { p->context_stack.count = d.context_stack_count; TB_Node *b = cg_control_region(p, "defer"); - if (last_instr == nullptr) { + if (last_inst == nullptr) { cg_emit_goto(p, b); } @@ -771,7 +771,6 @@ gb_internal void cg_emit_defer_stmts(cgProcedure *p, cgDeferExitKind kind, TB_No } 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) { @@ -1465,6 +1464,23 @@ gb_internal void cg_build_stmt(cgProcedure *p, Ast *node) { cg_build_switch_stmt(p, node); case_end; + case_ast_node(ds, DeferStmt, node); + Type *pt = base_type(p->type); + GB_ASSERT(pt->kind == Type_Proc); + if (pt->Proc.calling_convention == ProcCC_Odin) { + GB_ASSERT(p->context_stack.count != 0); + } + + cgDefer *d = array_add_and_get(&p->defer_stack); + d->kind = cgDefer_Node; + d->scope_index = p->scope_index; + d->context_stack_count = p->context_stack.count; + d->control_region = tb_inst_get_control(p->func); + GB_ASSERT(d->control_region != nullptr); + d->stmt = ds->stmt; + case_end; + + default: GB_PANIC("TODO cg_build_stmt %.*s", LIT(ast_strings[node->kind])); break;