Browse Source

Wrap Tilde's goto pseudo-instruction

gingerBill 2 years ago
parent
commit
7f97274ecc
3 changed files with 28 additions and 21 deletions
  1. 4 2
      src/tilde_backend.hpp
  2. 2 2
      src/tilde_expr.cpp
  3. 22 17
      src/tilde_stmt.cpp

+ 4 - 2
src/tilde_backend.hpp

@@ -247,9 +247,9 @@ gb_internal void    cg_addr_store(cgProcedure *p, cgAddr addr, cgValue value);
 gb_internal cgValue cg_addr_get_ptr(cgProcedure *p, cgAddr const &addr);
 
 gb_internal cgValue cg_emit_load(cgProcedure *p, cgValue const &ptr, bool is_volatile=false);
-gb_internal void cg_emit_store(cgProcedure *p, cgValue dst, cgValue const &src, bool is_volatile=false);
+gb_internal void    cg_emit_store(cgProcedure *p, cgValue dst, cgValue const &src, bool is_volatile=false);
 
-gb_internal cgAddr cg_add_local(cgProcedure *p, Type *type, Entity *e, bool zero_init);
+gb_internal cgAddr  cg_add_local(cgProcedure *p, Type *type, Entity *e, bool zero_init);
 gb_internal cgValue cg_address_from_load_or_generate_local(cgProcedure *p, cgValue value);
 
 gb_internal cgValue cg_build_call_expr(cgProcedure *p, Ast *expr);
