1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

cgen: simplify fixed arr return (#18380)

This commit is contained in:
Felipe Pena 2023-06-09 08:34:32 -03:00 committed by GitHub
parent 1de6523da5
commit 7a25c03aa7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 107 additions and 38 deletions

View File

@ -2538,10 +2538,12 @@ pub fn (mut c Checker) expr(node_ ast.Expr) ast.Type {
tsym := c.table.sym(unwrapped_expr_type)
if tsym.kind == .array_fixed {
info := tsym.info as ast.ArrayFixed
// for dumping fixed array we must registed the fixed array struct to return from function
if !info.is_fn_ret {
// for dumping fixed array we must register the fixed array struct to return from function
c.table.find_or_register_array_fixed(info.elem_type, info.size, info.size_expr,
true)
}
}
type_cname := if node.expr_type.has_flag(.option) {
'_option_${tsym.cname}'
} else {

View File

@ -636,13 +636,6 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) {
} else if is_fixed_array_var {
// TODO Instead of the translated check, check if it's a pointer already
// and don't generate memcpy &
right_is_fixed_ret := !(val is ast.CallExpr
&& (val as ast.CallExpr).or_block.kind == .propagate_option)
&& ((right_sym.info is ast.ArrayFixed
&& (right_sym.info as ast.ArrayFixed).is_fn_ret)
|| (val is ast.DumpExpr && right_sym.info is ast.ArrayFixed)
|| (val is ast.CallExpr
&& g.table.sym(g.unwrap_generic((val as ast.CallExpr).return_type)).kind == .array_fixed))
typ_str := g.typ(val_type).trim('*')
final_typ_str := if is_fixed_array_var { '' } else { '(${typ_str}*)' }
final_ref_str := if is_fixed_array_var {
@ -661,9 +654,6 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) {
g.expr(left)
g.write(', ${final_ref_str}')
g.expr(val)
if right_is_fixed_ret {
g.write('.ret_arr')
}
g.write(', sizeof(${typ_str})) /*assign*/')
}
} else if is_decl {

View File

@ -649,15 +649,15 @@ fn (mut g Gen) gen_str_for_array_fixed(info ast.ArrayFixed, styp string, str_fn_
is_elem_ptr := typ.is_ptr()
sym_has_str_method, str_method_expects_ptr, _ := sym.str_method_info()
elem_str_fn_name := g.get_str_fn(typ)
def_arg := if info.is_fn_ret { '${g.typ(typ)} a[${info.size}]' } else { '${styp} a' }
g.definitions.writeln('static string ${str_fn_name}(${styp} a); // auto')
g.auto_str_funcs.writeln('static string ${str_fn_name}(${styp} a) { return indent_${str_fn_name}(a, 0);}')
g.definitions.writeln('static string indent_${str_fn_name}(${styp} a, int indent_count); // auto')
g.auto_str_funcs.writeln('static string indent_${str_fn_name}(${styp} a, int indent_count) {')
g.definitions.writeln('static string ${str_fn_name}(); // auto')
g.auto_str_funcs.writeln('static string ${str_fn_name}(${def_arg}) { return indent_${str_fn_name}(a, 0);}')
g.definitions.writeln('static string indent_${str_fn_name}(${def_arg}, int indent_count); // auto')
g.auto_str_funcs.writeln('static string indent_${str_fn_name}(${def_arg}, int indent_count) {')
g.auto_str_funcs.writeln('\tstrings__Builder sb = strings__new_builder(${info.size} * 10);')
g.auto_str_funcs.writeln('\tstrings__Builder_write_string(&sb, _SLIT("["));')
g.auto_str_funcs.writeln('\tfor (int i = 0; i < ${info.size}; ++i) {')
suffix := if info.is_fn_ret { '.ret_arr' } else { '' }
if sym.kind == .function {
g.auto_str_funcs.writeln('\t\tstring x = ${elem_str_fn_name}();')
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_
if should_use_indent_func(sym.kind) && !sym_has_str_method {
if is_elem_ptr {
g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, _SLIT("${deref_label}"));')
g.auto_str_funcs.writeln('\t\tif ( 0 == a${suffix}[i] ) {')
g.auto_str_funcs.writeln('\t\tif ( 0 == a[i] ) {')
g.auto_str_funcs.writeln('\t\t\tstrings__Builder_write_string(&sb, _SLIT("0"));')
g.auto_str_funcs.writeln('\t\t}else{')
g.auto_str_funcs.writeln('\t\t\tstrings__Builder_write_string(&sb, ${elem_str_fn_name}( ${deref} a${suffix}[i]) );')
g.auto_str_funcs.writeln('\t\t\tstrings__Builder_write_string(&sb, ${elem_str_fn_name}( ${deref} a[i]) );')
g.auto_str_funcs.writeln('\t\t}')
} else {
g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, ${elem_str_fn_name}( ${deref} a${suffix}[i]) );')
g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, ${elem_str_fn_name}( ${deref} a[i]) );')
}
} else if sym.kind in [.f32, .f64] {
if sym.kind == .f32 {
field_str := str_intp_g32('a${suffix}[i]')
field_str := str_intp_g32('a[i]')
g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, ${field_str} );')
} else {
field_str := str_intp_g64('a${suffix}[i]')
field_str := str_intp_g64('a[i]')
g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, ${field_str} );')
}
} else if sym.kind == .string {
field_str := str_intp_sq('a${suffix}[i]')
field_str := str_intp_sq('a[i]')
g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, ${field_str});')
} else if sym.kind == .rune {
tmp_str := str_intp_rune('${elem_str_fn_name}( ${deref} a${suffix}[i])')
tmp_str := str_intp_rune('${elem_str_fn_name}( ${deref} a[i])')
g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, ${tmp_str});')
} else {
g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, ${elem_str_fn_name}( ${deref} a${suffix}[i]));')
g.auto_str_funcs.writeln('\t\tstrings__Builder_write_string(&sb, ${elem_str_fn_name}( ${deref} a[i]));')
}
}
g.auto_str_funcs.writeln('\t\tif (i < ${info.size - 1}) {')

