Skip to content

Commit

Permalink
cgen: minor optimization removing repeated code (#23417)
Browse files Browse the repository at this point in the history
  • Loading branch information
felipensp authored Jan 9, 2025
1 parent 6348e58 commit cc7caf4
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 47 deletions.
64 changes: 33 additions & 31 deletions vlib/v/gen/c/cgen.v
Original file line number Diff line number Diff line change
Expand Up @@ -5503,10 +5503,11 @@ 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 }
exprs_len := node.exprs.len
expr0 := if exprs_len > 0 { node.exprs[0] } else { ast.empty_expr }
type0 := if exprs_len > 0 { node.types[0] } else { ast.void_type }

if node.exprs.len > 0 {
if exprs_len > 0 {
// skip `return $vweb.html()`
if expr0 is ast.ComptimeCall && expr0.is_vweb {
g.inside_return_tmpl = true
Expand All @@ -5516,10 +5517,11 @@ fn (mut g Gen) return_stmt(node ast.Return) {
return
}
}
ret_type := g.fn_decl.return_type

// got to do a correct check for multireturn
sym := g.table.sym(g.unwrap_generic(g.fn_decl.return_type))
mut fn_ret_type := g.fn_decl.return_type
sym := g.table.sym(g.unwrap_generic(ret_type))
mut fn_ret_type := ret_type
if sym.kind == .alias {
unaliased_type := g.table.unaliased_type(fn_ret_type)
if unaliased_type.has_option_or_result() {
Expand All @@ -5533,7 +5535,7 @@ fn (mut g Gen) return_stmt(node ast.Return) {
fn_return_is_fixed_array_non_result := fn_return_is_fixed_array
&& !fn_ret_type.has_option_or_result()
mut has_semicolon := false
if node.exprs.len == 0 {
if exprs_len == 0 {
g.write_defer_stmts_when_needed()
if fn_return_is_option || fn_return_is_result {
styp := g.styp(fn_ret_type)
Expand All @@ -5556,8 +5558,8 @@ 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) && expr0 is ast.CallExpr
&& expr0.return_type == g.fn_decl.return_type && expr0.or_block.kind == .absent {
if exprs_len == 1 && (fn_return_is_option || fn_return_is_result) && expr0 is ast.CallExpr
&& expr0.return_type == ret_type && expr0.or_block.kind == .absent {
if g.defer_stmts.len > 0 {
g.write('${ret_typ} ${tmpvar} = ')
g.expr(expr0)
Expand All @@ -5574,7 +5576,7 @@ fn (mut g Gen) return_stmt(node ast.Return) {
}
mut use_tmp_var := g.defer_stmts.len > 0 || g.defer_profile_code.len > 0
|| g.cur_lock.lockeds.len > 0
|| (fn_return_is_multi && node.exprs.len >= 1 && fn_return_is_option)
|| (fn_return_is_multi && exprs_len >= 1 && fn_return_is_option)
|| fn_return_is_fixed_array_non_result
|| (fn_return_is_multi && node.types.any(g.table.final_sym(it).kind == .array_fixed))
// handle promoting none/error/function returning _option'
Expand All @@ -5601,7 +5603,7 @@ fn (mut g Gen) return_stmt(node ast.Return) {
g.writeln(';')
if use_tmp_var {
// handle options when returning `none` for `?(int, ?int)`
if fn_return_is_multi && node.exprs.len >= 1 {
if fn_return_is_multi && exprs_len >= 1 {
mr_info := sym.info as ast.MultiReturn
for i in 0 .. mr_info.types.len {
if mr_info.types[i].has_flag(.option) {
Expand Down Expand Up @@ -5646,8 +5648,8 @@ 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(expr0) {
if node.exprs.len == 1 && (expr0 is ast.IfExpr || expr0 is ast.MatchExpr) {
if fn_return_is_multi && exprs_len > 0 && !g.expr_is_multi_return_call(expr0) {
if 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(expr0)
Expand All @@ -5660,19 +5662,19 @@ fn (mut g Gen) return_stmt(node ast.Return) {
mut styp := ''
if fn_return_is_option {
g.writeln('${ret_typ} ${tmpvar};')
styp = g.base_type(g.fn_decl.return_type)
styp = g.base_type(ret_type)
g.write('_option_ok(&(${styp}[]) { ')
} else if fn_return_is_result {
g.writeln('${ret_typ} ${tmpvar};')
styp = g.base_type(g.fn_decl.return_type)
styp = g.base_type(ret_type)
g.write('_result_ok(&(${styp}[]) { ')
} else {
if use_tmp_var {
g.write('${ret_typ} ${tmpvar} = ')
} else {
g.write('return ')
}
styp = g.styp(g.fn_decl.return_type)
styp = g.styp(ret_type)
}
// Use this to keep the tmp assignments in order
mut multi_unpack := ''
Expand Down Expand Up @@ -5705,7 +5707,7 @@ fn (mut g Gen) return_stmt(node ast.Return) {
expr_types := expr_sym.mr_info().types
for j, _ in expr_types {
g.write('.arg${arg_idx}=${tmp}.arg${j}')
if j < expr_types.len || i < node.exprs.len - 1 {
if j < expr_types.len || i < exprs_len - 1 {
g.write(',')
}
arg_idx++
Expand Down Expand Up @@ -5733,7 +5735,7 @@ fn (mut g Gen) return_stmt(node ast.Return) {
g.expr(expr)
}
}
if i < node.exprs.len - 1 {
if i < exprs_len - 1 {
g.write(', ')
}
arg_idx++
Expand Down Expand Up @@ -5764,7 +5766,7 @@ fn (mut g Gen) return_stmt(node ast.Return) {
g.writeln('return ${tmpvar};')
has_semicolon = true
}
} else if node.exprs.len >= 1 {
} else if exprs_len >= 1 {
if node.types.len == 0 {
g.checker_bug('node.exprs.len == ${node.exprs.len} && node.types.len == 0',
node.pos)
Expand Down Expand Up @@ -5904,26 +5906,26 @@ fn (mut g Gen) return_stmt(node ast.Return) {
g.write('return ')
}
if expr0.is_auto_deref_var() && !fn_return_is_fixed_array {
if g.fn_decl.return_type.is_ptr() {
if ret_type.is_ptr() {
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, 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, type0, g.fn_decl.return_type)
} else if ret_type.has_flag(.option) {
g.expr_with_opt(expr0, type0, ret_type)
} else if g.table.sym(ret_type).kind in [.sum_type, .interface] {
g.expr_with_cast(expr0, type0, ret_type)
} else {
g.write('*')
g.expr(expr0)
}
} else {
if g.fn_decl.return_type.has_flag(.option) {
if ret_type.has_flag(.option) {
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(expr0, type0, g.fn_decl.return_type)
g.expr_opt_with_cast(expr0, type0, ret_type)
} else {
g.expr_with_opt(expr0, type0, g.fn_decl.return_type)
g.expr_with_opt(expr0, type0, ret_type)
}
} else {
if fn_return_is_fixed_array && !type0.has_option_or_result() {
Expand All @@ -5945,30 +5947,30 @@ fn (mut g Gen) return_stmt(node ast.Return) {
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(expr0, type0, g.fn_decl.return_type)
g.expr_with_cast(expr0, type0, ret_type)
g.writeln('};')
} else {
g.writeln('{0};')
g.write('memcpy(${tmpvar}.ret_arr, ')
g.expr_with_cast(expr0, type0, g.fn_decl.return_type)
g.expr_with_cast(expr0, type0, ret_type)
g.write(', sizeof(${g.styp(type0)}))')
}
} else {
g.writeln('{0};')
tmpvar2 := g.new_tmp_var()
g.write('${g.styp(type0)} ${tmpvar2} = ')
g.expr_with_cast(expr0, type0, g.fn_decl.return_type)
g.expr_with_cast(expr0, type0, ret_type)
g.writeln(';')
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(expr0, type0, g.fn_decl.return_type)
g.expr_with_cast(expr0, type0, ret_type)
g.write(', sizeof(${g.styp(type0)}))')
}
} else {
g.expr_with_cast(expr0, type0, g.fn_decl.return_type)
g.expr_with_cast(expr0, type0, ret_type)
}
}
}
Expand Down
32 changes: 16 additions & 16 deletions vlib/v/gen/c/spawn_and_go.v
Original file line number Diff line number Diff line change
Expand Up @@ -118,14 +118,15 @@ fn (mut g Gen) spawn_and_go_expr(node ast.SpawnExpr, mode SpawnGoMode) {
g.expr(arg.expr)
g.writeln(';')
}
s_ret_typ := g.styp(node.call_expr.return_type)
if g.pref.os == .windows && node.call_expr.return_type != ast.void_type {
call_ret_type := node.call_expr.return_type
s_ret_typ := g.styp(call_ret_type)
if g.pref.os == .windows && call_ret_type != ast.void_type {
g.writeln('${arg_tmp_var}->ret_ptr = (void *) _v_malloc(sizeof(${s_ret_typ}));')
}
is_opt := node.call_expr.return_type.has_flag(.option)
is_res := node.call_expr.return_type.has_flag(.result)
is_opt := call_ret_type.has_flag(.option)
is_res := call_ret_type.has_flag(.result)
mut gohandle_name := ''
if node.call_expr.return_type == ast.void_type {
if call_ret_type == ast.void_type {
if is_opt {
gohandle_name = '__v_thread_Option_void'
} else if is_res {
Expand All @@ -134,21 +135,20 @@ fn (mut g Gen) spawn_and_go_expr(node ast.SpawnExpr, mode SpawnGoMode) {
gohandle_name = '__v_thread'
}
} else {
ret_styp := g.styp(g.unwrap_generic(node.call_expr.return_type)).replace('*',
'_ptr')
ret_styp := g.styp(g.unwrap_generic(call_ret_type)).replace('*', '_ptr')
gohandle_name = '__v_thread_${ret_styp}'
}
if is_spawn {
if g.pref.os == .windows {
simple_handle := if node.is_expr && node.call_expr.return_type != ast.void_type {
simple_handle := if node.is_expr && call_ret_type != ast.void_type {
'thread_handle_${tmp}'
} else {
'thread_${tmp}'
}
stack_size := g.get_cur_thread_stack_size(expr.name)
g.writeln('HANDLE ${simple_handle} = CreateThread(0, ${stack_size}, (LPTHREAD_START_ROUTINE)${wrapper_fn_name}, ${arg_tmp_var}, 0, 0); // fn: ${expr.name}')
g.writeln('if (!${simple_handle}) panic_lasterr(tos3("`go ${name}()`: "));')
if node.is_expr && node.call_expr.return_type != ast.void_type {
if node.is_expr && call_ret_type != ast.void_type {
g.writeln('${gohandle_name} thread_${tmp} = {')
g.writeln('\t.ret_ptr = ${arg_tmp_var}->ret_ptr,')
g.writeln2('\t.handle = thread_handle_${tmp}', '};')
Expand Down Expand Up @@ -195,12 +195,12 @@ fn (mut g Gen) spawn_and_go_expr(node ast.SpawnExpr, mode SpawnGoMode) {
g.waiter_fn_definitions.writeln('${s_ret_typ} ${waiter_fn_name}(${gohandle_name} thread);')
g.gowrappers.writeln('\n${s_ret_typ} ${waiter_fn_name}(${gohandle_name} thread) {')
mut c_ret_ptr_ptr := 'NULL'
if node.call_expr.return_type != ast.void_type {
if call_ret_type != ast.void_type {
g.gowrappers.writeln('\t${s_ret_typ}* ret_ptr;')
c_ret_ptr_ptr = '&ret_ptr'
}
if g.pref.os == .windows {
if node.call_expr.return_type == ast.void_type {
if call_ret_type == ast.void_type {
g.gowrappers.writeln('\tu32 stat = WaitForSingleObject(thread, INFINITE);')
} else {
g.gowrappers.writeln('\tu32 stat = WaitForSingleObject(thread.handle, INFINITE);')
Expand All @@ -211,13 +211,13 @@ fn (mut g Gen) spawn_and_go_expr(node ast.SpawnExpr, mode SpawnGoMode) {
}
g.gowrappers.writeln('\tif (stat != 0) { _v_panic(_SLIT("unable to join thread")); }')
if g.pref.os == .windows {
if node.call_expr.return_type == ast.void_type {
if call_ret_type == ast.void_type {
g.gowrappers.writeln('\tCloseHandle(thread);')
} else {
g.gowrappers.writeln('\tCloseHandle(thread.handle);')
}
}
if node.call_expr.return_type != ast.void_type {
if call_ret_type != ast.void_type {
g.gowrappers.writeln('\t${s_ret_typ} ret = *ret_ptr;')
g.gowrappers.writeln('\t_v_free(ret_ptr);')
g.gowrappers.writeln('\treturn ret;')
Expand Down Expand Up @@ -288,7 +288,7 @@ fn (mut g Gen) spawn_and_go_expr(node ast.SpawnExpr, mode SpawnGoMode) {
styp := g.styp(expr.receiver_type)
g.type_definitions.writeln('\t${styp} arg0;')
}
need_return_ptr := g.pref.os == .windows && node.call_expr.return_type != ast.void_type
need_return_ptr := g.pref.os == .windows && call_ret_type != ast.void_type
for i, arg in expr.args {
arg_sym := g.table.sym(arg.typ)
if arg_sym.info is ast.FnType {
Expand All @@ -307,7 +307,7 @@ fn (mut g Gen) spawn_and_go_expr(node ast.SpawnExpr, mode SpawnGoMode) {
thread_ret_type := if g.pref.os == .windows { 'u32' } else { 'void*' }
g.type_definitions.writeln('${g.static_modifier} ${thread_ret_type} ${wrapper_fn_name}(${wrapper_struct_name} *arg);')
g.gowrappers.writeln('${thread_ret_type} ${wrapper_fn_name}(${wrapper_struct_name} *arg) {')
if node.call_expr.return_type != ast.void_type {
if call_ret_type != ast.void_type {
if g.pref.os == .windows {
g.gowrappers.write_string('\t*((${s_ret_typ}*)(arg->ret_ptr)) = ')
} else {
Expand Down Expand Up @@ -398,7 +398,7 @@ fn (mut g Gen) spawn_and_go_expr(node ast.SpawnExpr, mode SpawnGoMode) {
if is_spawn {
g.gowrappers.writeln('\t_v_free(arg);')
}
if g.pref.os != .windows && node.call_expr.return_type != ast.void_type {
if g.pref.os != .windows && call_ret_type != ast.void_type {
g.gowrappers.writeln('\treturn ret_ptr;')
} else {
g.gowrappers.writeln('\treturn 0;')
Expand Down

0 comments on commit cc7caf4

Please sign in to comment.