cgen: store return vals in tmp vars with -autofree
parent
92eea7f95a
commit
5eb76606ae
|
@ -103,6 +103,12 @@ pub fn mkdir(path string) ?bool {
|
||||||
if path == '.' {
|
if path == '.' {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
mut k := 0
|
||||||
|
defer {
|
||||||
|
k = 1
|
||||||
|
}
|
||||||
|
*/
|
||||||
apath := os.real_path(path)
|
apath := os.real_path(path)
|
||||||
/*
|
/*
|
||||||
$if linux {
|
$if linux {
|
||||||
|
|
|
@ -394,16 +394,11 @@ fn (g &Gen) cc_type(t table.Type) string {
|
||||||
if info.generic_types.len > 0 {
|
if info.generic_types.len > 0 {
|
||||||
mut sgtyps := '_T'
|
mut sgtyps := '_T'
|
||||||
for gt in info.generic_types {
|
for gt in info.generic_types {
|
||||||
gts := g.table.get_type_symbol(if gt.has_flag(.generic) {
|
gts := g.table.get_type_symbol(if gt.has_flag(.generic) { g.unwrap_generic(gt) } else { gt })
|
||||||
g.unwrap_generic(gt)
|
|
||||||
} else {
|
|
||||||
gt
|
|
||||||
})
|
|
||||||
sgtyps += '_$gts.name'
|
sgtyps += '_$gts.name'
|
||||||
}
|
}
|
||||||
styp += sgtyps
|
styp += sgtyps
|
||||||
}
|
} else if styp.contains('<') {
|
||||||
else if styp.contains('<') {
|
|
||||||
// TODO: yuck
|
// TODO: yuck
|
||||||
styp = styp.replace('<', '_T_').replace('>', '').replace(',', '_')
|
styp = styp.replace('<', '_T_').replace('>', '').replace(',', '_')
|
||||||
}
|
}
|
||||||
|
@ -772,7 +767,9 @@ fn (mut g Gen) stmt(node ast.Stmt) {
|
||||||
}
|
}
|
||||||
ast.Return {
|
ast.Return {
|
||||||
g.write_defer_stmts_when_needed()
|
g.write_defer_stmts_when_needed()
|
||||||
g.write_autofree_stmts_when_needed(node)
|
if g.pref.autofree {
|
||||||
|
g.write_autofree_stmts_when_needed(node)
|
||||||
|
}
|
||||||
g.return_statement(node)
|
g.return_statement(node)
|
||||||
}
|
}
|
||||||
ast.SqlStmt {
|
ast.SqlStmt {
|
||||||
|
@ -1095,18 +1092,18 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
|
||||||
info := sym.info as table.Array
|
info := sym.info as table.Array
|
||||||
styp := g.typ(info.elem_type)
|
styp := g.typ(info.elem_type)
|
||||||
g.write('$styp _var_$left.pos.pos = *($styp*)array_get(')
|
g.write('$styp _var_$left.pos.pos = *($styp*)array_get(')
|
||||||
g.expr(it.left)
|
g.expr(left.left)
|
||||||
g.write(', ')
|
g.write(', ')
|
||||||
g.expr(it.index)
|
g.expr(left.index)
|
||||||
g.writeln(');')
|
g.writeln(');')
|
||||||
} else if sym.kind == .map {
|
} else if sym.kind == .map {
|
||||||
info := sym.info as table.Map
|
info := sym.info as table.Map
|
||||||
styp := g.typ(info.value_type)
|
styp := g.typ(info.value_type)
|
||||||
zero := g.type_default(info.value_type)
|
zero := g.type_default(info.value_type)
|
||||||
g.write('$styp _var_$left.pos.pos = *($styp*)map_get(')
|
g.write('$styp _var_$left.pos.pos = *($styp*)map_get(')
|
||||||
g.expr(it.left)
|
g.expr(left.left)
|
||||||
g.write(', ')
|
g.write(', ')
|
||||||
g.expr(it.index)
|
g.expr(left.index)
|
||||||
g.writeln(', &($styp[]){ $zero });')
|
g.writeln(', &($styp[]){ $zero });')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2486,7 +2483,21 @@ fn (mut g Gen) return_statement(node ast.Return) {
|
||||||
g.writeln('return $opt_tmp;')
|
g.writeln('return $opt_tmp;')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
g.write('return ')
|
free := g.pref.autofree && node.exprs[0] is ast.CallExpr
|
||||||
|
mut tmp := ''
|
||||||
|
if free {
|
||||||
|
// `return foo(a, b, c)`
|
||||||
|
// `tmp := foo(a, b, c); free(a); free(b); free(c); return tmp;`
|
||||||
|
// Save return value in a temp var so that it all args (a,b,c) can be freed
|
||||||
|
tmp = g.new_tmp_var()
|
||||||
|
g.write(g.typ(g.fn_decl.return_type))
|
||||||
|
g.write(' ')
|
||||||
|
g.write(tmp)
|
||||||
|
g.write(' = ')
|
||||||
|
// g.write('return $tmp;')
|
||||||
|
} else {
|
||||||
|
g.write('return ')
|
||||||
|
}
|
||||||
cast_interface := sym.kind == .interface_ && node.types[0] != g.fn_decl.return_type
|
cast_interface := sym.kind == .interface_ && node.types[0] != g.fn_decl.return_type
|
||||||
if cast_interface {
|
if cast_interface {
|
||||||
g.interface_call(node.types[0], g.fn_decl.return_type)
|
g.interface_call(node.types[0], g.fn_decl.return_type)
|
||||||
|
@ -2495,6 +2506,10 @@ fn (mut g Gen) return_statement(node ast.Return) {
|
||||||
if cast_interface {
|
if cast_interface {
|
||||||
g.write(')')
|
g.write(')')
|
||||||
}
|
}
|
||||||
|
if free {
|
||||||
|
g.writeln(';')
|
||||||
|
g.write('return $tmp')
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
g.write('return')
|
g.write('return')
|
||||||
}
|
}
|
||||||
|
@ -2824,7 +2839,7 @@ fn (mut g Gen) write_init_function() {
|
||||||
g.writeln('void _vcleanup() {')
|
g.writeln('void _vcleanup() {')
|
||||||
// g.writeln('puts("cleaning up...");')
|
// g.writeln('puts("cleaning up...");')
|
||||||
g.writeln(g.cleanups.str())
|
g.writeln(g.cleanups.str())
|
||||||
//g.writeln('\tfree(g_str_buf);')
|
// g.writeln('\tfree(g_str_buf);')
|
||||||
g.writeln('}')
|
g.writeln('}')
|
||||||
if g.pref.printfn_list.len > 0 && '_vcleanup' in g.pref.printfn_list {
|
if g.pref.printfn_list.len > 0 && '_vcleanup' in g.pref.printfn_list {
|
||||||
println(g.out.after(fn_vcleanup_start_pos))
|
println(g.out.after(fn_vcleanup_start_pos))
|
||||||
|
|
|
@ -74,7 +74,7 @@ fn (mut g Gen) gen_fn_decl(it ast.FnDecl) {
|
||||||
}
|
}
|
||||||
mut impl_fn_name := name
|
mut impl_fn_name := name
|
||||||
if is_live_wrap {
|
if is_live_wrap {
|
||||||
impl_fn_name = 'impl_live_${name}'
|
impl_fn_name = 'impl_live_$name'
|
||||||
}
|
}
|
||||||
g.last_fn_c_name = impl_fn_name
|
g.last_fn_c_name = impl_fn_name
|
||||||
//
|
//
|
||||||
|
@ -113,17 +113,16 @@ fn (mut g Gen) gen_fn_decl(it ast.FnDecl) {
|
||||||
// an early exit, which will leave the mutex locked.
|
// an early exit, which will leave the mutex locked.
|
||||||
mut fn_args_list := []string{}
|
mut fn_args_list := []string{}
|
||||||
for ia, fa in fargs {
|
for ia, fa in fargs {
|
||||||
fn_args_list << '${fargtypes[ia]} ${fa}'
|
fn_args_list << '${fargtypes[ia]} $fa'
|
||||||
}
|
}
|
||||||
mut live_fncall := '${impl_fn_name}(' + fargs.join(', ') + ');'
|
mut live_fncall := '${impl_fn_name}(' + fargs.join(', ') + ');'
|
||||||
mut live_fnreturn := ''
|
mut live_fnreturn := ''
|
||||||
if type_name != 'void' {
|
if type_name != 'void' {
|
||||||
live_fncall = '${type_name} res = ${live_fncall}'
|
live_fncall = '$type_name res = $live_fncall'
|
||||||
live_fnreturn = 'return res;'
|
live_fnreturn = 'return res;'
|
||||||
}
|
}
|
||||||
g.definitions.writeln('$type_name ${name}(' + fn_args_list.join(', ') + ');')
|
g.definitions.writeln('$type_name ${name}(' + fn_args_list.join(', ') + ');')
|
||||||
g.hotcode_definitions.writeln('$type_name ${name}(' + fn_args_list.join(', ') +
|
g.hotcode_definitions.writeln('$type_name ${name}(' + fn_args_list.join(', ') + '){')
|
||||||
'){')
|
|
||||||
g.hotcode_definitions.writeln(' pthread_mutex_lock(&live_fn_mutex);')
|
g.hotcode_definitions.writeln(' pthread_mutex_lock(&live_fn_mutex);')
|
||||||
g.hotcode_definitions.writeln(' $live_fncall')
|
g.hotcode_definitions.writeln(' $live_fncall')
|
||||||
g.hotcode_definitions.writeln(' pthread_mutex_unlock(&live_fn_mutex);')
|
g.hotcode_definitions.writeln(' pthread_mutex_unlock(&live_fn_mutex);')
|
||||||
|
@ -140,7 +139,7 @@ fn (mut g Gen) gen_fn_decl(it ast.FnDecl) {
|
||||||
// /////////
|
// /////////
|
||||||
if g.autofree {
|
if g.autofree {
|
||||||
// TODO: remove this, when g.write_autofree_stmts_when_needed works properly
|
// TODO: remove this, when g.write_autofree_stmts_when_needed works properly
|
||||||
g.writeln(g.autofree_scope_vars(it.body_pos.pos))
|
// g.writeln(g.autofree_scope_vars(it.body_pos.pos))
|
||||||
}
|
}
|
||||||
g.writeln('}')
|
g.writeln('}')
|
||||||
g.defer_stmts = []
|
g.defer_stmts = []
|
||||||
|
@ -154,12 +153,9 @@ fn (mut g Gen) write_autofree_stmts_when_needed(r ast.Return) {
|
||||||
// TODO: write_autofree_stmts_when_needed should not free the returned variables.
|
// TODO: write_autofree_stmts_when_needed should not free the returned variables.
|
||||||
// It may require rewriting g.return_statement to assign the expressions
|
// It may require rewriting g.return_statement to assign the expressions
|
||||||
// to temporary variables, then protecting *them* from autofreeing ...
|
// to temporary variables, then protecting *them* from autofreeing ...
|
||||||
/*
|
// g.writeln('// autofreeings before return: -------')
|
||||||
g.writeln('/* autofreeings before return: -------')
|
// g.writeln(g.autofree_scope_vars(g.fn_decl.body_pos.pos))
|
||||||
//g.write( g.autofree_scope_vars(r.pos.pos) )
|
// g.writeln('//--------------------------------------------------- ') // //g.write( g.autofree_scope_vars(r.pos.pos) )
|
||||||
g.write( g.autofree_scope_vars(g.fn_decl.body_pos.pos) )
|
|
||||||
g.writeln('--------------------------------------------------- */')
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g Gen) write_defer_stmts_when_needed() {
|
fn (mut g Gen) write_defer_stmts_when_needed() {
|
||||||
|
@ -248,7 +244,9 @@ fn (mut g Gen) call_expr(node ast.CallExpr) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
g.inside_call = true
|
g.inside_call = true
|
||||||
defer {g.inside_call = false}
|
defer {
|
||||||
|
g.inside_call = false
|
||||||
|
}
|
||||||
gen_or := node.or_block.kind != .absent
|
gen_or := node.or_block.kind != .absent
|
||||||
cur_line := if gen_or && g.is_assign_rhs {
|
cur_line := if gen_or && g.is_assign_rhs {
|
||||||
line := g.go_before_stmt(0)
|
line := g.go_before_stmt(0)
|
||||||
|
@ -336,8 +334,8 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
|
||||||
g.gen_str_for_type_with_styp(node.receiver_type, styp)
|
g.gen_str_for_type_with_styp(node.receiver_type, styp)
|
||||||
}
|
}
|
||||||
// TODO performance, detect `array` method differently
|
// TODO performance, detect `array` method differently
|
||||||
if left_sym.kind == .array &&
|
if left_sym.kind == .array && node.name in
|
||||||
node.name in ['repeat', 'sort_with_compare', 'free', 'push_many', 'trim', 'first', 'last', 'clone', 'reverse', 'slice'] {
|
['repeat', 'sort_with_compare', 'free', 'push_many', 'trim', 'first', 'last', 'clone', 'reverse', 'slice'] {
|
||||||
// && rec_sym.name == 'array' {
|
// && rec_sym.name == 'array' {
|
||||||
// && rec_sym.name == 'array' && receiver_name.starts_with('array') {
|
// && rec_sym.name == 'array' && receiver_name.starts_with('array') {
|
||||||
// `array_byte_clone` => `array_clone`
|
// `array_byte_clone` => `array_clone`
|
||||||
|
|
Loading…
Reference in New Issue