mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-31 20:00:09 +00:00
Fix returns of tuple
This commit is contained in:
@@ -2,7 +2,18 @@
|
|||||||
#import "os.odin"
|
#import "os.odin"
|
||||||
#import "mem.odin"
|
#import "mem.odin"
|
||||||
|
|
||||||
|
|
||||||
main :: proc() {
|
main :: proc() {
|
||||||
|
x :: proc() -> (int, int) {
|
||||||
|
return 1, 2
|
||||||
|
}
|
||||||
|
y :: proc() -> (int, int) {
|
||||||
|
return x()
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.println(y())
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
arena: mem.Arena
|
arena: mem.Arena
|
||||||
mem.init_arena_from_context(^arena, 1000)
|
mem.init_arena_from_context(^arena, 1000)
|
||||||
|
|||||||
+19
-15
@@ -146,6 +146,13 @@ b32 check_is_terminating(AstNode *node) {
|
|||||||
}
|
}
|
||||||
return has_default;
|
return has_default;
|
||||||
case_end;
|
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;
|
return false;
|
||||||
@@ -160,15 +167,13 @@ Type *check_assignment_variable(Checker *c, Operand *op_a, AstNode *lhs) {
|
|||||||
AstNode *node = unparen_expr(lhs);
|
AstNode *node = unparen_expr(lhs);
|
||||||
|
|
||||||
// NOTE(bill): Ignore assignments to `_`
|
// NOTE(bill): Ignore assignments to `_`
|
||||||
if (node->kind == AstNode_Ident) {
|
if (node->kind == AstNode_Ident &&
|
||||||
ast_node(i, Ident, node);
|
node->Ident.string == make_string("_")) {
|
||||||
if (i->string == make_string("_")) {
|
add_entity_definition(&c->info, node, NULL);
|
||||||
add_entity_definition(&c->info, node, NULL);
|
check_assignment(c, op_a, NULL, make_string("assignment to `_` identifier"));
|
||||||
check_assignment(c, op_a, NULL, make_string("assignment to `_` identifier"));
|
if (op_a->mode == Addressing_Invalid)
|
||||||
if (op_a->mode == Addressing_Invalid)
|
return NULL;
|
||||||
return NULL;
|
return op_a->type;
|
||||||
return op_a->type;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Entity *e = NULL;
|
Entity *e = NULL;
|
||||||
@@ -989,17 +994,14 @@ void check_stmt(Checker *c, AstNode *node, u32 flags) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Type *proc_type = c->proc_stack[gb_array_count(c->proc_stack)-1];
|
Type *proc_type = c->proc_stack[gb_array_count(c->proc_stack)-1];
|
||||||
isize result_count = 0;
|
isize result_count = 0;
|
||||||
if (proc_type->Proc.results) {
|
if (proc_type->Proc.results) {
|
||||||
result_count = proc_type->Proc.results->Tuple.variable_count;
|
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",
|
if (result_count > 0) {
|
||||||
result_count,
|
|
||||||
(result_count != 1 ? "values" : "value"),
|
|
||||||
gb_array_count(rs->results));
|
|
||||||
} else if (result_count > 0) {
|
|
||||||
Entity **variables = NULL;
|
Entity **variables = NULL;
|
||||||
if (proc_type->Proc.results != NULL) {
|
if (proc_type->Proc.results != NULL) {
|
||||||
auto *tuple = &proc_type->Proc.results->Tuple;
|
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,
|
check_init_variables(c, variables, result_count,
|
||||||
rs->results, make_string("return statement"));
|
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;
|
case_end;
|
||||||
|
|
||||||
|
|||||||
+32
-3
@@ -3366,8 +3366,38 @@ void ssa_build_stmt(ssaProcedure *proc, AstNode *node) {
|
|||||||
ssaValue *v = NULL;
|
ssaValue *v = NULL;
|
||||||
auto *return_type_tuple = &proc->type->Proc.results->Tuple;
|
auto *return_type_tuple = &proc->type->Proc.results->Tuple;
|
||||||
isize return_count = proc->type->Proc.result_count;
|
isize return_count = proc->type->Proc.result_count;
|
||||||
if (gb_array_count(rs->results) == 1 && return_count > 1) {
|
if (gb_array_count(rs->results) < return_count) {
|
||||||
GB_PANIC("ReturnStmt tuple return statement");
|
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) {
|
} else if (return_count == 1) {
|
||||||
Entity *e = return_type_tuple->variables[0];
|
Entity *e = return_type_tuple->variables[0];
|
||||||
v = ssa_emit_conv(proc, ssa_build_expr(proc, rs->results[0]), e->type);
|
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_build_stmt(proc, pa->body);
|
||||||
ssa_emit_defer_stmts(proc, ssaDeferExit_Default, NULL);
|
ssa_emit_defer_stmts(proc, ssaDeferExit_Default, NULL);
|
||||||
|
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user