checker: make -skip-unused process a list of root functions, not just main.main
parent
41cc72e8e8
commit
167773dd1c
|
@ -7,103 +7,102 @@ import v.checker.mark_used_walker
|
||||||
|
|
||||||
// mark_used walks the AST, starting at main() and marks all used fns transitively
|
// mark_used walks the AST, starting at main() and marks all used fns transitively
|
||||||
fn (mut c Checker) mark_used(ast_files []ast.File) {
|
fn (mut c Checker) mark_used(ast_files []ast.File) {
|
||||||
// println('walking the ast')
|
|
||||||
// c.is_recursive = true
|
|
||||||
// c.fn_decl(mut c.table2.main_fn_decl_node)
|
|
||||||
|
|
||||||
util.timing_start(@METHOD)
|
util.timing_start(@METHOD)
|
||||||
mut walker := mark_used_walker.Walker{
|
mut walker := mark_used_walker.Walker{
|
||||||
files: ast_files
|
files: ast_files
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: walking over the AST using roots != main.main, like `panic`
|
mut allfns := map[string]ast.FnDecl{}
|
||||||
// for example, will potentially eliminate many cases where manual
|
for i in 0 .. ast_files.len {
|
||||||
// whitelisting is needed.
|
file := unsafe { &ast_files[i] }
|
||||||
// TODO: use the full name of the functions in the map. For now the
|
for node in file.stmts {
|
||||||
// receiver type is skipped, so we can not distinguish between
|
if node is ast.FnDecl {
|
||||||
// array.trim and string.trim etc.
|
fkey := if node.is_method {
|
||||||
for stmt in c.main_fn_decl_node.stmts {
|
'${int(node.receiver.typ)}.$node.name'
|
||||||
walker.stmt(stmt)
|
} else {
|
||||||
|
node.name
|
||||||
|
}
|
||||||
|
allfns[fkey] = node
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
all_fn_root_names := [
|
||||||
|
'main.main',
|
||||||
|
'__new_array',
|
||||||
|
'__new_array_with_default',
|
||||||
|
'new_array_from_c_array',
|
||||||
|
'panic',
|
||||||
|
'memdup',
|
||||||
|
'vstrlen',
|
||||||
|
'tos2',
|
||||||
|
'tos',
|
||||||
|
'isnil',
|
||||||
|
'utf8_char_len',
|
||||||
|
'utf8_str_visible_length',
|
||||||
|
'builtin_init',
|
||||||
|
'print_backtrace_skipping_top_frames',
|
||||||
|
'print_backtrace_skipping_top_frames_mac',
|
||||||
|
'print_backtrace_skipping_top_frames_linux',
|
||||||
|
'print_backtrace_skipping_top_frames_freebsd',
|
||||||
|
'print_backtrace_skipping_top_frames_windows',
|
||||||
|
'print_backtrace_skipping_top_frames_mingw',
|
||||||
|
'print_backtrace_skipping_top_frames_msvc',
|
||||||
|
'print_backtrace_skipping_top_frames_tcc',
|
||||||
|
/* byteptr and charptr */
|
||||||
|
'3.vstring',
|
||||||
|
'3.vstring_with_len',
|
||||||
|
'4.vstring',
|
||||||
|
'4.vstring_with_len',
|
||||||
|
/* string. methods */
|
||||||
|
'18.add',
|
||||||
|
'18.all_after',
|
||||||
|
'18.all_before',
|
||||||
|
'18.trim_space',
|
||||||
|
'18.replace',
|
||||||
|
'18.clone',
|
||||||
|
'18.trim',
|
||||||
|
'18.substr',
|
||||||
|
'18.at',
|
||||||
|
'18.index_kmp',
|
||||||
|
/* string. ==, !=, etc... */
|
||||||
|
'18.eq',
|
||||||
|
'18.ne',
|
||||||
|
'18.lt',
|
||||||
|
'18.gt',
|
||||||
|
'18.le',
|
||||||
|
'18.ge',
|
||||||
|
/* ustring. ==, !=, etc... */
|
||||||
|
'19.eq',
|
||||||
|
'19.ne',
|
||||||
|
'19.lt',
|
||||||
|
'19.gt',
|
||||||
|
'19.le',
|
||||||
|
'19.ge',
|
||||||
|
'19.add',
|
||||||
|
/* other array methods */
|
||||||
|
'21.get',
|
||||||
|
'21.get_unsafe',
|
||||||
|
'59.get',
|
||||||
|
'65557.free',
|
||||||
|
'65557.push',
|
||||||
|
'65557.set',
|
||||||
|
'65557.set_unsafe',
|
||||||
|
/* TODO: process the _vinit const initializations automatically too */
|
||||||
|
'os.getwd',
|
||||||
|
'os.init_os_args',
|
||||||
|
]
|
||||||
|
// println( allfns.keys() )
|
||||||
|
for fn_name in all_fn_root_names {
|
||||||
|
walker.fn_decl(mut allfns[fn_name])
|
||||||
}
|
}
|
||||||
// walker.fn_decl(mut c.table2.main_fn_decl_node)
|
|
||||||
// println('time = ${time.ticks() - t}ms, nr used fns=$walker.used_fns.len')
|
|
||||||
|
|
||||||
/*
|
$if trace_skip_unused ? {
|
||||||
for key, _ in walker.used_fns {
|
for key, _ in walker.used_fns {
|
||||||
println(key)
|
println('> used fn key: $key')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
c.table.used_fns = walker.used_fns
|
c.table.used_fns = walker.used_fns
|
||||||
|
|
||||||
// Whitelist some functions that are used by cgen directly:
|
|
||||||
c.table.used_fns['tos'] = true
|
|
||||||
c.table.used_fns['tos2'] = true
|
|
||||||
c.table.used_fns['v_panic'] = true
|
|
||||||
c.table.used_fns['panic'] = true
|
|
||||||
c.table.used_fns['eprintln'] = true
|
|
||||||
c.table.used_fns['print_backtrace_skipping_top_frames'] = true
|
|
||||||
c.table.used_fns['print_backtrace_skipping_top_frames_mac'] = true
|
|
||||||
c.table.used_fns['print_backtrace_skipping_top_frames_linux'] = true
|
|
||||||
c.table.used_fns['print_backtrace_skipping_top_frames_freebsd'] = true
|
|
||||||
c.table.used_fns['print_backtrace_skipping_top_frames_windows'] = true
|
|
||||||
c.table.used_fns['print_backtrace_skipping_top_frames_mingw'] = true
|
|
||||||
c.table.used_fns['print_backtrace_skipping_top_frames_msvc'] = true
|
|
||||||
c.table.used_fns['print_backtrace_skipping_top_frames_tcc'] = true
|
|
||||||
c.table.used_fns['is_atty'] = true
|
|
||||||
c.table.used_fns['add_unhandled_exception_handler'] = true
|
|
||||||
c.table.used_fns['add_vectored_exception_handler'] = true
|
|
||||||
c.table.used_fns['unhandled_exception_handler'] = true
|
|
||||||
c.table.used_fns['restore_codepage'] = true
|
|
||||||
c.table.used_fns['new_array_from_c_array'] = true
|
|
||||||
c.table.used_fns['__new_array_with_default'] = true
|
|
||||||
c.table.used_fns['__new_array'] = true
|
|
||||||
c.table.used_fns['vcalloc'] = true
|
|
||||||
c.table.used_fns['set_unsafe'] = true
|
|
||||||
c.table.used_fns['get_unsafe'] = true
|
|
||||||
c.table.used_fns['push'] = true
|
|
||||||
c.table.used_fns['ensure_cap'] = true
|
|
||||||
c.table.used_fns['v_realloc'] = true
|
|
||||||
c.table.used_fns['all_before'] = true
|
|
||||||
c.table.used_fns['all_after'] = true
|
|
||||||
c.table.used_fns['add'] = true
|
|
||||||
c.table.used_fns['isnil'] = true
|
|
||||||
c.table.used_fns['vstrlen'] = true
|
|
||||||
c.table.used_fns['trim_space'] = true
|
|
||||||
c.table.used_fns['malloc'] = true
|
|
||||||
c.table.used_fns['trim'] = true
|
|
||||||
c.table.used_fns['at'] = true
|
|
||||||
c.table.used_fns['replace'] = true
|
|
||||||
c.table.used_fns['index_'] = true
|
|
||||||
c.table.used_fns['index_after'] = true
|
|
||||||
c.table.used_fns['index_kmp'] = true
|
|
||||||
c.table.used_fns['substr'] = true
|
|
||||||
c.table.used_fns['clone'] = true
|
|
||||||
c.table.used_fns['free'] = true
|
|
||||||
c.table.used_fns['has_index'] = true
|
|
||||||
c.table.used_fns['key'] = true
|
|
||||||
c.table.used_fns['set'] = true
|
|
||||||
c.table.used_fns['get'] = true
|
|
||||||
c.table.used_fns['new_node'] = true
|
|
||||||
c.table.used_fns['eq'] = true
|
|
||||||
c.table.used_fns['ne'] = true
|
|
||||||
c.table.used_fns['lt'] = true
|
|
||||||
c.table.used_fns['gt'] = true
|
|
||||||
c.table.used_fns['le'] = true
|
|
||||||
c.table.used_fns['ge'] = true
|
|
||||||
c.table.used_fns['split_child'] = true
|
|
||||||
c.table.used_fns['bytes'] = true
|
|
||||||
c.table.used_fns['utf8_char_len'] = true
|
|
||||||
c.table.used_fns['utf8_str_visible_length'] = true
|
|
||||||
c.table.used_fns['main.main'] = true
|
|
||||||
c.table.used_fns['builtin_init'] = true
|
|
||||||
c.table.used_fns['memdup'] = true
|
|
||||||
c.table.used_fns['vstring'] = true
|
|
||||||
c.table.used_fns['vstring_with_len'] = true
|
|
||||||
c.table.used_fns['string'] = true // array.string
|
|
||||||
// c.table.used_fns['str'] = true // builtin .str() methods; They use strings.builder and strconv.ftoa_64 etc.
|
|
||||||
// whitelist common modules const initializers too:
|
|
||||||
c.table.used_fns['os.getwd'] = true
|
|
||||||
c.table.used_fns['os.init_os_args'] = true
|
|
||||||
//
|
//
|
||||||
c.table.used_fns['term.can_show_color_on_stdin'] = true
|
c.table.used_fns['term.can_show_color_on_stdin'] = true
|
||||||
c.table.used_fns['term.can_show_color_on_stdout'] = true
|
c.table.used_fns['term.can_show_color_on_stdout'] = true
|
||||||
|
|
|
@ -31,9 +31,9 @@ pub fn (mut w Walker) stmt(node ast.Stmt) {
|
||||||
ast.ExprStmt {
|
ast.ExprStmt {
|
||||||
w.expr(node.expr)
|
w.expr(node.expr)
|
||||||
}
|
}
|
||||||
// ast.FnDecl {
|
ast.FnDecl {
|
||||||
// w.fn_decl(mut node)
|
w.fn_decl(mut node)
|
||||||
//}
|
}
|
||||||
ast.ForStmt {
|
ast.ForStmt {
|
||||||
w.expr(node.cond)
|
w.expr(node.cond)
|
||||||
for stmt in node.stmts {
|
for stmt in node.stmts {
|
||||||
|
@ -79,10 +79,9 @@ fn (mut w Walker) expr(node ast.Expr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
pub fn (mut w Walker) fn_decl(mut node ast.FnDecl) {
|
pub fn (mut w Walker) fn_decl(mut node ast.FnDecl) {
|
||||||
fn_name := if node.is_method { node.receiver.typ.str() + '.' + node.name } else { node.name }
|
fkey := if node.is_method { '${int(node.receiver.typ)}.$node.name' } else { node.name }
|
||||||
if w.used_fns[fn_name] {
|
if w.used_fns[fkey] {
|
||||||
// This function is already known to be called, meaning it has been processed already.
|
// This function is already known to be called, meaning it has been processed already.
|
||||||
// Save CPU time and do nothing.
|
// Save CPU time and do nothing.
|
||||||
return
|
return
|
||||||
|
@ -90,13 +89,11 @@ pub fn (mut w Walker) fn_decl(mut node ast.FnDecl) {
|
||||||
if node.language == .c {
|
if node.language == .c {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// println('fn decl $fn_name')
|
w.used_fns[fkey] = true
|
||||||
w.used_fns[fn_name] = true
|
|
||||||
for stmt in node.stmts {
|
for stmt in node.stmts {
|
||||||
w.stmt(stmt)
|
w.stmt(stmt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
pub fn (mut w Walker) call_expr(mut node ast.CallExpr) {
|
pub fn (mut w Walker) call_expr(mut node ast.CallExpr) {
|
||||||
fn_name := if node.is_method { node.receiver_type.str() + '.' + node.name } else { node.name }
|
fn_name := if node.is_method { node.receiver_type.str() + '.' + node.name } else { node.name }
|
||||||
|
|
|
@ -28,8 +28,11 @@ fn (mut g Gen) gen_fn_decl(node ast.FnDecl, skip bool) {
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
if g.pref.skip_unused {
|
if g.pref.skip_unused {
|
||||||
is_used_by_main := g.table.used_fns[node.name]
|
fkey := if node.is_method { '${int(node.receiver.typ)}.$node.name' } else { node.name }
|
||||||
// println('> is_used_by_main: $is_used_by_main | node.name: $node.name')
|
is_used_by_main := g.table.used_fns[fkey]
|
||||||
|
$if trace_skip_unused ? {
|
||||||
|
println('> is_used_by_main: $is_used_by_main | node.name: $node.name | fkey: $fkey | node.is_method: $node.is_method')
|
||||||
|
}
|
||||||
if !is_used_by_main {
|
if !is_used_by_main {
|
||||||
g.writeln('// fn $node.name UNUSED')
|
g.writeln('// fn $node.name UNUSED')
|
||||||
return
|
return
|
||||||
|
|
Loading…
Reference in New Issue