From ca48d7da37fcc08ad022d7d70c0f60bd56268ecf Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Wed, 8 Jan 2025 15:41:36 -0300 Subject: [PATCH] cgen: cache return_stmt()'s node.exprs[0] and node.types[0] (#23408) --- vlib/v/gen/c/cgen.v | 127 ++++++++++++++++++++++---------------------- 1 file changed, 63 insertions(+), 64 deletions(-) diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index b78c80b32b37e4..c600483c912c5c 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -5521,11 +5521,14 @@ fn (mut g Gen) return_stmt(node ast.Return) { g.inside_return = old_inside_return } + expr0 := if node.exprs.len > 0 { node.exprs[0] } else { ast.empty_expr } + type0 := if node.exprs.len > 0 { node.types[0] } else { ast.void_type } + if node.exprs.len > 0 { // skip `return $vweb.html()` - if node.exprs[0] is ast.ComptimeCall && node.exprs[0].is_vweb { + if expr0 is ast.ComptimeCall && expr0.is_vweb { g.inside_return_tmpl = true - g.expr(node.exprs[0]) + g.expr(expr0) g.inside_return_tmpl = false g.writeln(';') return @@ -5571,19 +5574,18 @@ fn (mut g Gen) return_stmt(node ast.Return) { ret_typ := g.ret_styp(g.unwrap_generic(fn_ret_type)) // `return fn_call_opt()` - if node.exprs.len == 1 && (fn_return_is_option || fn_return_is_result) - && node.exprs[0] is ast.CallExpr && node.exprs[0].return_type == g.fn_decl.return_type - && node.exprs[0].or_block.kind == .absent { + if node.exprs.len == 1 && (fn_return_is_option || fn_return_is_result) && expr0 is ast.CallExpr + && expr0.return_type == g.fn_decl.return_type && expr0.or_block.kind == .absent { if g.defer_stmts.len > 0 { g.write('${ret_typ} ${tmpvar} = ') - g.expr(node.exprs[0]) + g.expr(expr0) g.writeln(';') g.write_defer_stmts_when_needed() g.writeln('return ${tmpvar};') } else { g.write_defer_stmts_when_needed() g.write('return ') - g.expr(node.exprs[0]) + g.expr(expr0) g.writeln(';') } return @@ -5595,14 +5597,14 @@ fn (mut g Gen) return_stmt(node ast.Return) { || (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 - ftyp := g.styp(node.types[0]) + option_none := expr0 is ast.None + ftyp := g.styp(type0) mut is_regular_option := ftyp == '_option' - if option_none || is_regular_option || node.types[0] == ast.error_type_idx { + if option_none || is_regular_option || type0 == ast.error_type_idx { if g.fn_decl != unsafe { nil } && g.fn_decl.is_test { test_error_var := g.new_tmp_var() g.write('${ret_typ} ${test_error_var} = ') - g.gen_option_error(fn_ret_type, node.exprs[0]) + g.gen_option_error(fn_ret_type, expr0) g.writeln(';') g.write_defer_stmts_when_needed() g.gen_failing_return_error_for_test_fn(node, test_error_var) @@ -5613,7 +5615,7 @@ fn (mut g Gen) return_stmt(node ast.Return) { } else { g.write('return ') } - g.gen_option_error(fn_ret_type, node.exprs[0]) + g.gen_option_error(fn_ret_type, expr0) g.writeln(';') if use_tmp_var { // handle options when returning `none` for `?(int, ?int)` @@ -5635,13 +5637,13 @@ fn (mut g Gen) return_stmt(node ast.Return) { } // handle promoting error/function returning result if fn_return_is_result { - ftyp := g.styp(node.types[0]) + ftyp := g.styp(type0) mut is_regular_result := ftyp == result_name - if is_regular_result || node.types[0] == ast.error_type_idx { + if is_regular_result || type0 == ast.error_type_idx { if g.fn_decl != unsafe { nil } && g.fn_decl.is_test { test_error_var := g.new_tmp_var() g.write('${ret_typ} ${test_error_var} = ') - g.gen_result_error(fn_ret_type, node.exprs[0]) + g.gen_result_error(fn_ret_type, expr0) g.writeln(';') g.write_defer_stmts_when_needed() g.gen_failing_return_error_for_test_fn(node, test_error_var) @@ -5652,7 +5654,7 @@ fn (mut g Gen) return_stmt(node ast.Return) { } else { g.write('return ') } - g.gen_result_error(fn_ret_type, node.exprs[0]) + g.gen_result_error(fn_ret_type, expr0) g.writeln(';') if use_tmp_var { g.write_defer_stmts_when_needed() @@ -5662,11 +5664,11 @@ fn (mut g Gen) return_stmt(node ast.Return) { } } // regular cases - if fn_return_is_multi && node.exprs.len > 0 && !g.expr_is_multi_return_call(node.exprs[0]) { - if node.exprs.len == 1 && (node.exprs[0] is ast.IfExpr || node.exprs[0] is ast.MatchExpr) { + if fn_return_is_multi && node.exprs.len > 0 && !g.expr_is_multi_return_call(expr0) { + if node.exprs.len == 1 && (expr0 is ast.IfExpr || expr0 is ast.MatchExpr) { // use a temporary for `return if cond { x,y } else { a,b }` or `return match expr { abc { x, y } else { z, w } }` g.write('${ret_typ} ${tmpvar} = ') - g.expr(node.exprs[0]) + g.expr(expr0) g.writeln(';') g.write_defer_stmts_when_needed() g.writeln('return ${tmpvar};') @@ -5786,30 +5788,29 @@ fn (mut g Gen) return_stmt(node ast.Return) { node.pos) } // normal return - return_sym := g.table.final_sym(g.unwrap_generic(node.types[0])) - expr0 := node.exprs[0] + return_sym := g.table.final_sym(g.unwrap_generic(type0)) // `return opt_ok(expr)` for functions that expect an option expr_type_is_opt := match expr0 { ast.CallExpr { expr0.return_type.has_flag(.option) && expr0.or_block.kind == .absent } else { - node.types[0].has_flag(.option) + type0.has_flag(.option) } } if fn_return_is_option && !expr_type_is_opt && return_sym.name != option_name { if fn_return_is_fixed_array && (expr0 in [ast.StructInit, ast.CallExpr, ast.CastExpr] || (expr0 is ast.ArrayInit && expr0.has_callexpr)) - && g.table.final_sym(node.types[0]).kind == .array_fixed { + && g.table.final_sym(type0).kind == .array_fixed { styp := g.styp(fn_ret_type.clear_option_and_result()) if expr0 is ast.CallExpr { - tmp_var := g.expr_with_fixed_array(expr0, node.types[0], fn_ret_type) + tmp_var := g.expr_with_fixed_array(expr0, type0, fn_ret_type) g.writeln('${ret_typ} ${tmpvar} = ${tmp_var};') } else { g.writeln('${ret_typ} ${tmpvar} = (${ret_typ}){ .state=0, .err=_const_none__, .data={EMPTY_STRUCT_INITIALIZATION} };') if expr0 is ast.StructInit { g.write('memcpy(${tmpvar}.data, ') - tmp_var := g.expr_with_opt(expr0, node.types[0], fn_ret_type) + tmp_var := g.expr_with_opt(expr0, type0, fn_ret_type) g.writeln('.data, sizeof(${styp}));') if tmp_var != '' { g.writeln('${tmpvar}.state = ${tmp_var}.state;') @@ -5824,8 +5825,8 @@ fn (mut g Gen) return_stmt(node ast.Return) { g.writeln('${ret_typ} ${tmpvar};') styp := g.base_type(fn_ret_type) g.write('_option_ok(&(${styp}[]) { ') - if !g.unwrap_generic(fn_ret_type).is_ptr() && node.types[0].is_ptr() { - if !(node.exprs[0] is ast.Ident && !g.is_amp) { + if !g.unwrap_generic(fn_ret_type).is_ptr() && type0.is_ptr() { + if !(expr0 is ast.Ident && !g.is_amp) { g.write('*') } } @@ -5834,7 +5835,7 @@ fn (mut g Gen) return_stmt(node ast.Return) { g.fixed_array_var_init(g.expr_string(expr0), expr0.is_auto_deref_var(), info.elem_type, info.size) } else { - g.expr_with_cast(expr0, node.types[0], fn_ret_type.clear_option_and_result()) + g.expr_with_cast(expr0, type0, fn_ret_type.clear_option_and_result()) } g.writeln(' }, (${option_name}*)(&${tmpvar}), sizeof(${styp}));') } @@ -5848,17 +5849,17 @@ fn (mut g Gen) return_stmt(node ast.Return) { expr0.return_type.has_flag(.result) && expr0.or_block.kind == .absent } else { - node.types[0].has_flag(.result) + type0.has_flag(.result) } } if fn_return_is_result && !expr_type_is_result && return_sym.name != result_name { g.writeln('${ret_typ} ${tmpvar} = {0};') if fn_return_is_fixed_array && expr0 !is ast.ArrayInit - && g.table.final_sym(node.types[0]).kind == .array_fixed { + && g.table.final_sym(type0).kind == .array_fixed { styp := g.styp(fn_ret_type.clear_option_and_result()) g.write('memcpy(${tmpvar}.data, ') if expr0 in [ast.CallExpr, ast.StructInit] { - g.expr_with_opt(expr0, node.types[0], fn_ret_type) + g.expr_with_opt(expr0, type0, fn_ret_type) g.write('.data') } else { g.expr(expr0) @@ -5867,19 +5868,19 @@ fn (mut g Gen) return_stmt(node ast.Return) { } else { styp := g.base_type(fn_ret_type) g.write('_result_ok(&(${styp}[]) { ') - if !fn_ret_type.is_ptr() && node.types[0].is_ptr() { - if !((node.exprs[0] is ast.Ident && !g.is_amp) || sym.kind == .interface) { + if !fn_ret_type.is_ptr() && type0.is_ptr() { + if !((expr0 is ast.Ident && !g.is_amp) || sym.kind == .interface) { g.write('*') } } if fn_ret_type.has_flag(.option) { - g.expr_with_opt(expr0, node.types[0], fn_ret_type.clear_flag(.result)) + g.expr_with_opt(expr0, type0, fn_ret_type.clear_flag(.result)) } else if return_sym.kind == .array_fixed && expr0 !is ast.ArrayInit { info := return_sym.info as ast.ArrayFixed g.fixed_array_var_init(g.expr_string(expr0), expr0.is_auto_deref_var(), info.elem_type, info.size) } else { - g.expr_with_cast(expr0, node.types[0], fn_ret_type.clear_flag(.result)) + g.expr_with_cast(expr0, type0, fn_ret_type.clear_flag(.result)) } g.writeln(' }, (${result_name}*)(&${tmpvar}), sizeof(${styp}));') } @@ -5892,12 +5893,11 @@ fn (mut g Gen) return_stmt(node ast.Return) { // set free_parent_scopes to true, since all variables defined in parent // scopes need to be freed before the return if g.is_autofree { - expr := node.exprs[0] - if expr is ast.Ident { - g.returned_var_name = expr.name + if expr0 is ast.Ident { + g.returned_var_name = expr0.name } if !use_tmp_var && !g.is_builtin_mod { - use_tmp_var = expr is ast.CallExpr + use_tmp_var = expr0 is ast.CallExpr } } // Create a temporary variable for the return expression @@ -5926,68 +5926,67 @@ fn (mut g Gen) return_stmt(node ast.Return) { var_str := g.expr_string(expr0) g.write(var_str.trim('&')) } else if g.fn_decl.return_type.has_flag(.option) { - g.expr_with_opt(expr0, node.types[0], g.fn_decl.return_type) + g.expr_with_opt(expr0, type0, g.fn_decl.return_type) } else if g.table.sym(g.fn_decl.return_type).kind in [.sum_type, .interface] { - g.expr_with_cast(expr0, node.types[0], g.fn_decl.return_type) + g.expr_with_cast(expr0, type0, g.fn_decl.return_type) } else { g.write('*') g.expr(expr0) } } else { if g.fn_decl.return_type.has_flag(.option) { - expr0_is_alias_fn_ret := expr0 is ast.CallExpr && node.types[0].has_flag(.option) - && g.table.type_kind(node.types[0]) in [.placeholder, .alias] + expr0_is_alias_fn_ret := expr0 is ast.CallExpr && type0.has_flag(.option) + && g.table.type_kind(type0) in [.placeholder, .alias] // return foo() where foo() returns different option alias than current fn if expr0_is_alias_fn_ret { - g.expr_opt_with_cast(node.exprs[0], node.types[0], g.fn_decl.return_type) + g.expr_opt_with_cast(expr0, type0, g.fn_decl.return_type) } else { - g.expr_with_opt(node.exprs[0], node.types[0], g.fn_decl.return_type) + g.expr_with_opt(expr0, type0, g.fn_decl.return_type) } } else { - if fn_return_is_fixed_array && !node.types[0].has_option_or_result() { + if fn_return_is_fixed_array && !type0.has_option_or_result() { if node.exprs[0] is ast.Ident { g.writeln('{0};') - typ := if expr0.is_auto_deref_var() { - node.types[0].deref() + typ := if node.exprs[0].is_auto_deref_var() { + type0.deref() } else { - node.types[0] + type0 } typ_sym := g.table.final_sym(typ) if typ_sym.kind == .array_fixed && (typ_sym.info as ast.ArrayFixed).is_fn_ret { - g.write('memcpy(${tmpvar}.ret_arr, ${g.expr_string(node.exprs[0])}.ret_arr, sizeof(${g.styp(typ)}))') + g.write('memcpy(${tmpvar}.ret_arr, ${g.expr_string(expr0)}.ret_arr, sizeof(${g.styp(typ)}))') } else { - g.write('memcpy(${tmpvar}.ret_arr, ${g.expr_string(node.exprs[0])}, sizeof(${g.styp(typ)}))') + g.write('memcpy(${tmpvar}.ret_arr, ${g.expr_string(expr0)}, sizeof(${g.styp(typ)}))') } - } else if node.exprs[0] in [ast.ArrayInit, ast.StructInit] { - if node.exprs[0] is ast.ArrayInit && node.exprs[0].is_fixed - && node.exprs[0].has_init { - if (node.exprs[0] as ast.ArrayInit).init_expr.is_literal() { + } else if expr0 in [ast.ArrayInit, ast.StructInit] { + if expr0 is ast.ArrayInit && expr0.is_fixed && expr0.has_init { + if (expr0 as ast.ArrayInit).init_expr.is_literal() { g.write('{.ret_arr=') - g.expr_with_cast(node.exprs[0], node.types[0], g.fn_decl.return_type) + g.expr_with_cast(expr0, type0, g.fn_decl.return_type) g.writeln('};') } else { g.writeln('{0};') 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.styp(node.types[0])}))') + g.expr_with_cast(expr0, type0, g.fn_decl.return_type) + g.write(', sizeof(${g.styp(type0)}))') } } else { g.writeln('{0};') tmpvar2 := g.new_tmp_var() - g.write('${g.styp(node.types[0])} ${tmpvar2} = ') - g.expr_with_cast(node.exprs[0], node.types[0], g.fn_decl.return_type) + g.write('${g.styp(type0)} ${tmpvar2} = ') + g.expr_with_cast(expr0, type0, g.fn_decl.return_type) g.writeln(';') - g.write('memcpy(${tmpvar}.ret_arr, ${tmpvar2}, sizeof(${g.styp(node.types[0])}))') + g.write('memcpy(${tmpvar}.ret_arr, ${tmpvar2}, sizeof(${g.styp(type0)}))') } } else { g.writeln('{0};') 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.styp(node.types[0])}))') + g.expr_with_cast(expr0, type0, g.fn_decl.return_type) + g.write(', sizeof(${g.styp(type0)}))') } } else { - g.expr_with_cast(node.exprs[0], node.types[0], g.fn_decl.return_type) + g.expr_with_cast(expr0, type0, g.fn_decl.return_type) } } }