Skip to content

Commit 7a25c03

Browse files
authored
cgen: simplify fixed arr return (#18380)
1 parent 1de6523 commit 7a25c03

10 files changed

Lines changed: 107 additions & 38 deletions

File tree

vlib/v/checker/checker.v

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2538,9 +2538,11 @@ pub fn (mut c Checker) expr(node_ ast.Expr) ast.Type {
25382538
tsym := c.table.sym(unwrapped_expr_type)
25392539
if tsym.kind == .array_fixed {
25402540
info := tsym.info as ast.ArrayFixed
2541-
// for dumping fixed array we must registed the fixed array struct to return from function
2542-
c.table.find_or_register_array_fixed(info.elem_type, info.size, info.size_expr,
2543-
true)
2541+
if !info.is_fn_ret {
2542+
// for dumping fixed array we must register the fixed array struct to return from function
2543+
c.table.find_or_register_array_fixed(info.elem_type, info.size, info.size_expr,
2544+
true)
2545+
}
25442546
}
25452547
type_cname := if node.expr_type.has_flag(.option) {
25462548
'_option_${tsym.cname}'

vlib/v/gen/c/assign.v

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -636,13 +636,6 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) {
636636
} else if is_fixed_array_var {
637637
// TODO Instead of the translated check, check if it's a pointer already
638638
// and don't generate memcpy &
639-
right_is_fixed_ret := !(val is ast.CallExpr
640-
&& (val as ast.CallExpr).or_block.kind == .propagate_option)
641-
&& ((right_sym.info is ast.ArrayFixed
642-
&& (right_sym.info as ast.ArrayFixed).is_fn_ret)
643-
|| (val is ast.DumpExpr && right_sym.info is ast.ArrayFixed)
644-
|| (val is ast.CallExpr
645-
&& g.table.sym(g.unwrap_generic((val as ast.CallExpr).return_type)).kind == .array_fixed))
646639
typ_str := g.typ(val_type).trim('*')
647640
final_typ_str := if is_fixed_array_var { '' } else { '(${typ_str}*)' }
648641
final_ref_str := if is_fixed_array_var {
@@ -661,9 +654,6 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) {
661654
g.expr(left)
662655
g.write(', ${final_ref_str}')
663656
g.expr(val)
664-
if right_is_fixed_ret {
665-
g.write('.ret_arr')
666-
}
667657
g.write(', sizeof(${typ_str})) /*assign*/')
668658
}
669659
} else if is_decl {

vlib/v/gen/c/auto_str_methods.v

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -649,15 +649,15 @@ fn (mut g Gen) gen_str_for_array_fixed(info ast.ArrayFixed, styp string, str_fn_
649649
is_elem_ptr := typ.is_ptr()
650650
sym_has_str_method, str_method_expects_ptr, _ := sym.str_method_info()
651651
elem_str_fn_name := g.get_str_fn(typ)
652+
def_arg := if info.is_fn_ret { '${g.typ(typ)} a[${info.size}]' } else { '${styp} a' }
652653

653-
g.definitions.writeln('static string ${str_fn_name}(${styp} a); // auto')
654-
g.auto_str_funcs.writeln('static string ${str_fn_name}(${styp} a) { return indent_${str_fn_name}(a, 0);}')
655-
g.definitions.writeln('static string indent_${str_fn_name}(${styp} a, int indent_count); // auto')
656-
g.auto_str_funcs.writeln('static string indent_${str_fn_name}(${styp} a, int indent_count) {')
654+
g.definitions.writeln('static string ${str_fn_name}(); // auto')
655+
g.auto_str_funcs.writeln('static string ${str_fn_name}(${def_arg}) { return indent_${str_fn_name}(a, 0);}')
656+
g.definitions.writeln('static string indent_${str_fn_name}(${def_arg}, int indent_count); // auto')
657+
g.auto_str_funcs.writeln('static string indent_${str_fn_name}(${def_arg}, int indent_count) {')
657658
g.auto_str_funcs.writeln('\tstrings__Builder sb = strings__new_builder(${info.size} * 10);')
658659
g.auto_str_funcs.writeln('\tstrings__Builder_write_string(&sb, _SLIT("["));')
659660
g.auto_str_funcs.writeln('\tfor (int i = 0; i < ${info.size}; ++i) {')
660-
suffix := if info.is_fn_ret { '.ret_arr' } else { '' }
661661
if sym.kind == .function {
662662
g.auto_str_funcs.writeln('\t\tstring x = ${elem_str_fn_name}();')
663663
g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, x);')
@@ -666,30 +666,30 @@ fn (mut g Gen) gen_str_for_array_fixed(info ast.ArrayFixed, styp string, str_fn_
666666
if should_use_indent_func(sym.kind) && !sym_has_str_method {
667667
if is_elem_ptr {
668668
g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, _SLIT("${deref_label}"));')
669-
g.auto_str_funcs.writeln('\t\tif ( 0 == a${suffix}[i] ) {')
669+
g.auto_str_funcs.writeln('\t\tif ( 0 == a[i] ) {')
670670
g.auto_str_funcs.writeln('\t\t\tstrings__Builder_write_string(&sb, _SLIT("0"));')
671671
g.auto_str_funcs.writeln('\t\t}else{')
672-
g.auto_str_funcs.writeln('\t\t\tstrings__Builder_write_string(&sb, ${elem_str_fn_name}( ${deref} a${suffix}[i]) );')
672+
g.auto_str_funcs.writeln('\t\t\tstrings__Builder_write_string(&sb, ${elem_str_fn_name}( ${deref} a[i]) );')
673673
g.auto_str_funcs.writeln('\t\t}')
674674
} else {
675-
g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, ${elem_str_fn_name}( ${deref} a${suffix}[i]) );')
675+
g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, ${elem_str_fn_name}( ${deref} a[i]) );')
676676
}
677677
} else if sym.kind in [.f32, .f64] {
678678
if sym.kind == .f32 {
679-
field_str := str_intp_g32('a${suffix}[i]')
679+
field_str := str_intp_g32('a[i]')
680680
g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, ${field_str} );')
681681
} else {
682-
field_str := str_intp_g64('a${suffix}[i]')
682+
field_str := str_intp_g64('a[i]')
683683
g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, ${field_str} );')
684684
}
685685
} else if sym.kind == .string {
686-
field_str := str_intp_sq('a${suffix}[i]')
686+
field_str := str_intp_sq('a[i]')
687687
g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, ${field_str});')
688688
} else if sym.kind == .rune {
689-
tmp_str := str_intp_rune('${elem_str_fn_name}( ${deref} a${suffix}[i])')
689+
tmp_str := str_intp_rune('${elem_str_fn_name}( ${deref} a[i])')
690690
g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, ${tmp_str});')
691691
} else {
692-
g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, ${elem_str_fn_name}( ${deref} a${suffix}[i]));')
692+
g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, ${elem_str_fn_name}( ${deref} a[i]));')
693693
}
694694
}
695695
g.auto_str_funcs.writeln('\t\tif (i < ${info.size - 1}) {')

