memory fixes: 21% of V compiler leaks fixed
parent
9b9c1cc834
commit
956bf23390
|
@ -73,7 +73,7 @@ pub fn cgen(files []ast.File, table &table.Table, pref &pref.Preferences) string
|
||||||
for file in files {
|
for file in files {
|
||||||
g.file = file
|
g.file = file
|
||||||
// println('\ncgen "$g.file.path" nr_stmts=$file.stmts.len')
|
// println('\ncgen "$g.file.path" nr_stmts=$file.stmts.len')
|
||||||
building_v := g.file.path.contains('/vlib/') || g.file.path.contains('cmd/v')
|
building_v := true && (g.file.path.contains('/vlib/') || g.file.path.contains('cmd/v'))
|
||||||
is_test := g.file.path.ends_with('.vv') || g.file.path.ends_with('_test.v')
|
is_test := g.file.path.ends_with('.vv') || g.file.path.ends_with('_test.v')
|
||||||
if g.file.path.ends_with('_test.v') {
|
if g.file.path.ends_with('_test.v') {
|
||||||
g.is_test = is_test
|
g.is_test = is_test
|
||||||
|
@ -454,7 +454,7 @@ fn (g mut Gen) for_in(it ast.ForInStmt) {
|
||||||
g.write('; $i < ')
|
g.write('; $i < ')
|
||||||
g.expr(it.high)
|
g.expr(it.high)
|
||||||
g.writeln('; $i++) { ')
|
g.writeln('; $i++) { ')
|
||||||
g.writeln('int $it.val_var = $i;')
|
g.writeln('\tint $it.val_var = $i;')
|
||||||
g.stmts(it.stmts)
|
g.stmts(it.stmts)
|
||||||
g.writeln('}')
|
g.writeln('}')
|
||||||
}
|
}
|
||||||
|
@ -467,7 +467,7 @@ fn (g mut Gen) for_in(it ast.ForInStmt) {
|
||||||
g.write('for (int $i = 0; $i < ')
|
g.write('for (int $i = 0; $i < ')
|
||||||
g.expr(it.cond)
|
g.expr(it.cond)
|
||||||
g.writeln('.len; $i++) {')
|
g.writeln('.len; $i++) {')
|
||||||
g.write('$styp $it.val_var = (($styp*)')
|
g.write('\t$styp $it.val_var = (($styp*)')
|
||||||
g.expr(it.cond)
|
g.expr(it.cond)
|
||||||
g.writeln('.data)[$i];')
|
g.writeln('.data)[$i];')
|
||||||
g.stmts(it.stmts)
|
g.stmts(it.stmts)
|
||||||
|
@ -486,8 +486,8 @@ fn (g mut Gen) for_in(it ast.ForInStmt) {
|
||||||
g.expr(it.cond)
|
g.expr(it.cond)
|
||||||
g.writeln(');')
|
g.writeln(');')
|
||||||
g.writeln('for (int $idx = 0; $idx < ${keys_tmp}.len; $idx++) {')
|
g.writeln('for (int $idx = 0; $idx < ${keys_tmp}.len; $idx++) {')
|
||||||
g.writeln('$key_styp $key = (($key_styp*)${keys_tmp}.data)[$idx];')
|
g.writeln('\t$key_styp $key = (($key_styp*)${keys_tmp}.data)[$idx];')
|
||||||
g.write('$val_styp $it.val_var = (*($val_styp*)map_get3(')
|
g.write('\t$val_styp $it.val_var = (*($val_styp*)map_get3(')
|
||||||
g.expr(it.cond)
|
g.expr(it.cond)
|
||||||
g.writeln(', $key, &($val_styp[]){ $zero }));')
|
g.writeln(', $key, &($val_styp[]){ $zero }));')
|
||||||
g.stmts(it.stmts)
|
g.stmts(it.stmts)
|
||||||
|
@ -641,36 +641,28 @@ fn (g mut Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
mut is_fixed_array_init := false
|
|
||||||
mut is_ident := false
|
|
||||||
right_sym := g.table.get_type_symbol(assign_stmt.right_types[i])
|
right_sym := g.table.get_type_symbol(assign_stmt.right_types[i])
|
||||||
|
mut is_fixed_array_init := false
|
||||||
match val {
|
match val {
|
||||||
ast.ArrayInit {
|
ast.ArrayInit {
|
||||||
is_fixed_array_init = right_sym.kind == .array_fixed
|
is_fixed_array_init = right_sym.kind == .array_fixed
|
||||||
}
|
}
|
||||||
ast.Ident {
|
|
||||||
is_ident = true
|
|
||||||
}
|
|
||||||
else {}
|
else {}
|
||||||
}
|
}
|
||||||
is_decl := assign_stmt.op == .decl_assign
|
is_decl := assign_stmt.op == .decl_assign
|
||||||
|
g.write('/*assign_stmt*/')
|
||||||
if is_decl {
|
if is_decl {
|
||||||
g.write('$styp ')
|
g.write('$styp ')
|
||||||
}
|
}
|
||||||
g.expr(ident)
|
g.expr(ident)
|
||||||
if g.autofree && right_sym.kind == .array && is_ident {
|
if g.autofree && right_sym.kind in [.array, .string] {
|
||||||
// `arr1 = arr2` => `arr1 = arr2.clone()`
|
if g.gen_clone_assignment(val, right_sym, true) {
|
||||||
g.write(' = array_clone(&')
|
g.writeln(';')
|
||||||
g.expr(val)
|
// g.expr_var_name = ''
|
||||||
g.write(')')
|
return
|
||||||
}
|
}
|
||||||
else if g.autofree && right_sym.kind == .string && is_ident {
|
|
||||||
// `str1 = str2` => `str1 = str2.clone()`
|
|
||||||
g.write(' = string_clone(')
|
|
||||||
g.expr(val)
|
|
||||||
g.write(')')
|
|
||||||
}
|
}
|
||||||
else if !is_fixed_array_init {
|
if !is_fixed_array_init {
|
||||||
g.write(' = ')
|
g.write(' = ')
|
||||||
if !is_decl {
|
if !is_decl {
|
||||||
g.expr_with_cast(val, assign_stmt.left_types[i], ident_var_info.typ)
|
g.expr_with_cast(val, assign_stmt.left_types[i], ident_var_info.typ)
|
||||||
|
@ -692,6 +684,40 @@ fn (g mut Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (g mut Gen) gen_clone_assignment(val ast.Expr, right_sym table.TypeSymbol, add_eq bool) bool {
|
||||||
|
mut is_ident := false
|
||||||
|
match val {
|
||||||
|
ast.Ident {
|
||||||
|
is_ident = true
|
||||||
|
}
|
||||||
|
ast.SelectorExpr {
|
||||||
|
is_ident = true
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if g.autofree && right_sym.kind == .array && is_ident {
|
||||||
|
// `arr1 = arr2` => `arr1 = arr2.clone()`
|
||||||
|
if add_eq {
|
||||||
|
g.write('=')
|
||||||
|
}
|
||||||
|
g.write(' array_clone(&')
|
||||||
|
g.expr(val)
|
||||||
|
g.write(')')
|
||||||
|
}
|
||||||
|
else if g.autofree && right_sym.kind == .string && is_ident {
|
||||||
|
if add_eq {
|
||||||
|
g.write('=')
|
||||||
|
}
|
||||||
|
// `str1 = str2` => `str1 = str2.clone()`
|
||||||
|
g.write(' string_clone(')
|
||||||
|
g.expr(val)
|
||||||
|
g.write(')')
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
fn (g mut Gen) gen_fn_decl(it ast.FnDecl) {
|
fn (g mut Gen) gen_fn_decl(it ast.FnDecl) {
|
||||||
if it.is_c {
|
if it.is_c {
|
||||||
// || it.no_body {
|
// || it.no_body {
|
||||||
|
@ -1173,7 +1199,18 @@ fn (g mut Gen) assign_expr(node ast.AssignExpr) {
|
||||||
g.write(', ')
|
g.write(', ')
|
||||||
}
|
}
|
||||||
g.is_assign_lhs = false
|
g.is_assign_lhs = false
|
||||||
|
right_sym := g.table.get_type_symbol(node.right_type)
|
||||||
|
// left_sym := g.table.get_type_symbol(node.left_type)
|
||||||
|
mut cloned := false
|
||||||
|
// !g.is_array_set
|
||||||
|
if g.autofree && right_sym.kind in [.array, .string] {
|
||||||
|
if g.gen_clone_assignment(node.val, right_sym, false) {
|
||||||
|
cloned = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !cloned {
|
||||||
g.expr_with_cast(node.val, node.right_type, node.left_type)
|
g.expr_with_cast(node.val, node.right_type, node.left_type)
|
||||||
|
}
|
||||||
if g.is_array_set {
|
if g.is_array_set {
|
||||||
g.write(' })')
|
g.write(' })')
|
||||||
g.is_array_set = false
|
g.is_array_set = false
|
||||||
|
@ -1397,7 +1434,7 @@ fn (g mut Gen) match_expr(node ast.MatchExpr) {
|
||||||
ast.Type {
|
ast.Type {
|
||||||
it_type := g.typ(it.typ)
|
it_type := g.typ(it.typ)
|
||||||
// g.writeln('$it_type* it = ($it_type*)${tmp}.obj; // ST it')
|
// g.writeln('$it_type* it = ($it_type*)${tmp}.obj; // ST it')
|
||||||
g.write('$it_type* it = ($it_type*)')
|
g.write('\t$it_type* it = ($it_type*)')
|
||||||
g.expr(node.cond)
|
g.expr(node.cond)
|
||||||
g.writeln('.obj; // ST it')
|
g.writeln('.obj; // ST it')
|
||||||
}
|
}
|
||||||
|
@ -2194,6 +2231,17 @@ fn (g mut Gen) call_expr(node ast.CallExpr) {
|
||||||
g.write('$styp $tmp_opt = ')
|
g.write('$styp $tmp_opt = ')
|
||||||
}
|
}
|
||||||
if node.is_method {
|
if node.is_method {
|
||||||
|
g.method_call(node)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
g.fn_call(node)
|
||||||
|
}
|
||||||
|
if gen_or {
|
||||||
|
g.or_block(tmp_opt, node.or_block.stmts, node.return_type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn (g mut Gen) method_call(node ast.CallExpr) {
|
||||||
// TODO: there are still due to unchecked exprs (opt/some fn arg)
|
// TODO: there are still due to unchecked exprs (opt/some fn arg)
|
||||||
if node.left_type == 0 {
|
if node.left_type == 0 {
|
||||||
verror('method receiver type is 0, this means there are some uchecked exprs')
|
verror('method receiver type is 0, this means there are some uchecked exprs')
|
||||||
|
@ -2253,8 +2301,12 @@ fn (g mut Gen) call_expr(node ast.CallExpr) {
|
||||||
// ///////
|
// ///////
|
||||||
g.call_args(node.args, node.exp_arg_types)
|
g.call_args(node.args, node.exp_arg_types)
|
||||||
g.write(')')
|
g.write(')')
|
||||||
|
// if node.or_block.stmts.len > 0 {
|
||||||
|
// g.or_block(node.or_block.stmts, node.return_type)
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
|
fn (g mut Gen) fn_call(node ast.CallExpr) {
|
||||||
mut name := node.name
|
mut name := node.name
|
||||||
is_print := name == 'println'
|
is_print := name == 'println'
|
||||||
if node.is_c {
|
if node.is_c {
|
||||||
|
@ -2311,12 +2363,11 @@ fn (g mut Gen) call_expr(node ast.CallExpr) {
|
||||||
g.call_args(node.args, node.exp_arg_types)
|
g.call_args(node.args, node.exp_arg_types)
|
||||||
g.write(')')
|
g.write(')')
|
||||||
}
|
}
|
||||||
|
// if node.or_block.stmts.len > 0 {
|
||||||
|
// g.or_block(node.or_block.stmts, node.return_type)
|
||||||
|
// }
|
||||||
g.is_c_call = false
|
g.is_c_call = false
|
||||||
}
|
}
|
||||||
if gen_or {
|
|
||||||
g.or_block(tmp_opt, node.or_block.stmts, node.return_type)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If user is accessing the return value eg. in assigment, pass the variable name.
|
// If user is accessing the return value eg. in assigment, pass the variable name.
|
||||||
// If the user is not using the optional return value. We need to pass a temp var
|
// If the user is not using the optional return value. We need to pass a temp var
|
||||||
|
|
|
@ -26,7 +26,7 @@ fn (p mut Parser) comp_if() ast.CompIf {
|
||||||
// `$if os {` for a different target, skip everything inside
|
// `$if os {` for a different target, skip everything inside
|
||||||
// to avoid compilation errors (like including <windows.h> or calling WinAPI fns
|
// to avoid compilation errors (like including <windows.h> or calling WinAPI fns
|
||||||
// on non-Windows systems)
|
// on non-Windows systems)
|
||||||
if ((!is_not && os != p.pref.os) || (is_not && os == p.pref.os)) && !p.pref.output_cross_c {
|
if false && ((!is_not && os != p.pref.os) || (is_not && os == p.pref.os)) && !p.pref.output_cross_c {
|
||||||
skip_os = true
|
skip_os = true
|
||||||
p.check(.lcbr)
|
p.check(.lcbr)
|
||||||
// p.warn('skipping $if $val os=$os p.pref.os=$p.pref.os')
|
// p.warn('skipping $if $val os=$os p.pref.os=$p.pref.os')
|
||||||
|
|
|
@ -70,9 +70,10 @@ pub fn (p mut Parser) parse_multi_return_type() table.Type {
|
||||||
pub fn (p mut Parser) parse_fn_type(name string) table.Type {
|
pub fn (p mut Parser) parse_fn_type(name string) table.Type {
|
||||||
// p.warn('parse fn')
|
// p.warn('parse fn')
|
||||||
p.check(.key_fn)
|
p.check(.key_fn)
|
||||||
|
line_nr := p.tok.line_nr
|
||||||
args,is_variadic := p.fn_args()
|
args,is_variadic := p.fn_args()
|
||||||
mut return_type := table.void_type
|
mut return_type := table.void_type
|
||||||
if p.tok.kind.is_start_of_type() {
|
if p.tok.line_nr == line_nr && p.tok.kind.is_start_of_type() {
|
||||||
return_type = p.parse_type()
|
return_type = p.parse_type()
|
||||||
}
|
}
|
||||||
func := table.Fn{
|
func := table.Fn{
|
||||||
|
|
|
@ -1520,6 +1520,13 @@ fn (p mut Parser) struct_decl() ast.StructDecl {
|
||||||
field_name := p.check_name()
|
field_name := p.check_name()
|
||||||
// p.warn('field $field_name')
|
// p.warn('field $field_name')
|
||||||
typ := p.parse_type()
|
typ := p.parse_type()
|
||||||
|
/*
|
||||||
|
if name == '_net_module_s' {
|
||||||
|
s := p.table.get_type_symbol(typ)
|
||||||
|
println('XXXX' + s.str())
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// Default value
|
// Default value
|
||||||
if p.tok.kind == .assign {
|
if p.tok.kind == .assign {
|
||||||
p.next()
|
p.next()
|
||||||
|
|
Loading…
Reference in New Issue