cgen: minor optimization removing repeated code (#23417)

This commit is contained in:
Felipe Pena 2025-01-09 12:59:29 -03:00 committed by GitHub
parent 6348e581de
commit cc7caf4384
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 49 additions and 47 deletions

View File

@ -5503,10 +5503,11 @@ fn (mut g Gen) return_stmt(node ast.Return) {
g.inside_return = old_inside_return g.inside_return = old_inside_return
} }
expr0 := if node.exprs.len > 0 { node.exprs[0] } else { ast.empty_expr } exprs_len := node.exprs.len
type0 := if node.exprs.len > 0 { node.types[0] } else { ast.void_type } 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()` // skip `return $vweb.html()`
if expr0 is ast.ComptimeCall && expr0.is_vweb { if expr0 is ast.ComptimeCall && expr0.is_vweb {
g.inside_return_tmpl = true g.inside_return_tmpl = true
@ -5516,10 +5517,11 @@ fn (mut g Gen) return_stmt(node ast.Return) {
return return
} }
} }
ret_type := g.fn_decl.return_type
// got to do a correct check for multireturn // got to do a correct check for multireturn
sym := g.table.sym(g.unwrap_generic(g.fn_decl.return_type)) sym := g.table.sym(g.unwrap_generic(ret_type))
mut fn_ret_type := g.fn_decl.return_type mut fn_ret_type := ret_type
if sym.kind == .alias { if sym.kind == .alias {
unaliased_type := g.table.unaliased_type(fn_ret_type) unaliased_type := g.table.unaliased_type(fn_ret_type)
if unaliased_type.has_option_or_result() { if unaliased_type.has_option_or_result() {
@ -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_return_is_fixed_array_non_result := fn_return_is_fixed_array
&& !fn_ret_type.has_option_or_result() && !fn_ret_type.has_option_or_result()
mut has_semicolon := false mut has_semicolon := false
if node.exprs.len == 0 { if exprs_len == 0 {
g.write_defer_stmts_when_needed() g.write_defer_stmts_when_needed()
if fn_return_is_option || fn_return_is_result { if fn_return_is_option || fn_return_is_result {
styp := g.styp(fn_ret_type) styp := g.styp(fn_ret_type)
@ -5556,8 +5558,8 @@ fn (mut g Gen) return_stmt(node ast.Return) {
ret_typ := g.ret_styp(g.unwrap_generic(fn_ret_type)) ret_typ := g.ret_styp(g.unwrap_generic(fn_ret_type))
// `return fn_call_opt()` // `return fn_call_opt()`
if node.exprs.len == 1 && (fn_return_is_option || fn_return_is_result) && expr0 is ast.CallExpr if 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 { && expr0.return_type == ret_type && expr0.or_block.kind == .absent {
if g.defer_stmts.len > 0 { if g.defer_stmts.len > 0 {
g.write('${ret_typ} ${tmpvar} = ') g.write('${ret_typ} ${tmpvar} = ')
g.expr(expr0) g.expr(expr0)
@ -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 mut use_tmp_var := g.defer_stmts.len > 0 || g.defer_profile_code.len > 0
|| g.cur_lock.lockeds.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_fixed_array_non_result
|| (fn_return_is_multi && node.types.any(g.table.final_sym(it).kind == .array_fixed)) || (fn_return_is_multi && node.types.any(g.table.final_sym(it).kind == .array_fixed))
// handle promoting none/error/function returning _option' // handle promoting none/error/function returning _option'
@ -5601,7 +5603,7 @@ fn (mut g Gen) return_stmt(node ast.Return) {
g.writeln(';') g.writeln(';')
if use_tmp_var { if use_tmp_var {
// handle options when returning `none` for `?(int, ?int)` // 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 mr_info := sym.info as ast.MultiReturn
for i in 0 .. mr_info.types.len { for i in 0 .. mr_info.types.len {
if mr_info.types[i].has_flag(.option) { if mr_info.types[i].has_flag(.option) {
@ -5646,8 +5648,8 @@ fn (mut g Gen) return_stmt(node ast.Return) {
} }
} }
// regular cases // regular cases
if fn_return_is_multi && node.exprs.len > 0 && !g.expr_is_multi_return_call(expr0) { if fn_return_is_multi && exprs_len > 0 && !g.expr_is_multi_return_call(expr0) {
if node.exprs.len == 1 && (expr0 is ast.IfExpr || expr0 is ast.MatchExpr) { 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 } }` // 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.write('${ret_typ} ${tmpvar} = ')
g.expr(expr0) g.expr(expr0)
@ -5660,11 +5662,11 @@ fn (mut g Gen) return_stmt(node ast.Return) {
mut styp := '' mut styp := ''
if fn_return_is_option { if fn_return_is_option {
g.writeln('${ret_typ} ${tmpvar};') 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}[]) { ') g.write('_option_ok(&(${styp}[]) { ')
} else if fn_return_is_result { } else if fn_return_is_result {
g.writeln('${ret_typ} ${tmpvar};') 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}[]) { ') g.write('_result_ok(&(${styp}[]) { ')
} else { } else {
if use_tmp_var { if use_tmp_var {
@ -5672,7 +5674,7 @@ fn (mut g Gen) return_stmt(node ast.Return) {
} else { } else {
g.write('return ') 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 // Use this to keep the tmp assignments in order
mut multi_unpack := '' mut multi_unpack := ''
@ -5705,7 +5707,7 @@ fn (mut g Gen) return_stmt(node ast.Return) {
expr_types := expr_sym.mr_info().types expr_types := expr_sym.mr_info().types
for j, _ in expr_types { for j, _ in expr_types {
g.write('.arg${arg_idx}=${tmp}.arg${j}') 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(',') g.write(',')
} }
arg_idx++ arg_idx++
@ -5733,7 +5735,7 @@ fn (mut g Gen) return_stmt(node ast.Return) {
g.expr(expr) g.expr(expr)
} }
} }
if i < node.exprs.len - 1 { if i < exprs_len - 1 {
g.write(', ') g.write(', ')
} }
arg_idx++ arg_idx++
@ -5764,7 +5766,7 @@ fn (mut g Gen) return_stmt(node ast.Return) {
g.writeln('return ${tmpvar};') g.writeln('return ${tmpvar};')
has_semicolon = true has_semicolon = true
} }
} else if node.exprs.len >= 1 { } else if exprs_len >= 1 {
if node.types.len == 0 { if node.types.len == 0 {
g.checker_bug('node.exprs.len == ${node.exprs.len} && node.types.len == 0', g.checker_bug('node.exprs.len == ${node.exprs.len} && node.types.len == 0',
node.pos) node.pos)
@ -5904,26 +5906,26 @@ fn (mut g Gen) return_stmt(node ast.Return) {
g.write('return ') g.write('return ')
} }
if expr0.is_auto_deref_var() && !fn_return_is_fixed_array { 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) var_str := g.expr_string(expr0)
g.write(var_str.trim('&')) g.write(var_str.trim('&'))
} else if g.fn_decl.return_type.has_flag(.option) { } else if ret_type.has_flag(.option) {
g.expr_with_opt(expr0, type0, g.fn_decl.return_type) g.expr_with_opt(expr0, type0, ret_type)
} else if g.table.sym(g.fn_decl.return_type).kind in [.sum_type, .interface] { } else if g.table.sym(ret_type).kind in [.sum_type, .interface] {
g.expr_with_cast(expr0, type0, g.fn_decl.return_type) g.expr_with_cast(expr0, type0, ret_type)
} else { } else {
g.write('*') g.write('*')
g.expr(expr0) g.expr(expr0)
} }
} else { } 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) expr0_is_alias_fn_ret := expr0 is ast.CallExpr && type0.has_flag(.option)
&& g.table.type_kind(type0) in [.placeholder, .alias] && g.table.type_kind(type0) in [.placeholder, .alias]
// return foo() where foo() returns different option alias than current fn // return foo() where foo() returns different option alias than current fn
if expr0_is_alias_fn_ret { 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 { } else {
g.expr_with_opt(expr0, type0, g.fn_decl.return_type) g.expr_with_opt(expr0, type0, ret_type)
} }
} else { } else {
if fn_return_is_fixed_array && !type0.has_option_or_result() { if fn_return_is_fixed_array && !type0.has_option_or_result() {
@ -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 is ast.ArrayInit && expr0.is_fixed && expr0.has_init {
if (expr0 as ast.ArrayInit).init_expr.is_literal() { if (expr0 as ast.ArrayInit).init_expr.is_literal() {
g.write('{.ret_arr=') 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('};') g.writeln('};')
} else { } else {
g.writeln('{0};') g.writeln('{0};')
g.write('memcpy(${tmpvar}.ret_arr, ') 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)}))') g.write(', sizeof(${g.styp(type0)}))')
} }
} else { } else {
g.writeln('{0};') g.writeln('{0};')
tmpvar2 := g.new_tmp_var() tmpvar2 := g.new_tmp_var()
g.write('${g.styp(type0)} ${tmpvar2} = ') 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.writeln(';')
g.write('memcpy(${tmpvar}.ret_arr, ${tmpvar2}, sizeof(${g.styp(type0)}))') g.write('memcpy(${tmpvar}.ret_arr, ${tmpvar2}, sizeof(${g.styp(type0)}))')
} }
} else { } else {
g.writeln('{0};') g.writeln('{0};')
g.write('memcpy(${tmpvar}.ret_arr, ') 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)}))') g.write(', sizeof(${g.styp(type0)}))')
} }
} else { } else {
g.expr_with_cast(expr0, type0, g.fn_decl.return_type) g.expr_with_cast(expr0, type0, ret_type)
} }
} }
} }

