mirror of
https://github.com/vlang/v.git
synced 2025-08-04 02:07:28 -04:00
v: missing -skip-unused
fixes (#22978)
This commit is contained in:
parent
066384ce8c
commit
ae4a9047c1
@ -88,7 +88,7 @@ mut:
|
||||
values &u8 = unsafe { nil }
|
||||
}
|
||||
|
||||
@[inline; markused]
|
||||
@[inline]
|
||||
fn new_dense_array(key_bytes int, value_bytes int) DenseArray {
|
||||
cap := 8
|
||||
return DenseArray{
|
||||
@ -103,18 +103,18 @@ fn new_dense_array(key_bytes int, value_bytes int) DenseArray {
|
||||
}
|
||||
}
|
||||
|
||||
@[inline; markused]
|
||||
@[inline]
|
||||
fn (d &DenseArray) key(i int) voidptr {
|
||||
return unsafe { voidptr(d.keys + i * d.key_bytes) }
|
||||
}
|
||||
|
||||
// for cgen
|
||||
@[inline; markused]
|
||||
@[inline]
|
||||
fn (d &DenseArray) value(i int) voidptr {
|
||||
return unsafe { voidptr(d.values + i * d.value_bytes) }
|
||||
}
|
||||
|
||||
@[inline; markused]
|
||||
@[inline]
|
||||
fn (d &DenseArray) has_index(i int) bool {
|
||||
return d.deletes == 0 || unsafe { d.all_deleted[i] } == 0
|
||||
}
|
||||
@ -259,7 +259,6 @@ fn map_free_string(pkey voidptr) {
|
||||
fn map_free_nop(_ voidptr) {
|
||||
}
|
||||
|
||||
@[markused]
|
||||
fn new_map(key_bytes int, value_bytes int, hash_fn MapHashFn, key_eq_fn MapEqFn, clone_fn MapCloneFn, free_fn MapFreeFn) map {
|
||||
metasize := int(sizeof(u32) * (init_capicity + extra_metas_inc))
|
||||
// for now assume anything bigger than a pointer is a string
|
||||
|
@ -12,10 +12,10 @@ pub struct UsedFeatures {
|
||||
pub mut:
|
||||
interfaces bool // interface
|
||||
dump bool // dump()
|
||||
builtin_types bool // uses any builtin type
|
||||
index bool // string[0]
|
||||
range_index bool // string[0..1]
|
||||
cast_ptr bool // &u8(...)
|
||||
asserts bool // assert expr
|
||||
as_cast bool // expr as Type
|
||||
anon_fn bool // fn () { }
|
||||
auto_str bool // auto str fns
|
||||
@ -24,6 +24,11 @@ pub mut:
|
||||
arr_first bool // arr.first()
|
||||
arr_last bool // arr.last()
|
||||
arr_pop bool // arr.pop()
|
||||
arr_delete bool // arr.delete()
|
||||
arr_init bool // [1, 2, 3]
|
||||
arr_map bool // []map[key]value
|
||||
map_update bool // {...foo}
|
||||
interpolation bool // '${foo} ${bar}'
|
||||
option_or_result bool // has panic call
|
||||
print_types map[int]bool // print() idx types
|
||||
used_fns map[string]bool // filled in by markused
|
||||
@ -32,6 +37,7 @@ pub mut:
|
||||
used_veb_types []Type // veb context types, filled in by checker
|
||||
used_maps int // how many times maps were used, filled in by markused
|
||||
used_arrays int // how many times arrays were used, filled in by markused
|
||||
used_modules map[string]bool // filled in checker
|
||||
// json bool // json is imported
|
||||
debugger bool // debugger is used
|
||||
comptime_calls map[string]bool // resolved $method() names
|
||||
|
@ -2302,11 +2302,20 @@ fn (mut c Checker) stmt(mut node ast.Stmt) {
|
||||
|
||||
fn (mut c Checker) assert_stmt(mut node ast.AssertStmt) {
|
||||
if node.is_used {
|
||||
c.table.used_features.auto_str = true
|
||||
c.table.used_features.asserts = true
|
||||
}
|
||||
cur_exp_typ := c.expected_type
|
||||
c.expected_type = ast.bool_type
|
||||
assert_type := c.check_expr_option_or_result_call(node.expr, c.expr(mut node.expr))
|
||||
if c.pref.skip_unused && !c.table.used_features.auto_str && !c.is_builtin_mod
|
||||
&& mut node.expr is ast.InfixExpr {
|
||||
if !c.table.sym(c.unwrap_generic(node.expr.left_type)).has_method('str') {
|
||||
c.table.used_features.auto_str = true
|
||||
}
|
||||
if !c.table.sym(c.unwrap_generic(node.expr.right_type)).has_method('str') {
|
||||
c.table.used_features.auto_str = true
|
||||
}
|
||||
}
|
||||
if assert_type != ast.bool_type_idx {
|
||||
atype_name := c.table.sym(assert_type).name
|
||||
c.error('assert can be used only with `bool` expressions, but found `${atype_name}` instead',
|
||||
@ -2949,6 +2958,7 @@ pub fn (mut c Checker) expr(mut node ast.Expr) ast.Type {
|
||||
return c.concat_expr(mut node)
|
||||
}
|
||||
ast.DumpExpr {
|
||||
c.table.used_features.dump = true
|
||||
c.expected_type = ast.string_type
|
||||
node.expr_type = c.expr(mut node.expr)
|
||||
if c.pref.skip_unused && !c.is_builtin_mod {
|
||||
@ -3268,7 +3278,8 @@ fn (mut c Checker) cast_expr(mut node ast.CastExpr) ast.Type {
|
||||
to_type
|
||||
}
|
||||
final_to_is_ptr := to_type.is_ptr() || final_to_type.is_ptr()
|
||||
if to_type.is_ptr() {
|
||||
if c.pref.skip_unused && !c.is_builtin_mod && c.mod !in ['strings', 'math.bits']
|
||||
&& to_type.is_ptr() {
|
||||
c.table.used_features.cast_ptr = true
|
||||
}
|
||||
if to_type.has_flag(.result) {
|
||||
@ -4763,9 +4774,11 @@ fn (mut c Checker) index_expr(mut node ast.IndexExpr) ast.Type {
|
||||
}
|
||||
else {}
|
||||
}
|
||||
c.table.used_features.index = true
|
||||
if node.index is ast.RangeExpr {
|
||||
c.table.used_features.range_index = true
|
||||
if !c.is_builtin_mod && c.mod !in ['strings', 'math.bits'] {
|
||||
if node.index is ast.RangeExpr {
|
||||
c.table.used_features.range_index = true
|
||||
}
|
||||
c.table.used_features.index = true
|
||||
}
|
||||
is_aggregate_arr := typ_sym.kind == .aggregate
|
||||
&& (typ_sym.info as ast.Aggregate).types.filter(c.table.type_kind(it) !in [.array, .array_fixed, .string, .map]).len == 0
|
||||
|
@ -13,6 +13,9 @@ fn (mut c Checker) array_init(mut node ast.ArrayInit) ast.Type {
|
||||
}
|
||||
// `x := []string{}` (the type was set in the parser)
|
||||
if node.typ != ast.void_type {
|
||||
if !c.is_builtin_mod && c.mod !in ['builtin', 'strings', 'strconv', 'math.bits'] {
|
||||
c.table.used_features.arr_init = true
|
||||
}
|
||||
if node.elem_type != 0 {
|
||||
elem_sym := c.table.sym(node.elem_type)
|
||||
|
||||
@ -61,6 +64,11 @@ fn (mut c Checker) array_init(mut node ast.ArrayInit) ast.Type {
|
||||
c.warn('byte is deprecated, use u8 instead', node.elem_type_pos)
|
||||
}
|
||||
}
|
||||
ast.Map {
|
||||
if c.pref.skip_unused && !c.is_builtin_mod {
|
||||
c.table.used_features.arr_map = true
|
||||
}
|
||||
}
|
||||
else {}
|
||||
}
|
||||
}
|
||||
@ -143,6 +151,9 @@ fn (mut c Checker) array_init(mut node ast.ArrayInit) ast.Type {
|
||||
}
|
||||
// `[1,2,3]`
|
||||
if node.exprs.len > 0 && node.elem_type == ast.void_type {
|
||||
if !c.is_builtin_mod && c.mod !in ['builtin', 'strings', 'strconv', 'math.bits'] {
|
||||
c.table.used_features.arr_init = true
|
||||
}
|
||||
mut expected_value_type := ast.void_type
|
||||
mut expecting_interface_array := false
|
||||
mut expecting_sumtype_array := false
|
||||
@ -495,6 +506,7 @@ fn (mut c Checker) map_init(mut node ast.MapInit) ast.Type {
|
||||
}
|
||||
|
||||
if (node.keys.len > 0 && node.vals.len > 0) || node.has_update_expr {
|
||||
c.table.used_features.map_update = true
|
||||
mut map_type := ast.void_type
|
||||
use_expected_type := c.expected_type != ast.void_type && !c.inside_const
|
||||
&& c.table.sym(c.expected_type).kind == .map && !(c.inside_fn_arg
|
||||
|
@ -751,8 +751,23 @@ fn (mut c Checker) call_expr(mut node ast.CallExpr) ast.Type {
|
||||
c.inside_or_block_value = true
|
||||
c.check_or_expr(node.or_block, typ, c.expected_or_type, node)
|
||||
c.inside_or_block_value = old_inside_or_block_value
|
||||
} else if node.or_block.kind == .propagate_option || node.or_block.kind == .propagate_result {
|
||||
if c.pref.skip_unused && !c.is_builtin_mod && c.mod != 'strings' {
|
||||
c.table.used_features.option_or_result = true
|
||||
}
|
||||
}
|
||||
c.expected_or_type = old_expected_or_type
|
||||
if c.pref.skip_unused && !c.is_builtin_mod && c.mod == 'main' {
|
||||
if node.is_method {
|
||||
type_str := c.table.type_to_str(node.left_type)
|
||||
if c.table.sym(node.left_type).is_builtin()
|
||||
&& type_str !in c.table.used_features.used_modules {
|
||||
c.table.used_features.used_modules[type_str] = true
|
||||
}
|
||||
} else if node.name.contains('.') {
|
||||
c.table.used_features.used_modules[node.name.all_before('.')] = true
|
||||
}
|
||||
}
|
||||
|
||||
if !c.inside_const && c.table.cur_fn != unsafe { nil } && !c.table.cur_fn.is_main
|
||||
&& !c.table.cur_fn.is_test {
|
||||
@ -1401,7 +1416,8 @@ fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool) ast.
|
||||
// println / eprintln / panic can print anything
|
||||
if node.args.len > 0 && fn_name in print_everything_fns {
|
||||
c.builtin_args(mut node, fn_name, func)
|
||||
if c.pref.skip_unused && !c.is_builtin_mod && node.args[0].expr !is ast.StringLiteral {
|
||||
if c.pref.skip_unused && !c.is_builtin_mod && c.mod != 'math.bits'
|
||||
&& node.args[0].expr !is ast.StringLiteral {
|
||||
if !c.table.sym(c.unwrap_generic(node.args[0].typ)).has_method('str') {
|
||||
c.table.used_features.auto_str = true
|
||||
if node.args[0].typ.is_ptr() {
|
||||
@ -2162,9 +2178,6 @@ fn (mut c Checker) method_call(mut node ast.CallExpr, mut continue_check &bool)
|
||||
continue_check = false
|
||||
return ast.void_type
|
||||
}
|
||||
if c.pref.skip_unused && !c.is_builtin_mod && c.mod != 'strings' {
|
||||
c.table.used_features.builtin_types = true
|
||||
}
|
||||
c.expected_type = left_type
|
||||
mut is_generic := left_type.has_flag(.generic)
|
||||
node.left_type = left_type
|
||||
@ -2949,6 +2962,9 @@ fn (mut c Checker) check_expected_arg_count(mut node ast.CallExpr, f &ast.Fn) !
|
||||
}
|
||||
if f.is_variadic {
|
||||
min_required_params--
|
||||
if c.pref.skip_unused && !c.is_builtin_mod {
|
||||
c.table.used_features.arr_init = true
|
||||
}
|
||||
} else {
|
||||
has_decompose := node.args.any(it.expr is ast.ArrayDecompose)
|
||||
if has_decompose {
|
||||
@ -3565,7 +3581,7 @@ fn (mut c Checker) array_builtin_method_call(mut node ast.CallExpr, left_type as
|
||||
}
|
||||
node.return_type = ast.int_type
|
||||
} else if method_name in ['first', 'last', 'pop'] {
|
||||
if c.pref.skip_unused {
|
||||
if c.pref.skip_unused && !c.is_builtin_mod {
|
||||
if method_name == 'first' {
|
||||
c.table.used_features.arr_first = true
|
||||
}
|
||||
@ -3587,6 +3603,9 @@ fn (mut c Checker) array_builtin_method_call(mut node ast.CallExpr, left_type as
|
||||
node.receiver_type = node.left_type
|
||||
}
|
||||
} else if method_name == 'delete' {
|
||||
if c.pref.skip_unused && !c.is_builtin_mod {
|
||||
c.table.used_features.arr_delete = true
|
||||
}
|
||||
c.check_for_mut_receiver(mut node.left)
|
||||
unwrapped_left_sym := c.table.sym(unwrapped_left_type)
|
||||
if method := c.table.find_method(unwrapped_left_sym, method_name) {
|
||||
|
@ -190,6 +190,9 @@ fn (mut c Checker) for_in_stmt(mut node ast.ForInStmt) {
|
||||
'declare a key and a value variable when ranging a map: `for key, val in map {`\n' +
|
||||
'use `_` if you do not need the variable', node.pos)
|
||||
}
|
||||
if !c.is_builtin_mod && c.mod != 'strings' {
|
||||
c.table.used_features.used_maps++
|
||||
}
|
||||
if node.key_var.len > 0 {
|
||||
key_type := match sym.kind {
|
||||
.map { sym.map_info().key_type }
|
||||
|
@ -62,6 +62,7 @@ fn (mut c Checker) string_inter_lit(mut node ast.StringInterLiteral) ast.Type {
|
||||
} else {
|
||||
c.table.used_features.print_types[ftyp.idx()] = true
|
||||
}
|
||||
c.table.used_features.interpolation = true
|
||||
}
|
||||
c.fail_if_unreadable(expr, ftyp, 'interpolation object')
|
||||
node.expr_types << ftyp
|
||||
|
@ -6660,7 +6660,7 @@ fn (mut g Gen) write_init_function() {
|
||||
g.write('\tas_cast_type_indexes = ')
|
||||
g.writeln(g.as_cast_name_table())
|
||||
}
|
||||
if !g.pref.is_shared && (!g.pref.skip_unused || g.table.used_features.builtin_types) {
|
||||
if !g.pref.is_shared && (!g.pref.skip_unused || g.table.used_features.used_modules.len > 0) {
|
||||
// shared object does not need this
|
||||
g.writeln('\tbuiltin_init();')
|
||||
}
|
||||
|
@ -13,7 +13,6 @@ pub fn mark_used(mut table ast.Table, mut pref_ pref.Preferences, ast_files []&a
|
||||
defer {
|
||||
util.timing_measure(@METHOD)
|
||||
}
|
||||
mut allow_noscan := true
|
||||
// Functions that must be generated and can't be skipped
|
||||
mut all_fn_root_names := []string{}
|
||||
if pref_.backend == .native {
|
||||
@ -25,17 +24,19 @@ pub fn mark_used(mut table ast.Table, mut pref_ pref.Preferences, ast_files []&a
|
||||
string_idx_str := '${ast.string_type_idx}'
|
||||
array_idx_str := '${ast.array_type_idx}'
|
||||
map_idx_str := '${ast.map_type_idx}'
|
||||
ref_map_idx_str := '${int(ast.map_type.ref())}'
|
||||
ref_densearray_idx_str := '${int(table.find_type('DenseArray').ref())}'
|
||||
ref_array_idx_str := '${int(ast.array_type.ref())}'
|
||||
mut core_fns := [
|
||||
'main.main',
|
||||
'init_global_allocator', // needed for linux_bare and wasm_bare
|
||||
'v_realloc', // needed for _STR
|
||||
'malloc',
|
||||
'malloc_noscan',
|
||||
'vcalloc',
|
||||
'vcalloc_noscan',
|
||||
//'malloc',
|
||||
//'malloc_noscan',
|
||||
//'vcalloc',
|
||||
//'vcalloc_noscan',
|
||||
'memdup',
|
||||
'vstrlen',
|
||||
//'vstrlen',
|
||||
'tos',
|
||||
'tos2',
|
||||
'error',
|
||||
@ -45,26 +46,35 @@ pub fn mark_used(mut table ast.Table, mut pref_ pref.Preferences, ast_files []&a
|
||||
'main.vtest_init',
|
||||
'main.vtest_new_metainfo',
|
||||
'main.vtest_new_filemetainfo',
|
||||
'println',
|
||||
]
|
||||
$if debug_used_features ? {
|
||||
dump(table.used_features)
|
||||
}
|
||||
panic_deps := [
|
||||
'__new_array_with_default',
|
||||
'__new_array_with_default_noscan',
|
||||
'str_intp',
|
||||
ref_array_idx_str + '.push',
|
||||
ref_array_idx_str + '.push_noscan',
|
||||
string_idx_str + '.substr',
|
||||
array_idx_str + '.slice',
|
||||
array_idx_str + '.get',
|
||||
'v_fixed_index',
|
||||
charptr_idx_str + '.vstring_literal',
|
||||
]
|
||||
// real world apps
|
||||
if table.used_features.builtin_types || table.used_features.as_cast
|
||||
|| table.used_features.auto_str {
|
||||
if table.used_features.used_modules.len > 0 {
|
||||
core_fns << panic_deps
|
||||
}
|
||||
if table.used_features.as_cast || table.used_features.auto_str || pref_.is_shared {
|
||||
core_fns << panic_deps
|
||||
core_fns << 'isnil'
|
||||
core_fns << '__new_array'
|
||||
core_fns << '__new_array_noscan'
|
||||
core_fns << '__new_array_with_multi_default'
|
||||
core_fns << '__new_array_with_multi_default_noscan'
|
||||
core_fns << '__new_array_with_array_default'
|
||||
core_fns << '__new_array_with_array_default_noscan'
|
||||
core_fns << 'new_array_from_c_array'
|
||||
// byteptr and charptr
|
||||
core_fns << byteptr_idx_str + '.vstring'
|
||||
@ -73,65 +83,82 @@ pub fn mark_used(mut table ast.Table, mut pref_ pref.Preferences, ast_files []&a
|
||||
core_fns << charptr_idx_str + '.vstring'
|
||||
core_fns << charptr_idx_str + '.vstring_with_len'
|
||||
core_fns << charptr_idx_str + '.vstring_literal'
|
||||
|
||||
if table.used_features.index {
|
||||
core_fns << string_idx_str + '.at_with_check'
|
||||
core_fns << string_idx_str + '.clone'
|
||||
core_fns << string_idx_str + '.clone_static'
|
||||
core_fns << string_idx_str + '.at'
|
||||
core_fns << array_idx_str + '.set'
|
||||
core_fns << ref_array_idx_str + '.set'
|
||||
core_fns << map_idx_str + '.get'
|
||||
core_fns << map_idx_str + '.set'
|
||||
}
|
||||
if table.used_features.range_index {
|
||||
core_fns << string_idx_str + '.substr_with_check'
|
||||
core_fns << string_idx_str + '.substr_ni'
|
||||
core_fns << array_idx_str + '.slice_ni'
|
||||
core_fns << array_idx_str + '.get_with_check' // used for `x := a[i] or {}`
|
||||
core_fns << array_idx_str + '.clone_static_to_depth'
|
||||
core_fns << array_idx_str + '.clone_to_depth'
|
||||
}
|
||||
if table.used_features.cast_ptr {
|
||||
core_fns << 'ptr_str' // TODO: remove this. It is currently needed for the auto str methods for &u8, fn types, etc; See `./v -skip-unused vlib/builtin/int_test.v`
|
||||
}
|
||||
if table.used_features.auto_str {
|
||||
core_fns << string_idx_str + '.repeat'
|
||||
core_fns << 'tos3'
|
||||
}
|
||||
if table.used_features.auto_str_ptr {
|
||||
core_fns << 'isnil'
|
||||
}
|
||||
if table.used_features.arr_prepend {
|
||||
core_fns << ref_array_idx_str + '.prepend_many'
|
||||
}
|
||||
if table.used_features.arr_pop {
|
||||
core_fns << ref_array_idx_str + '.pop'
|
||||
}
|
||||
if table.used_features.arr_first {
|
||||
core_fns << array_idx_str + '.first'
|
||||
}
|
||||
if table.used_features.arr_last {
|
||||
core_fns << array_idx_str + '.last'
|
||||
}
|
||||
} else {
|
||||
// TODO: this *should not* depend on the used compiler, which is brittle, but only on info in the AST...
|
||||
// hello world apps
|
||||
if pref_.ccompiler_type != .tinyc && 'no_backtrace' !in pref_.compile_defines {
|
||||
// with backtrace on gcc/clang more code needs be generated
|
||||
allow_noscan = true
|
||||
core_fns << panic_deps
|
||||
} else {
|
||||
allow_noscan = false
|
||||
}
|
||||
}
|
||||
if table.used_features.index || pref_.is_shared {
|
||||
core_fns << string_idx_str + '.at_with_check'
|
||||
core_fns << string_idx_str + '.clone'
|
||||
core_fns << string_idx_str + '.clone_static'
|
||||
core_fns << string_idx_str + '.at'
|
||||
core_fns << array_idx_str + '.set'
|
||||
core_fns << ref_array_idx_str + '.set'
|
||||
core_fns << map_idx_str + '.get'
|
||||
core_fns << map_idx_str + '.set'
|
||||
core_fns << '__new_array_noscan'
|
||||
core_fns << ref_array_idx_str + '.push_noscan'
|
||||
core_fns << ref_array_idx_str + '.push_many_noscan'
|
||||
}
|
||||
if table.used_features.range_index || pref_.is_shared {
|
||||
core_fns << string_idx_str + '.substr_with_check'
|
||||
core_fns << string_idx_str + '.substr_ni'
|
||||
core_fns << array_idx_str + '.slice_ni'
|
||||
core_fns << array_idx_str + '.get_with_check' // used for `x := a[i] or {}`
|
||||
core_fns << array_idx_str + '.clone_static_to_depth'
|
||||
core_fns << array_idx_str + '.clone_to_depth'
|
||||
}
|
||||
if table.used_features.cast_ptr {
|
||||
core_fns << 'ptr_str' // TODO: remove this. It is currently needed for the auto str methods for &u8, fn types, etc; See `./v -skip-unused vlib/builtin/int_test.v`
|
||||
}
|
||||
if table.used_features.auto_str {
|
||||
core_fns << string_idx_str + '.repeat'
|
||||
core_fns << 'tos3'
|
||||
}
|
||||
if table.used_features.auto_str_ptr {
|
||||
core_fns << 'isnil'
|
||||
}
|
||||
if table.used_features.arr_prepend {
|
||||
core_fns << ref_array_idx_str + '.prepend_many'
|
||||
}
|
||||
if table.used_features.arr_pop {
|
||||
core_fns << ref_array_idx_str + '.pop'
|
||||
}
|
||||
if table.used_features.arr_first {
|
||||
core_fns << array_idx_str + '.first'
|
||||
}
|
||||
if table.used_features.arr_last {
|
||||
core_fns << array_idx_str + '.last'
|
||||
}
|
||||
if table.used_features.arr_delete {
|
||||
core_fns << panic_deps
|
||||
}
|
||||
if pref_.ccompiler_type != .tinyc && 'no_backtrace' !in pref_.compile_defines {
|
||||
// with backtrace on gcc/clang more code needs be generated
|
||||
core_fns << panic_deps
|
||||
}
|
||||
if table.used_features.interpolation {
|
||||
core_fns << panic_deps
|
||||
}
|
||||
if table.used_features.dump {
|
||||
core_fns << panic_deps
|
||||
builderptr_idx := int(table.find_type('strings.Builder').ref())
|
||||
core_fns << [
|
||||
'${builderptr_idx}.str',
|
||||
'${builderptr_idx}.free',
|
||||
'${builderptr_idx}.write_rune',
|
||||
]
|
||||
}
|
||||
if table.used_features.arr_init {
|
||||
core_fns << '__new_array'
|
||||
core_fns << 'new_array_from_c_array'
|
||||
core_fns << 'new_array_from_c_array_noscan'
|
||||
core_fns << '__new_array_with_multi_default'
|
||||
core_fns << '__new_array_with_multi_default_noscan'
|
||||
core_fns << '__new_array_with_array_default'
|
||||
}
|
||||
if table.used_features.option_or_result {
|
||||
core_fns << '_option_ok'
|
||||
core_fns << '_result_ok'
|
||||
if !allow_noscan {
|
||||
core_fns << panic_deps
|
||||
allow_noscan = true
|
||||
}
|
||||
core_fns << charptr_idx_str + '.vstring_literal'
|
||||
core_fns << panic_deps
|
||||
}
|
||||
if table.used_features.as_cast {
|
||||
core_fns << '__as_cast'
|
||||
@ -139,9 +166,33 @@ pub fn mark_used(mut table ast.Table, mut pref_ pref.Preferences, ast_files []&a
|
||||
if table.used_features.anon_fn {
|
||||
core_fns << 'memdup_uncollectable'
|
||||
}
|
||||
if table.used_features.arr_map {
|
||||
core_fns << '__new_array_with_map_default'
|
||||
core_fns << 'new_map_noscan_key'
|
||||
core_fns << ref_map_idx_str + '.clone'
|
||||
core_fns << ref_densearray_idx_str + '.clone'
|
||||
core_fns << map_idx_str + '.clone'
|
||||
table.used_features.used_maps++
|
||||
}
|
||||
if table.used_features.map_update {
|
||||
core_fns << 'new_map_update_init'
|
||||
table.used_features.used_maps++
|
||||
}
|
||||
if table.used_features.asserts {
|
||||
core_fns << panic_deps
|
||||
core_fns << '__print_assert_failure'
|
||||
core_fns << 'isnil'
|
||||
}
|
||||
if pref_.trace_calls || pref_.trace_fns.len > 0 {
|
||||
core_fns << panic_deps
|
||||
core_fns << 'vgettid'
|
||||
core_fns << 'C.gettid'
|
||||
core_fns << 'v.trace_calls.on_c_main'
|
||||
core_fns << 'v.trace_calls.current_time'
|
||||
core_fns << 'v.trace_calls.on_call'
|
||||
}
|
||||
all_fn_root_names << core_fns
|
||||
}
|
||||
|
||||
if pref_.is_bare {
|
||||
all_fn_root_names << [
|
||||
'strlen',
|
||||
@ -154,16 +205,18 @@ pub fn mark_used(mut table ast.Table, mut pref_ pref.Preferences, ast_files []&a
|
||||
}
|
||||
|
||||
is_noscan_whitelisted := pref_.gc_mode in [.boehm_full_opt, .boehm_incr_opt]
|
||||
|
||||
has_noscan := all_fn_root_names.any(it.contains('noscan')
|
||||
&& it !in ['vcalloc_noscan', 'malloc_noscan'])
|
||||
for k, mut mfn in all_fns {
|
||||
$if trace_skip_unused_all_fns ? {
|
||||
println('k: ${k} | mfn: ${mfn.name}')
|
||||
}
|
||||
if k in table.used_features.comptime_calls {
|
||||
all_fn_root_names << k
|
||||
continue
|
||||
}
|
||||
// _noscan functions/methods are selected when the `-gc boehm` is on:
|
||||
if allow_noscan && is_noscan_whitelisted && mfn.name.ends_with('_noscan') {
|
||||
if has_noscan && is_noscan_whitelisted && mfn.name.ends_with('_noscan') {
|
||||
all_fn_root_names << k
|
||||
continue
|
||||
}
|
||||
@ -176,8 +229,7 @@ pub fn mark_used(mut table ast.Table, mut pref_ pref.Preferences, ast_files []&a
|
||||
all_fn_root_names << k
|
||||
continue
|
||||
}
|
||||
if method_receiver_typename == '&strings.Builder'
|
||||
&& (table.used_features.builtin_types || table.used_features.auto_str) {
|
||||
if method_receiver_typename == '&strings.Builder' && table.used_features.auto_str {
|
||||
// implicit string builders are generated in auto_eq_methods.v
|
||||
all_fn_root_names << k
|
||||
continue
|
||||
@ -187,7 +239,7 @@ pub fn mark_used(mut table ast.Table, mut pref_ pref.Preferences, ast_files []&a
|
||||
if k.ends_with('.str') || k.ends_with('.auto_str') {
|
||||
if table.used_features.auto_str
|
||||
|| table.used_features.print_types[mfn.receiver.typ.idx()]
|
||||
|| table.used_features.debugger {
|
||||
|| table.used_features.debugger || table.used_features.used_modules.len > 0 {
|
||||
all_fn_root_names << k
|
||||
}
|
||||
continue
|
||||
@ -196,7 +248,7 @@ pub fn mark_used(mut table ast.Table, mut pref_ pref.Preferences, ast_files []&a
|
||||
all_fn_root_names << k
|
||||
continue
|
||||
}
|
||||
if table.used_features.builtin_types && k.ends_with('.free') {
|
||||
if table.used_features.used_modules.len > 0 && k.ends_with('.free') {
|
||||
all_fn_root_names << k
|
||||
continue
|
||||
}
|
||||
@ -356,19 +408,13 @@ pub fn mark_used(mut table ast.Table, mut pref_ pref.Preferences, ast_files []&a
|
||||
all_globals: all_globals
|
||||
pref: pref_
|
||||
)
|
||||
// println( all_fns.keys() )
|
||||
|
||||
walker.mark_markused_fn_decls() // tagged with `@[markused]`
|
||||
|
||||
walker.mark_markused_consts() // tagged with `@[markused]`
|
||||
walker.mark_markused_globals() // tagged with `@[markused]`
|
||||
walker.mark_exported_fns()
|
||||
walker.mark_root_fns(all_fn_root_names)
|
||||
walker.mark_veb_actions()
|
||||
|
||||
if walker.n_asserts > 0 {
|
||||
unsafe { walker.fn_decl(mut all_fns['__print_assert_failure']) }
|
||||
}
|
||||
if table.used_features.used_maps > 0 {
|
||||
for k, mut mfn in all_fns {
|
||||
mut method_receiver_typename := ''
|
||||
@ -465,6 +511,13 @@ fn all_fn_const_and_global(ast_files []&ast.File) (map[string]ast.FnDecl, map[st
|
||||
return all_fns, all_consts, all_globals
|
||||
}
|
||||
|
||||
fn mark_all_methods_used(mut table ast.Table, mut all_fn_root_names []string, typ ast.Type) {
|
||||
sym := table.sym(typ)
|
||||
for method in sym.methods {
|
||||
all_fn_root_names << '${int(typ)}.${method.name}'
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_vweb(mut table ast.Table, mut all_fn_root_names []string, result_name string, filter_name string,
|
||||
context_name string) {
|
||||
// handle vweb magic router methods:
|
||||
@ -472,7 +525,7 @@ fn handle_vweb(mut table ast.Table, mut all_fn_root_names []string, result_name
|
||||
if result_type_idx != 0 {
|
||||
all_fn_root_names << filter_name
|
||||
typ_vweb_context := table.find_type(context_name).set_nr_muls(1)
|
||||
all_fn_root_names << '${int(typ_vweb_context)}.html'
|
||||
mark_all_methods_used(mut table, mut all_fn_root_names, typ_vweb_context)
|
||||
for vgt in table.used_features.used_veb_types {
|
||||
sym_app := table.sym(vgt)
|
||||
for m in sym_app.methods {
|
||||
|
@ -299,6 +299,10 @@ fn (mut w Walker) expr(node_ ast.Expr) {
|
||||
w.fn_decl(mut node.decl)
|
||||
}
|
||||
ast.ArrayInit {
|
||||
sym := w.table.final_sym(node.elem_type)
|
||||
if sym.info is ast.Struct {
|
||||
w.a_struct_info(sym.name, sym.info)
|
||||
}
|
||||
w.expr(node.len_expr)
|
||||
w.expr(node.cap_expr)
|
||||
w.expr(node.init_expr)
|
||||
@ -419,6 +423,7 @@ fn (mut w Walker) expr(node_ ast.Expr) {
|
||||
// println('>>> else, ast.Ident kind: $node.kind')
|
||||
}
|
||||
}
|
||||
w.or_block(node.or_expr)
|
||||
}
|
||||
ast.LambdaExpr {
|
||||
w.expr(node.func)
|
||||
@ -470,6 +475,7 @@ fn (mut w Walker) expr(node_ ast.Expr) {
|
||||
w.fn_by_name(method.fkey())
|
||||
}
|
||||
}
|
||||
w.or_block(node.or_block)
|
||||
}
|
||||
ast.SqlExpr {
|
||||
w.expr(node.db_expr)
|
||||
@ -511,7 +517,14 @@ fn (mut w Walker) expr(node_ ast.Expr) {
|
||||
w.expr(node.orig)
|
||||
}
|
||||
ast.Comment {}
|
||||
ast.EnumVal {}
|
||||
ast.EnumVal {
|
||||
if e := w.table.enum_decls[node.enum_name] {
|
||||
filtered := e.fields.filter(it.name == node.val)
|
||||
if filtered.len != 0 && filtered[0].expr !is ast.EmptyExpr {
|
||||
w.expr(filtered[0].expr)
|
||||
}
|
||||
}
|
||||
}
|
||||
ast.LockExpr {
|
||||
w.stmts(node.stmts)
|
||||
}
|
||||
@ -557,6 +570,7 @@ pub fn (mut w Walker) a_struct_info(sname string, info ast.Struct) {
|
||||
|
||||
pub fn (mut w Walker) fn_decl(mut node ast.FnDecl) {
|
||||
if node.language == .c {
|
||||
w.mark_fn_as_used(node.fkey())
|
||||
return
|
||||
}
|
||||
fkey := node.fkey()
|
||||
@ -587,6 +601,17 @@ pub fn (mut w Walker) call_expr(mut node ast.CallExpr) {
|
||||
w.mark_aggregate_call_used(fn_name, types)
|
||||
}
|
||||
}
|
||||
} else if left_sym.info is ast.Interface {
|
||||
for typ in left_sym.info.types {
|
||||
sym := w.table.sym(typ)
|
||||
_, embed_types := w.table.find_method_from_embeds(sym, node.name) or {
|
||||
ast.Fn{}, []ast.Type{}
|
||||
}
|
||||
if embed_types.len != 0 {
|
||||
fn_embed := '${int(embed_types.last())}.${node.name}'
|
||||
w.fn_by_name(fn_embed)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
w.expr(node.left)
|
||||
@ -609,15 +634,19 @@ pub fn (mut w Walker) call_expr(mut node ast.CallExpr) {
|
||||
else {}
|
||||
}
|
||||
}
|
||||
} else if node.is_fn_a_const {
|
||||
const_fn_name := '${node.mod}.${fn_name}'
|
||||
if const_fn_name in w.all_consts {
|
||||
w.mark_const_as_used(const_fn_name)
|
||||
}
|
||||
}
|
||||
|
||||
w.mark_fn_as_used(fn_name)
|
||||
if node.is_method && node.receiver_type.has_flag(.generic) && node.receiver_concrete_type != 0
|
||||
&& !node.receiver_concrete_type.has_flag(.generic) {
|
||||
// if receiver is generic, then cgen requires `node.receiver_type` to be T.
|
||||
// We therefore need to get the concrete type from `node.receiver_concrete_type`.
|
||||
fkey := '${int(node.receiver_concrete_type)}.${node.name}'
|
||||
w.used_fns[fkey] = true
|
||||
w.mark_fn_as_used(fkey)
|
||||
}
|
||||
stmt := w.all_fns[fn_name] or { return }
|
||||
if stmt.name == node.name {
|
||||
|
Loading…
x
Reference in New Issue
Block a user