瀏覽代碼

Add `defer` statements; add implicit `context` pointer to context stack

gingerBill 2 年之前
父節點
當前提交
fb04103352
共有 2 個文件被更改,包括 49 次插入14 次删除
  1. 23 4
      src/tilde_proc.cpp
  2. 26 10
      src/tilde_stmt.cpp

+ 23 - 4
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) {

+ 26 - 10
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;