@@ -273,6 +273,8 @@ gb_internal cgValue cg_emit_comp_against_nil(cgProcedure *p, TokenKind op_kind,
 gb_internal cgValue cg_emit_comp(cgProcedure *p, TokenKind op_kind, cgValue left, cgValue right);
 gb_internal cgValue cg_emit_arith(cgProcedure *p, TokenKind op, cgValue lhs, cgValue rhs, Type *type);
 
+gb_internal bool    cg_emit_goto(cgProcedure *p, TB_Node *control_region);
+
 gb_internal TB_Node *tb_inst_region_with_name(TB_Function *f, ptrdiff_t n, char const *name) {
 	#if 1
 	if (n < 0) {

+ 2 - 2
src/tilde_expr.cpp

@@ -2060,13 +2060,13 @@ gb_internal cgValue cg_build_expr_internal(cgProcedure *p, Ast *expr) {
 		incoming_values [0] = cg_emit_conv(p, cg_build_expr(p, te->x), type);
 		incoming_regions[0] = tb_inst_get_control(p->func);
 
-		tb_inst_goto(p->func, done);
+		cg_emit_goto(p, done);
 		tb_inst_set_control(p->func, else_);
 
 		incoming_values [1] = cg_emit_conv(p, cg_build_expr(p, te->y), type);
 		incoming_regions[1] = tb_inst_get_control(p->func);
 
-		tb_inst_goto(p->func, done);
+		cg_emit_goto(p, done);
 		tb_inst_set_control(p->func, done);
 
 		GB_ASSERT(incoming_values[0].kind == cgValue_Value ||

+ 22 - 17
src/tilde_stmt.cpp

@@ -1,3 +1,11 @@
+gb_internal bool cg_emit_goto(cgProcedure *p, TB_Node *control_region) {
+	if (tb_inst_get_control(p->func)) {
+		tb_inst_goto(p->func, control_region);
+		return true;
+	}
+	return false;
+}
+
 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);
@@ -857,7 +865,7 @@ gb_internal void cg_build_if_stmt(cgProcedure *p, Ast *node) {
 
 	if (is->init != nullptr) {
 		TB_Node *init = tb_inst_region_with_name(p->func, -1, "if_init");
-		tb_inst_goto(p->func, init);
+		cg_emit_goto(p, init);
 		tb_inst_set_control(p->func, init);
 		cg_build_stmt(p, is->init);
 	}
@@ -886,7 +894,7 @@ gb_internal void cg_build_if_stmt(cgProcedure *p, Ast *node) {
 
 	cg_build_stmt(p, is->body);
 
-	tb_inst_goto(p->func, done);
+	cg_emit_goto(p, done);
 
 	if (is->else_stmt != nullptr) {
 		tb_inst_set_control(p->func, else_);
@@ -895,7 +903,7 @@ gb_internal void cg_build_if_stmt(cgProcedure *p, Ast *node) {
 		cg_build_stmt(p, is->else_stmt);
 		cg_scope_close(p, cgDeferExit_Default, nullptr);
 
-		tb_inst_goto(p->func, done);
+		cg_emit_goto(p, done);
 	}
 
 	tb_inst_set_control(p->func, done);
@@ -909,7 +917,7 @@ gb_internal void cg_build_for_stmt(cgProcedure *p, Ast *node) {
 
 	if (fs->init != nullptr) {
 		TB_Node *init = tb_inst_region_with_name(p->func, -1, "for_init");
-		tb_inst_goto(p->func, init);
+		cg_emit_goto(p, init);
 		tb_inst_set_control(p->func, init);
 		cg_build_stmt(p, fs->init);
 	}
@@ -924,7 +932,7 @@ gb_internal void cg_build_for_stmt(cgProcedure *p, Ast *node) {
 		post = tb_inst_region_with_name(p->func, -1, "for_post");
 	}
 
-	tb_inst_goto(p->func, loop);
+	cg_emit_goto(p, loop);
 	tb_inst_set_control(p->func, loop);
 
 	if (loop != body) {
@@ -936,12 +944,12 @@ gb_internal void cg_build_for_stmt(cgProcedure *p, Ast *node) {
 	cg_build_stmt(p, fs->body);
 	cg_pop_target_list(p);
 
-	tb_inst_goto(p->func, post);
+	cg_emit_goto(p, post);
 
 	if (fs->post != nullptr) {
 		tb_inst_set_control(p->func, post);
 		cg_build_stmt(p, fs->post);
-		tb_inst_goto(p->func, loop);
+		cg_emit_goto(p, loop);
 	}
 	tb_inst_set_control(p->func, done);
 }
@@ -1144,13 +1152,13 @@ gb_internal void cg_build_switch_stmt(cgProcedure *p, Ast *node) {
 		cg_scope_close(p, cgDeferExit_Default, body_region);
 		cg_pop_target_list(p);
 
-		tb_inst_goto(p->func, done);
+		cg_emit_goto(p, done);
 		tb_inst_set_control(p->func, next_cond);
 	}
 
 	if (default_block != nullptr) {
 		if (!is_trivial) {
-			tb_inst_goto(p->func, default_block);
+			cg_emit_goto(p, default_block);
 		}
 		tb_inst_set_control(p->func, default_block);
 
@@ -1161,7 +1169,8 @@ gb_internal void cg_build_switch_stmt(cgProcedure *p, Ast *node) {
 		cg_pop_target_list(p);
 	}
 
-	tb_inst_goto(p->func, done);
+
+	cg_emit_goto(p, done);
 	tb_inst_set_control(p->func, done);
 
 	cg_scope_close(p, cgDeferExit_Default, done);
@@ -1232,7 +1241,7 @@ gb_internal void cg_build_stmt(cgProcedure *p, Ast *node) {
 		cg_scope_close(p, cgDeferExit_Default, nullptr);
 
 		if (done != nullptr) {
-			tb_inst_goto(p->func, done);
+			cg_emit_goto(p, done);
 			tb_inst_set_control(p->func, done);
 		}
 
@@ -1304,9 +1313,7 @@ gb_internal void cg_build_stmt(cgProcedure *p, Ast *node) {
 	case_end;
 
 	case_ast_node(bs, BranchStmt, node);
-		TB_Node *prev_block = tb_inst_get_control(p->func);
-
-		TB_Node *block = nullptr;
+ 		TB_Node *block = nullptr;
 
 		if (bs->label != nullptr) {
 			cgBranchBlocks bb = cg_lookup_branch_blocks(p, bs->label);
@@ -1333,9 +1340,7 @@ gb_internal void cg_build_stmt(cgProcedure *p, Ast *node) {
 		GB_ASSERT(block != nullptr);
 
 		cg_emit_defer_stmts(p, cgDeferExit_Branch, block);
-		tb_inst_goto(p->func, block);
-
-		tb_inst_set_control(p->func, prev_block);
+		cg_emit_goto(p, block);
 	case_end;
 
 	case_ast_node(es, ExprStmt, node);