Skip to content

Commit

Permalink
cgen: fix codegen for multi return with array fixed (fix #22451) (#22454
Browse files Browse the repository at this point in the history
)
  • Loading branch information
felipensp authored Oct 9, 2024
1 parent 875faaf commit 8fcf3d7
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 10 deletions.
2 changes: 1 addition & 1 deletion vlib/v/gen/c/assign.v
Original file line number Diff line number Diff line change
Expand Up @@ -910,7 +910,7 @@ fn (mut g Gen) gen_multi_return_assign(node &ast.AssignStmt, return_type ast.Typ
}
} else {
g.expr(lx)
sym := g.table.sym(node.left_types[i])
sym := g.table.final_sym(node.left_types[i])
if sym.kind == .array_fixed {
g.writeln(';')
g.writeln('memcpy(&${g.expr_string(lx)}, &${mr_var_name}.arg${i}, sizeof(${styp}));')
Expand Down
34 changes: 25 additions & 9 deletions vlib/v/gen/c/cgen.v
Original file line number Diff line number Diff line change
Expand Up @@ -5504,6 +5504,7 @@ fn (mut g Gen) return_stmt(node ast.Return) {
|| g.cur_lock.lockeds.len > 0
|| (fn_return_is_multi && node.exprs.len >= 1 && fn_return_is_option)
|| fn_return_is_fixed_array
|| (fn_return_is_multi && node.types.any(g.table.final_sym(it).kind == .array_fixed))
// handle promoting none/error/function returning _option'
if fn_return_is_option {
option_none := node.exprs[0] is ast.None
Expand Down Expand Up @@ -5603,6 +5604,7 @@ fn (mut g Gen) return_stmt(node ast.Return) {
}
// Use this to keep the tmp assignments in order
mut multi_unpack := ''
mut final_assignments := ''
g.write('(${styp}){')
mut arg_idx := 0
for i, expr in node.exprs {
Expand Down Expand Up @@ -5639,17 +5641,27 @@ fn (mut g Gen) return_stmt(node ast.Return) {
continue
}
g.write('.arg${arg_idx}=')
if expr.is_auto_deref_var() {
g.write('*')
}
if mr_info.types[i].has_flag(.option) {
g.expr_with_opt(expr, node.types[i], mr_info.types[i])
} else if g.table.sym(mr_info.types[i]).kind in [.sum_type, .interface_] {
g.expr_with_cast(expr, node.types[i], mr_info.types[i])
} else {
if expr !is ast.ArrayInit && g.table.final_sym(node.types[i]).kind == .array_fixed {
line := g.go_before_last_stmt().trim_space()
expr_styp := g.typ(node.types[i])
g.write('memcpy(&${tmpvar}.arg${arg_idx}, ')
g.expr(expr)
g.writeln(', sizeof(${expr_styp}));')
final_assignments += g.go_before_last_stmt() + '\t'
g.write(line)
g.write('{0}')
} else {
if expr.is_auto_deref_var() {
g.write('*')
}
if mr_info.types[i].has_flag(.option) {
g.expr_with_opt(expr, node.types[i], mr_info.types[i])
} else if g.table.sym(mr_info.types[i]).kind in [.sum_type, .interface_] {
g.expr_with_cast(expr, node.types[i], mr_info.types[i])
} else {
g.expr(expr)
}
}

if i < node.exprs.len - 1 {
g.write(', ')
}
Expand All @@ -5669,6 +5681,10 @@ fn (mut g Gen) return_stmt(node ast.Return) {
if multi_unpack != '' {
g.insert_before_stmt(multi_unpack)
}
if final_assignments != '' {
g.writeln(';')
g.write(final_assignments)
}
if use_tmp_var && !fn_return_is_option && !fn_return_is_result {
if !has_semicolon {
g.writeln(';')
Expand Down
19 changes: 19 additions & 0 deletions vlib/v/tests/fns/multi_return_array_fixed_test.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
module main

type Mat4 = [2]f32

struct GameObject {
mut:
rot Mat4 = Mat4([f32(1.1), 2.2]!)
transform Mat4 = Mat4([f32(1.1), 2.2]!)
}

fn (g GameObject) calc() (Mat4, Mat4) {
return g.rot, g.transform
}

fn test_main() {
x, y := GameObject{}.calc()
assert x == Mat4([f32(1.1), 2.2]!)
assert y == Mat4([f32(1.1), 2.2]!)
}

0 comments on commit 8fcf3d7

Please sign in to comment.