vlib/v/gen/c/cgen.v

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ mut:
138138
inside_or_block bool
139139
inside_call bool
140140
inside_curry_call bool // inside foo()()!, foo()()?, foo()()
141+
expected_fixed_arr bool
141142
inside_for_c_stmt bool
142143
inside_comptime_for_field bool
143144
inside_cast_in_heap int // inside cast to interface type in heap (resolve recursive calls)
@@ -2452,11 +2453,6 @@ fn (mut g Gen) expr_with_cast(expr ast.Expr, got_type_raw ast.Type, expected_typ
24522453
}
24532454
// no cast
24542455
g.expr(expr)
2455-
if expr is ast.CallExpr && !(expr as ast.CallExpr).is_fn_var && !expected_type.has_flag(.option)
2456-
&& exp_sym.kind == .array_fixed {
2457-
// it's non-option fixed array, requires accessing .ret_arr member to get the array
2458-
g.write('.ret_arr')
2459-
}
24602456
}
24612457

24622458
fn write_octal_escape(mut b strings.Builder, c u8) {
@@ -4989,12 +4985,16 @@ fn (mut g Gen) return_stmt(node ast.Return) {
49894985
g.writeln('{0};')
49904986
if node.exprs[0] is ast.Ident {
49914987
g.write('memcpy(${tmpvar}.ret_arr, ${g.expr_string(node.exprs[0])}, sizeof(${g.typ(node.types[0])})) /*ret*/')
4992-
} else {
4988+
} else if node.exprs[0] is ast.ArrayInit {
49934989
tmpvar2 := g.new_tmp_var()
49944990
g.write('${g.typ(node.types[0])} ${tmpvar2} = ')
49954991
g.expr_with_cast(node.exprs[0], node.types[0], g.fn_decl.return_type)
49964992
g.writeln(';')
49974993
g.write('memcpy(${tmpvar}.ret_arr, ${tmpvar2}, sizeof(${g.typ(node.types[0])})) /*ret*/')
4994+
} else {
4995+
g.write('memcpy(${tmpvar}.ret_arr, ')
4996+
g.expr_with_cast(node.exprs[0], node.types[0], g.fn_decl.return_type)
4997+
g.write(', sizeof(${g.typ(node.types[0])})) /*ret*/')
49984998
}
49994999
} else {
50005000
g.expr_with_cast(node.exprs[0], node.types[0], g.fn_decl.return_type)

vlib/v/gen/c/dumpexpr.v

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ fn (mut g Gen) dump_expr(node ast.DumpExpr) {
6767
g.inside_opt_or_res = old_inside_opt_or_res
6868
}
6969
g.write(')')
70+
if (g.inside_assign || g.expected_fixed_arr) && !expr_type.has_flag(.option)
71+
&& g.table.type_kind(expr_type) == .array_fixed {
72+
g.write('.ret_arr')
73+
}
7074
}
7175

7276
fn (mut g Gen) dump_expr_definitions() {
@@ -106,8 +110,13 @@ fn (mut g Gen) dump_expr_definitions() {
106110
dump_typedefs['typedef ${str_tdef};'] = true
107111
str_dumparg_ret_type = str_dumparg_type
108112
} else if !typ.has_flag(.option) && dump_sym.kind == .array_fixed {
109-
// fixed array returned from function
110-
str_dumparg_ret_type = '_v_' + str_dumparg_type
113+
if (dump_sym.info as ast.ArrayFixed).is_fn_ret {
114+
str_dumparg_ret_type = str_dumparg_type
115+
str_dumparg_type = str_dumparg_type.trim_string_left('_v_')
116+
} else {
117+
// fixed array returned from function
118+
str_dumparg_ret_type = '_v_' + str_dumparg_type
119+
}
111120
} else {
112121
str_dumparg_ret_type = str_dumparg_type
113122
}

vlib/v/gen/c/fn.v

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1474,6 +1474,11 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
14741474
g.write(', ${array_depth}')
14751475
}
14761476
g.write(')')
1477+
if node.return_type != 0 && !node.return_type.has_flag(.option)
1478+
&& g.table.sym(node.return_type).kind == .array_fixed {
1479+
// it's non-option fixed array, requires accessing .ret_arr member to get the array
1480+
g.write('.ret_arr')
1481+
}
14771482
}
14781483