View File

@ -118,14 +118,15 @@ fn (mut g Gen) spawn_and_go_expr(node ast.SpawnExpr, mode SpawnGoMode) {
g.expr(arg.expr) g.expr(arg.expr)
g.writeln(';') g.writeln(';')
} }
s_ret_typ := g.styp(node.call_expr.return_type) call_ret_type := node.call_expr.return_type
if g.pref.os == .windows && node.call_expr.return_type != ast.void_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}));') 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_opt := call_ret_type.has_flag(.option)
is_res := node.call_expr.return_type.has_flag(.result) is_res := call_ret_type.has_flag(.result)
mut gohandle_name := '' mut gohandle_name := ''
if node.call_expr.return_type == ast.void_type { if call_ret_type == ast.void_type {
if is_opt { if is_opt {
gohandle_name = '__v_thread_Option_void' gohandle_name = '__v_thread_Option_void'
} else if is_res { } else if is_res {
@ -134,13 +135,12 @@ fn (mut g Gen) spawn_and_go_expr(node ast.SpawnExpr, mode SpawnGoMode) {
gohandle_name = '__v_thread' gohandle_name = '__v_thread'
} }
} else { } else {
ret_styp := g.styp(g.unwrap_generic(node.call_expr.return_type)).replace('*', ret_styp := g.styp(g.unwrap_generic(call_ret_type)).replace('*', '_ptr')
'_ptr')
gohandle_name = '__v_thread_${ret_styp}' gohandle_name = '__v_thread_${ret_styp}'
} }
if is_spawn { if is_spawn {
if g.pref.os == .windows { 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}' 'thread_handle_${tmp}'
} else { } else {
'thread_${tmp}' 'thread_${tmp}'
@ -148,7 +148,7 @@ fn (mut g Gen) spawn_and_go_expr(node ast.SpawnExpr, mode SpawnGoMode) {
stack_size := g.get_cur_thread_stack_size(expr.name) 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('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}()`: "));') 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('${gohandle_name} thread_${tmp} = {')
g.writeln('\t.ret_ptr = ${arg_tmp_var}->ret_ptr,') g.writeln('\t.ret_ptr = ${arg_tmp_var}->ret_ptr,')
g.writeln2('\t.handle = thread_handle_${tmp}', '};') g.writeln2('\t.handle = thread_handle_${tmp}', '};')
@ -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.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) {') g.gowrappers.writeln('\n${s_ret_typ} ${waiter_fn_name}(${gohandle_name} thread) {')
mut c_ret_ptr_ptr := 'NULL' 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;') g.gowrappers.writeln('\t${s_ret_typ}* ret_ptr;')
c_ret_ptr_ptr = '&ret_ptr' c_ret_ptr_ptr = '&ret_ptr'
} }
if g.pref.os == .windows { 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);') g.gowrappers.writeln('\tu32 stat = WaitForSingleObject(thread, INFINITE);')
} else { } else {
g.gowrappers.writeln('\tu32 stat = WaitForSingleObject(thread.handle, INFINITE);') g.gowrappers.writeln('\tu32 stat = WaitForSingleObject(thread.handle, INFINITE);')
@ -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")); }') g.gowrappers.writeln('\tif (stat != 0) { _v_panic(_SLIT("unable to join thread")); }')
if g.pref.os == .windows { 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);') g.gowrappers.writeln('\tCloseHandle(thread);')
} else { } else {
g.gowrappers.writeln('\tCloseHandle(thread.handle);') 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${s_ret_typ} ret = *ret_ptr;')
g.gowrappers.writeln('\t_v_free(ret_ptr);') g.gowrappers.writeln('\t_v_free(ret_ptr);')
g.gowrappers.writeln('\treturn ret;') g.gowrappers.writeln('\treturn ret;')
@ -288,7 +288,7 @@ fn (mut g Gen) spawn_and_go_expr(node ast.SpawnExpr, mode SpawnGoMode) {
styp := g.styp(expr.receiver_type) styp := g.styp(expr.receiver_type)
g.type_definitions.writeln('\t${styp} arg0;') 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 { for i, arg in expr.args {
arg_sym := g.table.sym(arg.typ) arg_sym := g.table.sym(arg.typ)
if arg_sym.info is ast.FnType { if arg_sym.info is ast.FnType {
@ -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*' } 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.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) {') 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 { if g.pref.os == .windows {
g.gowrappers.write_string('\t*((${s_ret_typ}*)(arg->ret_ptr)) = ') g.gowrappers.write_string('\t*((${s_ret_typ}*)(arg->ret_ptr)) = ')
} else { } else {
@ -398,7 +398,7 @@ fn (mut g Gen) spawn_and_go_expr(node ast.SpawnExpr, mode SpawnGoMode) {
if is_spawn { if is_spawn {
g.gowrappers.writeln('\t_v_free(arg);') 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;') g.gowrappers.writeln('\treturn ret_ptr;')
} else { } else {
g.gowrappers.writeln('\treturn 0;') g.gowrappers.writeln('\treturn 0;')