View File

@ -138,6 +138,7 @@ mut:
inside_or_block bool
inside_call bool
inside_curry_call bool // inside foo()()!, foo()()?, foo()()
expected_fixed_arr bool
inside_for_c_stmt bool
inside_comptime_for_field bool
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
}
// no cast
g.expr(expr)
if expr is ast.CallExpr && !(expr as ast.CallExpr).is_fn_var && !expected_type.has_flag(.option)
&& exp_sym.kind == .array_fixed {
// it's non-option fixed array, requires accessing .ret_arr member to get the array
g.write('.ret_arr')
}
}
fn write_octal_escape(mut b strings.Builder, c u8) {
@ -4989,12 +4985,16 @@ fn (mut g Gen) return_stmt(node ast.Return) {
g.writeln('{0};')
if node.exprs[0] is ast.Ident {
g.write('memcpy(${tmpvar}.ret_arr, ${g.expr_string(node.exprs[0])}, sizeof(${g.typ(node.types[0])})) /*ret*/')
} else {
} else if node.exprs[0] is ast.ArrayInit {
tmpvar2 := g.new_tmp_var()
g.write('${g.typ(node.types[0])} ${tmpvar2} = ')
g.expr_with_cast(node.exprs[0], node.types[0], g.fn_decl.return_type)
g.writeln(';')
g.write('memcpy(${tmpvar}.ret_arr, ${tmpvar2}, sizeof(${g.typ(node.types[0])})) /*ret*/')
} else {
g.write('memcpy(${tmpvar}.ret_arr, ')
g.expr_with_cast(node.exprs[0], node.types[0], g.fn_decl.return_type)
g.write(', sizeof(${g.typ(node.types[0])})) /*ret*/')
}
} else {
g.expr_with_cast(node.exprs[0], node.types[0], g.fn_decl.return_type)

View File

@ -67,6 +67,10 @@ fn (mut g Gen) dump_expr(node ast.DumpExpr) {
g.inside_opt_or_res = old_inside_opt_or_res
}
g.write(')')
if (g.inside_assign || g.expected_fixed_arr) && !expr_type.has_flag(.option)
&& g.table.type_kind(expr_type) == .array_fixed {
g.write('.ret_arr')
}
}
fn (mut g Gen) dump_expr_definitions() {
@ -106,8 +110,13 @@ fn (mut g Gen) dump_expr_definitions() {
dump_typedefs['typedef ${str_tdef};'] = true
str_dumparg_ret_type = str_dumparg_type
} else if !typ.has_flag(.option) && dump_sym.kind == .array_fixed {
if (dump_sym.info as ast.ArrayFixed).is_fn_ret {
str_dumparg_ret_type = str_dumparg_type
str_dumparg_type = str_dumparg_type.trim_string_left('_v_')
} else {
// fixed array returned from function
str_dumparg_ret_type = '_v_' + str_dumparg_type
}
} else {
str_dumparg_ret_type = str_dumparg_type
}

View File

@ -1474,6 +1474,11 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
g.write(', ${array_depth}')
}
g.write(')')
if node.return_type != 0 && !node.return_type.has_flag(.option)
&& g.table.sym(node.return_type).kind == .array_fixed {
// it's non-option fixed array, requires accessing .ret_arr member to get the array
g.write('.ret_arr')
}
}
fn (mut g Gen) fn_call(node ast.CallExpr) {
@ -1776,6 +1781,11 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
if name != '&' {
g.write(')')
}
if node.return_type != 0 && !node.return_type.has_flag(.option)
&& g.table.sym(node.return_type).kind == .array_fixed {
// it's non-option fixed array, requires accessing .ret_arr member to get the array
g.write('.ret_arr')
}
if tmp_cnt_save >= 0 {
g.writeln(';')
g.keep_alive_call_postgen(node, tmp_cnt_save)
@ -1916,6 +1926,10 @@ fn (mut g Gen) autofree_call_postgen(node_pos int) {
}
fn (mut g Gen) call_args(node ast.CallExpr) {
g.expected_fixed_arr = true
defer {
g.expected_fixed_arr = false
}
args := if g.is_js_call {
if node.args.len < 1 {
g.error('node should have at least 1 arg', node.pos)

View File

@ -368,10 +368,6 @@ fn (mut g Gen) index_of_fixed_array(node ast.IndexExpr, sym ast.TypeSymbol) {
} else {
g.expr(node.left)
}
if node.left is ast.CallExpr && sym.kind == .array_fixed
&& (sym.info as ast.ArrayFixed).is_fn_ret {
g.write('.ret_arr')
}
}
g.write('[')
if g.is_direct_array_access || g.pref.translated || node.index is ast.IntegerLiteral {

View File

@ -8,6 +8,10 @@ import v.token
import v.util
fn (mut g Gen) infix_expr(node ast.InfixExpr) {
g.expected_fixed_arr = true
defer {
g.expected_fixed_arr = false
}
if node.auto_locked != '' {
g.writeln('sync__RwMutex_lock(&${node.auto_locked}->mtx);')
}

View File

@ -54,8 +54,10 @@ fn (mut g Gen) string_inter_literal_sb_optimized(call_expr ast.CallExpr) {
fn (mut g Gen) gen_expr_to_string(expr ast.Expr, etype ast.Type) {
old_inside_opt_or_res := g.inside_opt_or_res
g.inside_opt_or_res = true
g.expected_fixed_arr = true
defer {
g.inside_opt_or_res = old_inside_opt_or_res
g.expected_fixed_arr = false
}
is_shared := etype.has_flag(.shared_f)
mut typ := etype

View File

@ -0,0 +1,52 @@
struct Test {}
fn (t Test) conversion_error(value u16) [4]u8 {
return conversion_error(value)
}
fn arr_opt() ?[2]int {
return [1, 2]!
}
fn conversion_error(value u16) [4]u8 {
mut return_value := [4]u8{}
for i := 0; i < 4; i++ {
return_value[i] = u8(value)
}
return return_value
}
fn test_assign() {
// -- Block below works fine
value := conversion_error(42)
println(value)
}
fn test_assign_method() {
value2 := Test{}.conversion_error(42)
println(value2)
}
fn test_ret() {
// -- Block above works fine
println(conversion_error(42))
println(Test{}.conversion_error(42))
}
fn test_assign_dump() {
y := dump(conversion_error(42))
dump(y)
y2 := dump(Test{}.conversion_error(42))
dump(y2)
}
fn test_assert() {
a := [1, 2]!
assert dump(a) == [1, 2]!
}
fn test_call() {
conversion_error(42)
Test{}.conversion_error(42)
dump(arr_opt())
}