Browse Source

Improve behaviour of `return` with named results to aid with `defer` statements

gingerBill 5 years ago
parent
commit
99944f3b02
2 changed files with 51 additions and 1 deletions
  1. 25 0
      src/ir.cpp
  2. 26 1
      src/llvm_backend.cpp

+ 25 - 0
src/ir.cpp

@@ -10164,6 +10164,14 @@ void ir_build_stmt_internal(irProcedure *proc, Ast *node) {
 				v = ir_build_expr(proc, rs->results[0]);
 				v = ir_build_expr(proc, rs->results[0]);
 				v = ir_emit_conv(proc, v, e->type);
 				v = ir_emit_conv(proc, v, e->type);
 			}
 			}
+			if (proc->type->Proc.has_named_results) {
+				// NOTE(bill): store the named values before returning
+				if (e->token.string != "") {
+					irValue **found = map_get(&proc->module->values, hash_entity(e));
+					GB_ASSERT(found != nullptr);
+					ir_emit_store(proc, *found, v);
+				}
+			}
 		} else {
 		} else {
 			gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&proc->module->tmp_arena);
 			gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&proc->module->tmp_arena);
 			defer (gb_temp_arena_memory_end(tmp));
 			defer (gb_temp_arena_memory_end(tmp));
@@ -10196,6 +10204,23 @@ void ir_build_stmt_internal(irProcedure *proc, Ast *node) {
 
 
 			GB_ASSERT(results.count == return_count);
 			GB_ASSERT(results.count == return_count);
 
 
+			if (proc->type->Proc.has_named_results) {
+				// NOTE(bill): store the named values before returning
+				for_array(i, tuple->variables) {
+					Entity *e = tuple->variables[i];
+					if (e->kind != Entity_Variable) {
+						continue;
+					}
+
+					if (e->token.string == "") {
+						continue;
+					}
+					irValue **found = map_get(&proc->module->values, hash_entity(e));
+					GB_ASSERT(found != nullptr);
+					ir_emit_store(proc, *found, results[i]);
+				}
+			}
+
 			Type *ret_type = proc->type->Proc.results;
 			Type *ret_type = proc->type->Proc.results;
 			// NOTE(bill): Doesn't need to be zero because it will be initialized in the loops
 			// NOTE(bill): Doesn't need to be zero because it will be initialized in the loops
 			v = ir_add_local_generated(proc, ret_type, false);
 			v = ir_add_local_generated(proc, ret_type, false);

+ 26 - 1
src/llvm_backend.cpp

@@ -2434,7 +2434,6 @@ void lb_begin_procedure_body(lbProcedure *p) {
 	if (p->type->Proc.has_named_results) {
 	if (p->type->Proc.has_named_results) {
 		GB_ASSERT(p->type->Proc.result_count > 0);
 		GB_ASSERT(p->type->Proc.result_count > 0);
 		TypeTuple *results = &p->type->Proc.results->Tuple;
 		TypeTuple *results = &p->type->Proc.results->Tuple;
-		LLVMValueRef return_ptr = LLVMGetParam(p->value, 0);
 
 
 		isize result_index = 0;
 		isize result_index = 0;
 
 
@@ -4192,6 +4191,15 @@ void lb_build_stmt(lbProcedure *p, Ast *node) {
 				res = lb_build_expr(p, rs->results[0]);
 				res = lb_build_expr(p, rs->results[0]);
 				res = lb_emit_conv(p, res, e->type);
 				res = lb_emit_conv(p, res, e->type);
 			}
 			}
+			if (p->type->Proc.has_named_results) {
+				// NOTE(bill): store the named values before returning
+				if (e->token.string != "") {
+					lbValue *found = map_get(&p->module->values, hash_entity(e));
+					GB_ASSERT(found != nullptr);
+					lb_emit_store(p, *found, res);
+				}
+			}
+
 		} else {
 		} else {
 			auto results = array_make<lbValue>(heap_allocator(), 0, return_count);
 			auto results = array_make<lbValue>(heap_allocator(), 0, return_count);
 
 
@@ -4221,6 +4229,23 @@ void lb_build_stmt(lbProcedure *p, Ast *node) {
 
 
 			GB_ASSERT(results.count == return_count);
 			GB_ASSERT(results.count == return_count);
 
 
+			if (p->type->Proc.has_named_results) {
+				// NOTE(bill): store the named values before returning
+				for_array(i, p->type->Proc.results->Tuple.variables) {
+					Entity *e = p->type->Proc.results->Tuple.variables[i];
+					if (e->kind != Entity_Variable) {
+						continue;
+					}
+
+					if (e->token.string == "") {
+						continue;
+					}
+					lbValue *found = map_get(&p->module->values, hash_entity(e));
+					GB_ASSERT(found != nullptr);
+					lb_emit_store(p, *found, results[i]);
+				}
+			}
+
 			Type *ret_type = p->type->Proc.results;
 			Type *ret_type = p->type->Proc.results;
 			// NOTE(bill): Doesn't need to be zero because it will be initialized in the loops
 			// NOTE(bill): Doesn't need to be zero because it will be initialized in the loops
 			res = lb_add_local_generated(p, ret_type, false).addr;
 			res = lb_add_local_generated(p, ret_type, false).addr;