14791484
fn (mut g Gen) fn_call(node ast.CallExpr) {
@@ -1776,6 +1781,11 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
17761781
if name != '&' {
17771782
g.write(')')
17781783
}
1784+
if node.return_type != 0 && !node.return_type.has_flag(.option)
1785+
&& g.table.sym(node.return_type).kind == .array_fixed {
1786+
// it's non-option fixed array, requires accessing .ret_arr member to get the array
1787+
g.write('.ret_arr')
1788+
}
17791789
if tmp_cnt_save >= 0 {
17801790
g.writeln(';')
17811791
g.keep_alive_call_postgen(node, tmp_cnt_save)
@@ -1916,6 +1926,10 @@ fn (mut g Gen) autofree_call_postgen(node_pos int) {
19161926
}
19171927

19181928
fn (mut g Gen) call_args(node ast.CallExpr) {
1929+
g.expected_fixed_arr = true
1930+
defer {
1931+
g.expected_fixed_arr = false
1932+
}
19191933
args := if g.is_js_call {
19201934
if node.args.len < 1 {
19211935
g.error('node should have at least 1 arg', node.pos)

vlib/v/gen/c/index.v

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -368,10 +368,6 @@ fn (mut g Gen) index_of_fixed_array(node ast.IndexExpr, sym ast.TypeSymbol) {
368368
} else {
369369
g.expr(node.left)
370370
}
371-
if node.left is ast.CallExpr && sym.kind == .array_fixed
372-
&& (sym.info as ast.ArrayFixed).is_fn_ret {
373-
g.write('.ret_arr')
374-
}
375371
}
376372
g.write('[')
377373
if g.is_direct_array_access || g.pref.translated || node.index is ast.IntegerLiteral {

vlib/v/gen/c/infix.v

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ import v.token
88
import v.util
99

1010
fn (mut g Gen) infix_expr(node ast.InfixExpr) {
11+
g.expected_fixed_arr = true
12+
defer {
13+
g.expected_fixed_arr = false
14+
}
1115
if node.auto_locked != '' {
1216
g.writeln('sync__RwMutex_lock(&${node.auto_locked}->mtx);')
1317
}

vlib/v/gen/c/str.v

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,10 @@ fn (mut g Gen) string_inter_literal_sb_optimized(call_expr ast.CallExpr) {
5454
fn (mut g Gen) gen_expr_to_string(expr ast.Expr, etype ast.Type) {
5555
old_inside_opt_or_res := g.inside_opt_or_res
5656
g.inside_opt_or_res = true
57+
g.expected_fixed_arr = true
5758
defer {
5859
g.inside_opt_or_res = old_inside_opt_or_res
60+
g.expected_fixed_arr = false
5961
}
6062
is_shared := etype.has_flag(.shared_f)
6163
mut typ := etype

vlib/v/tests/fixed_array_2_test.v

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
struct Test {}
2+
3+
fn (t Test) conversion_error(value u16) [4]u8 {
4+
return conversion_error(value)
5+
}
6+
7+
fn arr_opt() ?[2]int {
8+
return [1, 2]!
9+
}
10+
11+
fn conversion_error(value u16) [4]u8 {
12+
mut return_value := [4]u8{}
13+
for i := 0; i < 4; i++ {
14+
return_value[i] = u8(value)
15+
}
16+
return return_value
17+
}
18+
19+
fn test_assign() {
20+
// -- Block below works fine
21+
value := conversion_error(42)
22+
println(value)
23+
}
24+
25+
fn test_assign_method() {
26+
value2 := Test{}.conversion_error(42)
27+
println(value2)
28+
}
29+
30+
fn test_ret() {
31+
// -- Block above works fine
32+
println(conversion_error(42))
33+
println(Test{}.conversion_error(42))
34+
}
35+
36+
fn test_assign_dump() {
37+
y := dump(conversion_error(42))
38+
dump(y)
39+
y2 := dump(Test{}.conversion_error(42))
40+
dump(y2)
41+
}
42+
43+
fn test_assert() {
44+
a := [1, 2]!
45+
assert dump(a) == [1, 2]!
46+
}
47+
48+
fn test_call() {
49+
conversion_error(42)
50+
Test{}.conversion_error(42)
51+
dump(arr_opt())
52+
}

0 commit comments

Comments
 (0)