diff --git a/code/demo.odin b/code/demo.odin index 10d0009f8..7e4e5eed7 100644 --- a/code/demo.odin +++ b/code/demo.odin @@ -2,7 +2,18 @@ #import "os.odin" #import "mem.odin" + main :: proc() { + x :: proc() -> (int, int) { + return 1, 2 + } + y :: proc() -> (int, int) { + return x() + } + + fmt.println(y()) + + arena: mem.Arena mem.init_arena_from_context(^arena, 1000) diff --git a/src/checker/stmt.cpp b/src/checker/stmt.cpp index 04df70ffb..20d4bb904 100644 --- a/src/checker/stmt.cpp +++ b/src/checker/stmt.cpp @@ -146,6 +146,13 @@ b32 check_is_terminating(AstNode *node) { } return has_default; case_end; + + case_ast_node(pa, PushAllocator, node); + return check_is_terminating(pa->body); + case_end; + case_ast_node(pc, PushContext, node); + return check_is_terminating(pc->body); + case_end; } return false; @@ -160,15 +167,13 @@ Type *check_assignment_variable(Checker *c, Operand *op_a, AstNode *lhs) { AstNode *node = unparen_expr(lhs); // NOTE(bill): Ignore assignments to `_` - if (node->kind == AstNode_Ident) { - ast_node(i, Ident, node); - if (i->string == make_string("_")) { - add_entity_definition(&c->info, node, NULL); - check_assignment(c, op_a, NULL, make_string("assignment to `_` identifier")); - if (op_a->mode == Addressing_Invalid) - return NULL; - return op_a->type; - } + if (node->kind == AstNode_Ident && + node->Ident.string == make_string("_")) { + add_entity_definition(&c->info, node, NULL); + check_assignment(c, op_a, NULL, make_string("assignment to `_` identifier")); + if (op_a->mode == Addressing_Invalid) + return NULL; + return op_a->type; } Entity *e = NULL; @@ -989,17 +994,14 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) { break; } + Type *proc_type = c->proc_stack[gb_array_count(c->proc_stack)-1]; isize result_count = 0; if (proc_type->Proc.results) { result_count = proc_type->Proc.results->Tuple.variable_count; } - if (result_count != gb_array_count(rs->results)) { - error(rs->token, "Expected %td return %s, got %td", - result_count, - (result_count != 1 ? "values" : "value"), - gb_array_count(rs->results)); - } else if (result_count > 0) { + + if (result_count > 0) { Entity **variables = NULL; if (proc_type->Proc.results != NULL) { auto *tuple = &proc_type->Proc.results->Tuple; @@ -1007,6 +1009,8 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) { } check_init_variables(c, variables, result_count, rs->results, make_string("return statement")); + } else if (gb_array_count(rs->results) > 0) { + error(ast_node_token(rs->results[0]), "No result values expected"); } case_end; diff --git a/src/codegen/ssa.cpp b/src/codegen/ssa.cpp index aeb7d0de6..6226424dd 100644 --- a/src/codegen/ssa.cpp +++ b/src/codegen/ssa.cpp @@ -3366,8 +3366,38 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { ssaValue *v = NULL; auto *return_type_tuple = &proc->type->Proc.results->Tuple; isize return_count = proc->type->Proc.result_count; - if (gb_array_count(rs->results) == 1 && return_count > 1) { - GB_PANIC("ReturnStmt tuple return statement"); + if (gb_array_count(rs->results) < return_count) { + gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&proc->module->tmp_arena); + defer (gb_temp_arena_memory_end(tmp)); + + gbArray(ssaValue *) results; + gb_array_init_reserve(results, proc->module->tmp_allocator, return_count); + + gb_for_array(res_index, rs->results) { + ssaValue *res = ssa_build_expr(proc, rs->results[res_index]); + Type *t = ssa_type(res); + if (t->kind == Type_Tuple) { + for (isize i = 0; i < t->Tuple.variable_count; i++) { + Entity *e = t->Tuple.variables[i]; + ssaValue *v = ssa_emit_struct_ev(proc, res, i, e->type); + gb_array_append(results, v); + } + } else { + gb_array_append(results, res); + } + } + + Type *ret_type = proc->type->Proc.results; + v = ssa_add_local_generated(proc, ret_type); + gb_for_array(i, results) { + Type *t = return_type_tuple->variables[i]->type; + ssaValue *e = ssa_emit_conv(proc, results[i], t); + ssaValue *gep = ssa_emit_struct_gep(proc, v, i, make_type_pointer(proc->module->allocator, t)); + ssa_emit_store(proc, gep, e); + } + + v = ssa_emit_load(proc, v); + } else if (return_count == 1) { Entity *e = return_type_tuple->variables[0]; v = ssa_emit_conv(proc, ssa_build_expr(proc, rs->results[0]), e->type); @@ -3732,7 +3762,6 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) { ssa_build_stmt(proc, pa->body); ssa_emit_defer_stmts(proc, ssaDeferExit_Default, NULL); - case_end;