builder,checker: split the unused marking into a new `v.markused` module
parent
4ef3a21c8a
commit
e809264f12
|
@ -5,6 +5,7 @@ import v.parser
|
||||||
import v.pref
|
import v.pref
|
||||||
import v.util
|
import v.util
|
||||||
import v.gen.c
|
import v.gen.c
|
||||||
|
import v.markused
|
||||||
|
|
||||||
pub fn (mut b Builder) gen_c(v_files []string) string {
|
pub fn (mut b Builder) gen_c(v_files []string) string {
|
||||||
util.timing_start('PARSE')
|
util.timing_start('PARSE')
|
||||||
|
@ -20,6 +21,10 @@ pub fn (mut b Builder) gen_c(v_files []string) string {
|
||||||
b.checker.check_files(b.parsed_files)
|
b.checker.check_files(b.parsed_files)
|
||||||
util.timing_measure('CHECK')
|
util.timing_measure('CHECK')
|
||||||
//
|
//
|
||||||
|
if b.pref.skip_unused {
|
||||||
|
markused.mark_used(mut b.table, b.pref, b.parsed_files)
|
||||||
|
}
|
||||||
|
|
||||||
b.print_warnings_and_errors()
|
b.print_warnings_and_errors()
|
||||||
// TODO: move gen.cgen() to c.gen()
|
// TODO: move gen.cgen() to c.gen()
|
||||||
util.timing_start('C GEN')
|
util.timing_start('C GEN')
|
||||||
|
|
|
@ -212,9 +212,6 @@ pub fn (mut c Checker) check_files(ast_files []ast.File) {
|
||||||
c.error('a _test.v file should have *at least* one `test_` function', token.Position{})
|
c.error('a _test.v file should have *at least* one `test_` function', token.Position{})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if c.pref.skip_unused {
|
|
||||||
c.mark_used(ast_files)
|
|
||||||
}
|
|
||||||
// Make sure fn main is defined in non lib builds
|
// Make sure fn main is defined in non lib builds
|
||||||
if c.pref.build_mode == .build_module || c.pref.is_test {
|
if c.pref.build_mode == .build_module || c.pref.is_test {
|
||||||
return
|
return
|
||||||
|
|
|
@ -1,39 +1,20 @@
|
||||||
module checker
|
// Copyright (c) 2019-2021 Alexander Medvednikov. All rights reserved.
|
||||||
|
// Use of this source code is governed by an MIT license that can be found in the LICENSE file.
|
||||||
|
module markused
|
||||||
|
|
||||||
import v.ast
|
import v.ast
|
||||||
import v.table
|
import v.table
|
||||||
import v.util
|
import v.util
|
||||||
import v.checker.mark_used_walker
|
import v.pref
|
||||||
|
|
||||||
// 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) {
|
pub fn mark_used(mut the_table table.Table, pref &pref.Preferences, ast_files []ast.File) {
|
||||||
|
mut all_fns, all_consts := all_fn_and_const(ast_files)
|
||||||
|
|
||||||
util.timing_start(@METHOD)
|
util.timing_start(@METHOD)
|
||||||
util.timing_start('all_fn_and_const')
|
defer {
|
||||||
mut all_fns := map[string]ast.FnDecl{}
|
util.timing_measure(@METHOD)
|
||||||
mut all_consts := map[string]ast.ConstField{}
|
|
||||||
for i in 0 .. ast_files.len {
|
|
||||||
file := unsafe { &ast_files[i] }
|
|
||||||
for node in file.stmts {
|
|
||||||
match node {
|
|
||||||
ast.FnDecl {
|
|
||||||
fkey := if node.is_method {
|
|
||||||
'${int(node.receiver.typ)}.$node.name'
|
|
||||||
} else {
|
|
||||||
node.name
|
|
||||||
}
|
}
|
||||||
all_fns[fkey] = node
|
|
||||||
}
|
|
||||||
ast.ConstDecl {
|
|
||||||
for cfield in node.fields {
|
|
||||||
ckey := cfield.name
|
|
||||||
all_consts[ckey] = cfield
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
util.timing_measure('all_fn_and_const')
|
|
||||||
|
|
||||||
mut all_fn_root_names := [
|
mut all_fn_root_names := [
|
||||||
'main.main',
|
'main.main',
|
||||||
|
@ -120,7 +101,7 @@ fn (mut c Checker) mark_used(ast_files []ast.File) {
|
||||||
|
|
||||||
// implicit string builders are generated in auto_eq_methods.v
|
// implicit string builders are generated in auto_eq_methods.v
|
||||||
mut sb_mut_type := ''
|
mut sb_mut_type := ''
|
||||||
if sbfn := c.table.find_fn('strings.new_builder') {
|
if sbfn := the_table.find_fn('strings.new_builder') {
|
||||||
sb_mut_type = sbfn.return_type.set_nr_muls(1).str() + '.'
|
sb_mut_type = sbfn.return_type.set_nr_muls(1).str() + '.'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,7 +119,7 @@ fn (mut c Checker) mark_used(ast_files []ast.File) {
|
||||||
|| k.ends_with('.runlock') {
|
|| k.ends_with('.runlock') {
|
||||||
all_fn_root_names << k
|
all_fn_root_names << k
|
||||||
}
|
}
|
||||||
if c.pref.is_test {
|
if pref.is_test {
|
||||||
if k.starts_with('test_') || k.contains('.test_') {
|
if k.starts_with('test_') || k.contains('.test_') {
|
||||||
all_fn_root_names << k
|
all_fn_root_names << k
|
||||||
}
|
}
|
||||||
|
@ -151,13 +132,13 @@ fn (mut c Checker) mark_used(ast_files []ast.File) {
|
||||||
all_fn_root_names << k
|
all_fn_root_names << k
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if c.pref.is_debug {
|
if pref.is_debug {
|
||||||
all_fn_root_names << 'panic_debug'
|
all_fn_root_names << 'panic_debug'
|
||||||
}
|
}
|
||||||
if c.pref.is_test {
|
if pref.is_test {
|
||||||
all_fn_root_names << 'main.cb_assertion_ok'
|
all_fn_root_names << 'main.cb_assertion_ok'
|
||||||
all_fn_root_names << 'main.cb_assertion_failed'
|
all_fn_root_names << 'main.cb_assertion_failed'
|
||||||
if benched_tests_sym := c.table.find_type('main.BenchedTests') {
|
if benched_tests_sym := the_table.find_type('main.BenchedTests') {
|
||||||
bts_type := benched_tests_sym.methods[0].params[0].typ
|
bts_type := benched_tests_sym.methods[0].params[0].typ
|
||||||
all_fn_root_names << '${bts_type}.testing_step_start'
|
all_fn_root_names << '${bts_type}.testing_step_start'
|
||||||
all_fn_root_names << '${bts_type}.testing_step_end'
|
all_fn_root_names << '${bts_type}.testing_step_end'
|
||||||
|
@ -166,8 +147,8 @@ fn (mut c Checker) mark_used(ast_files []ast.File) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mut walker := mark_used_walker.Walker{
|
mut walker := Walker{
|
||||||
table: c.table
|
table: the_table
|
||||||
files: ast_files
|
files: ast_files
|
||||||
all_fns: all_fns
|
all_fns: all_fns
|
||||||
all_consts: all_consts
|
all_consts: all_consts
|
||||||
|
@ -197,13 +178,44 @@ fn (mut c Checker) mark_used(ast_files []ast.File) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
c.table.used_fns = walker.used_fns
|
the_table.used_fns = walker.used_fns
|
||||||
c.table.used_consts = walker.used_consts
|
the_table.used_consts = walker.used_consts
|
||||||
|
|
||||||
$if trace_skip_unused ? {
|
$if trace_skip_unused ? {
|
||||||
eprintln('>> c.table.used_fns: $c.table.used_fns.keys()')
|
eprintln('>> the_table.used_fns: $the_table.used_fns.keys()')
|
||||||
eprintln('>> c.table.used_consts: $c.table.used_consts.keys()')
|
eprintln('>> the_table.used_consts: $the_table.used_consts.keys()')
|
||||||
eprintln('>> walker.n_maps: $walker.n_maps')
|
eprintln('>> walker.n_maps: $walker.n_maps')
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn all_fn_and_const(ast_files []ast.File) (map[string]ast.FnDecl, map[string]ast.ConstField) {
|
||||||
|
util.timing_start(@METHOD)
|
||||||
|
defer {
|
||||||
util.timing_measure(@METHOD)
|
util.timing_measure(@METHOD)
|
||||||
}
|
}
|
||||||
|
mut all_fns := map[string]ast.FnDecl{}
|
||||||
|
mut all_consts := map[string]ast.ConstField{}
|
||||||
|
for i in 0 .. ast_files.len {
|
||||||
|
file := unsafe { &ast_files[i] }
|
||||||
|
for node in file.stmts {
|
||||||
|
match node {
|
||||||
|
ast.FnDecl {
|
||||||
|
fkey := if node.is_method {
|
||||||
|
'${int(node.receiver.typ)}.$node.name'
|
||||||
|
} else {
|
||||||
|
node.name
|
||||||
|
}
|
||||||
|
all_fns[fkey] = node
|
||||||
|
}
|
||||||
|
ast.ConstDecl {
|
||||||
|
for cfield in node.fields {
|
||||||
|
ckey := cfield.name
|
||||||
|
all_consts[ckey] = cfield
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return all_fns, all_consts
|
||||||
|
}
|
|
@ -1,8 +1,8 @@
|
||||||
// Copyright (c) 2019-2021 Alexander Medvednikov. All rights reserved.
|
// Copyright (c) 2019-2021 Alexander Medvednikov. All rights reserved.
|
||||||
// Use of this source code is governed by an MIT license that can be found in the LICENSE file.
|
// Use of this source code is governed by an MIT license that can be found in the LICENSE file.
|
||||||
module mark_used_walker
|
module markused
|
||||||
|
|
||||||
// This module walks the entire program starting at fn main and marks used (called) functions.
|
// Walk the entire program starting at fn main and marks used (called) functions.
|
||||||
// Unused functions can be safely skipped by the backends to save CPU time and space.
|
// Unused functions can be safely skipped by the backends to save CPU time and space.
|
||||||
import v.ast
|
import v.ast
|
||||||
import v.table
|
import v.table
|
Loading…
Reference in New Issue