mirror of
https://github.com/vlang/v.git
synced 2025-09-13 22:42:26 +03:00
markused: reduce hello world csize by 49%, do more cleanups and improvements (#24971)
This commit is contained in:
parent
59d408f72c
commit
396dc77a20
16 changed files with 424 additions and 303 deletions
|
@ -1468,6 +1468,7 @@ fn (t Tree) index_expr(node ast.IndexExpr) &Node {
|
||||||
obj.add_terse('is_setter', t.bool_node(node.is_setter))
|
obj.add_terse('is_setter', t.bool_node(node.is_setter))
|
||||||
obj.add_terse('is_direct', t.bool_node(node.is_direct))
|
obj.add_terse('is_direct', t.bool_node(node.is_direct))
|
||||||
obj.add_terse('or_expr', t.or_expr(node.or_expr))
|
obj.add_terse('or_expr', t.or_expr(node.or_expr))
|
||||||
|
obj.add_terse('typ', t.type_node(node.typ))
|
||||||
obj.add('pos', t.pos(node.pos))
|
obj.add('pos', t.pos(node.pos))
|
||||||
return obj
|
return obj
|
||||||
}
|
}
|
||||||
|
|
|
@ -134,7 +134,7 @@ pub fn tos2(s &u8) string {
|
||||||
// It will panic, when the pointer `s` is 0.
|
// It will panic, when the pointer `s` is 0.
|
||||||
// It is the same as `tos2`, but for &char pointers, avoiding callsite casts.
|
// It is the same as `tos2`, but for &char pointers, avoiding callsite casts.
|
||||||
// See also `tos_clone`.
|
// See also `tos_clone`.
|
||||||
@[markused; unsafe]
|
@[unsafe]
|
||||||
pub fn tos3(s &char) string {
|
pub fn tos3(s &char) string {
|
||||||
if s == 0 {
|
if s == 0 {
|
||||||
panic('tos3: nil string')
|
panic('tos3: nil string')
|
||||||
|
@ -151,7 +151,7 @@ pub fn tos3(s &char) string {
|
||||||
// It returns '', when given a 0 pointer `s`, it does NOT panic.
|
// It returns '', when given a 0 pointer `s`, it does NOT panic.
|
||||||
// It is the same as `tos5`, but for &u8 pointers, avoiding callsite casts.
|
// It is the same as `tos5`, but for &u8 pointers, avoiding callsite casts.
|
||||||
// See also `tos_clone`.
|
// See also `tos_clone`.
|
||||||
@[markused; unsafe]
|
@[unsafe]
|
||||||
pub fn tos4(s &u8) string {
|
pub fn tos4(s &u8) string {
|
||||||
if s == 0 {
|
if s == 0 {
|
||||||
return ''
|
return ''
|
||||||
|
@ -168,7 +168,7 @@ pub fn tos4(s &u8) string {
|
||||||
// It returns '', when given a 0 pointer `s`, it does NOT panic.
|
// It returns '', when given a 0 pointer `s`, it does NOT panic.
|
||||||
// It is the same as `tos4`, but for &char pointers, avoiding callsite casts.
|
// It is the same as `tos4`, but for &char pointers, avoiding callsite casts.
|
||||||
// See also `tos_clone`.
|
// See also `tos_clone`.
|
||||||
@[markused; unsafe]
|
@[unsafe]
|
||||||
pub fn tos5(s &char) string {
|
pub fn tos5(s &char) string {
|
||||||
if s == 0 {
|
if s == 0 {
|
||||||
return ''
|
return ''
|
||||||
|
|
|
@ -1207,6 +1207,7 @@ pub mut:
|
||||||
is_option bool // IfGuard
|
is_option bool // IfGuard
|
||||||
is_direct bool // Set if the underlying memory can be safely accessed
|
is_direct bool // Set if the underlying memory can be safely accessed
|
||||||
is_gated bool // #[] gated array
|
is_gated bool // #[] gated array
|
||||||
|
typ Type
|
||||||
}
|
}
|
||||||
|
|
||||||
@[minify]
|
@[minify]
|
||||||
|
|
|
@ -14,7 +14,6 @@ pub mut:
|
||||||
index bool // string[0]
|
index bool // string[0]
|
||||||
range_index bool // string[0..1]
|
range_index bool // string[0..1]
|
||||||
cast_ptr bool // &u8(...)
|
cast_ptr bool // &u8(...)
|
||||||
asserts bool // assert expr
|
|
||||||
anon_fn bool // fn () { }
|
anon_fn bool // fn () { }
|
||||||
auto_str bool // auto str fns
|
auto_str bool // auto str fns
|
||||||
auto_str_ptr bool // auto str fns for ptr type
|
auto_str_ptr bool // auto str fns for ptr type
|
||||||
|
@ -25,10 +24,8 @@ pub mut:
|
||||||
arr_pop bool // arr.pop()
|
arr_pop bool // arr.pop()
|
||||||
arr_delete bool // arr.delete()
|
arr_delete bool // arr.delete()
|
||||||
arr_reverse bool // arr.reverse()
|
arr_reverse bool // arr.reverse()
|
||||||
arr_init bool // [1, 2, 3]
|
|
||||||
arr_map bool // []map[key]value
|
arr_map bool // []map[key]value
|
||||||
type_name bool // var.type_name()
|
type_name bool // var.type_name()
|
||||||
map_update bool // {...foo}
|
|
||||||
print_options bool // print option type
|
print_options bool // print option type
|
||||||
print_types map[int]bool // print() idx types
|
print_types map[int]bool // print() idx types
|
||||||
used_fns map[string]bool // filled in by markused
|
used_fns map[string]bool // filled in by markused
|
||||||
|
@ -39,11 +36,8 @@ pub mut:
|
||||||
used_maps int // how many times maps were used, filled in by markused
|
used_maps int // how many times maps were used, filled in by markused
|
||||||
used_none int // how many times `none` was used, filled in by markused
|
used_none int // how many times `none` was used, filled in by markused
|
||||||
// json bool // json is imported
|
// json bool // json is imported
|
||||||
debugger bool // debugger is used
|
|
||||||
comptime_calls map[string]bool // resolved name to call on comptime
|
comptime_calls map[string]bool // resolved name to call on comptime
|
||||||
comptime_syms map[int]bool // resolved syms (generic)
|
comptime_syms map[Type]bool // resolved syms (generic)
|
||||||
comptime_for bool // uses $for
|
|
||||||
memory_align bool // @[aligned] for struct
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@[unsafe]
|
@[unsafe]
|
||||||
|
|
|
@ -2385,9 +2385,7 @@ fn (mut c Checker) stmt(mut node ast.Stmt) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast.NodeError {}
|
ast.NodeError {}
|
||||||
ast.DebuggerStmt {
|
ast.DebuggerStmt {}
|
||||||
c.table.used_features.debugger = true
|
|
||||||
}
|
|
||||||
ast.AsmStmt {
|
ast.AsmStmt {
|
||||||
c.asm_stmt(mut node)
|
c.asm_stmt(mut node)
|
||||||
}
|
}
|
||||||
|
@ -2398,9 +2396,6 @@ fn (mut c Checker) stmt(mut node ast.Stmt) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut c Checker) assert_stmt(mut node ast.AssertStmt) {
|
fn (mut c Checker) assert_stmt(mut node ast.AssertStmt) {
|
||||||
if node.is_used {
|
|
||||||
c.table.used_features.asserts = true
|
|
||||||
}
|
|
||||||
cur_exp_typ := c.expected_type
|
cur_exp_typ := c.expected_type
|
||||||
c.expected_type = ast.bool_type
|
c.expected_type = ast.bool_type
|
||||||
assert_type := c.check_expr_option_or_result_call(node.expr, c.expr(mut node.expr))
|
assert_type := c.check_expr_option_or_result_call(node.expr, c.expr(mut node.expr))
|
||||||
|
@ -5140,6 +5135,7 @@ fn (mut c Checker) index_expr(mut node ast.IndexExpr) ast.Type {
|
||||||
}
|
}
|
||||||
c.stmts_ending_with_expression(mut node.or_expr.stmts, c.expected_or_type)
|
c.stmts_ending_with_expression(mut node.or_expr.stmts, c.expected_or_type)
|
||||||
c.check_expr_option_or_result_call(node, typ)
|
c.check_expr_option_or_result_call(node, typ)
|
||||||
|
node.typ = typ
|
||||||
return typ
|
return typ
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -277,7 +277,6 @@ fn (mut c Checker) comptime_for(mut node ast.ComptimeFor) {
|
||||||
prev_inside_x_matches_type := c.inside_x_matches_type
|
prev_inside_x_matches_type := c.inside_x_matches_type
|
||||||
c.push_new_comptime_info()
|
c.push_new_comptime_info()
|
||||||
c.comptime.inside_comptime_for = true
|
c.comptime.inside_comptime_for = true
|
||||||
c.table.used_features.comptime_for = true
|
|
||||||
if c.field_data_type == 0 {
|
if c.field_data_type == 0 {
|
||||||
c.field_data_type = c.table.find_type('FieldData')
|
c.field_data_type = c.table.find_type('FieldData')
|
||||||
}
|
}
|
||||||
|
@ -322,7 +321,6 @@ fn (mut c Checker) comptime_for(mut node ast.ComptimeFor) {
|
||||||
c.type_resolver.update_ct_type('${node.val_var}.typ', node.typ)
|
c.type_resolver.update_ct_type('${node.val_var}.typ', node.typ)
|
||||||
c.stmts(mut node.stmts)
|
c.stmts(mut node.stmts)
|
||||||
c.pop_comptime_info()
|
c.pop_comptime_info()
|
||||||
c.table.used_features.comptime_for = true
|
|
||||||
} else {
|
} else {
|
||||||
c.error('iterating over .values is supported only for enums, and ${sym.name} is not an enum',
|
c.error('iterating over .values is supported only for enums, and ${sym.name} is not an enum',
|
||||||
node.typ_pos)
|
node.typ_pos)
|
||||||
|
@ -340,7 +338,6 @@ fn (mut c Checker) comptime_for(mut node ast.ComptimeFor) {
|
||||||
c.stmts(mut node.stmts)
|
c.stmts(mut node.stmts)
|
||||||
c.pop_comptime_info()
|
c.pop_comptime_info()
|
||||||
}
|
}
|
||||||
c.table.used_features.comptime_for = true
|
|
||||||
} else if node.kind == .params {
|
} else if node.kind == .params {
|
||||||
if !(sym.kind == .function || sym.name == 'FunctionData') {
|
if !(sym.kind == .function || sym.name == 'FunctionData') {
|
||||||
c.error('iterating over `.params` is supported only for functions, and `${sym.name}` is not a function',
|
c.error('iterating over `.params` is supported only for functions, and `${sym.name}` is not a function',
|
||||||
|
|
|
@ -8,14 +8,14 @@ import v.token
|
||||||
fn (mut c Checker) array_init(mut node ast.ArrayInit) ast.Type {
|
fn (mut c Checker) array_init(mut node ast.ArrayInit) ast.Type {
|
||||||
mut elem_type := ast.void_type
|
mut elem_type := ast.void_type
|
||||||
unwrap_elem_type := c.unwrap_generic(node.elem_type)
|
unwrap_elem_type := c.unwrap_generic(node.elem_type)
|
||||||
|
if node.typ.has_flag(.generic) {
|
||||||
|
c.table.used_features.comptime_syms[c.unwrap_generic(node.typ)] = true
|
||||||
|
}
|
||||||
if c.pref.warn_about_allocs {
|
if c.pref.warn_about_allocs {
|
||||||
c.warn_alloc('array initialization', node.pos)
|
c.warn_alloc('array initialization', node.pos)
|
||||||
}
|
}
|
||||||
// `x := []string{}` (the type was set in the parser)
|
// `x := []string{}` (the type was set in the parser)
|
||||||
if node.typ != ast.void_type {
|
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 {
|
if node.elem_type != 0 {
|
||||||
elem_sym := c.table.sym(node.elem_type)
|
elem_sym := c.table.sym(node.elem_type)
|
||||||
c.check_any_type(node.elem_type, elem_sym, node.pos)
|
c.check_any_type(node.elem_type, elem_sym, node.pos)
|
||||||
|
@ -159,9 +159,6 @@ fn (mut c Checker) array_init(mut node ast.ArrayInit) ast.Type {
|
||||||
}
|
}
|
||||||
// `[1,2,3]`
|
// `[1,2,3]`
|
||||||
if node.exprs.len > 0 && node.elem_type == ast.void_type {
|
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 expected_value_type := ast.void_type
|
||||||
mut expecting_interface_array := false
|
mut expecting_interface_array := false
|
||||||
mut expecting_sumtype_array := false
|
mut expecting_sumtype_array := false
|
||||||
|
@ -502,6 +499,9 @@ fn (mut c Checker) map_init(mut node ast.MapInit) ast.Type {
|
||||||
// `x := map[string]string` - set in parser
|
// `x := map[string]string` - set in parser
|
||||||
if node.typ != 0 {
|
if node.typ != 0 {
|
||||||
info := c.table.sym(node.typ).map_info()
|
info := c.table.sym(node.typ).map_info()
|
||||||
|
if node.typ.has_flag(.generic) {
|
||||||
|
c.table.used_features.comptime_syms[c.unwrap_generic(node.typ)] = true
|
||||||
|
}
|
||||||
if info.value_type != 0 {
|
if info.value_type != 0 {
|
||||||
if info.value_type.has_flag(.result) {
|
if info.value_type.has_flag(.result) {
|
||||||
c.error('cannot use Result type as map value type', node.pos)
|
c.error('cannot use Result type as map value type', node.pos)
|
||||||
|
@ -541,7 +541,6 @@ 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 {
|
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
|
mut map_type := ast.void_type
|
||||||
use_expected_type := c.expected_type != ast.void_type && !c.inside_const
|
use_expected_type := c.expected_type != ast.void_type && !c.inside_const
|
||||||
&& c.table.sym(c.expected_type).kind == .map && !(c.inside_fn_arg
|
&& c.table.sym(c.expected_type).kind == .map && !(c.inside_fn_arg
|
||||||
|
|
|
@ -342,9 +342,15 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
|
||||||
if c.pref.skip_unused {
|
if c.pref.skip_unused {
|
||||||
if param.typ.has_flag(.generic) {
|
if param.typ.has_flag(.generic) {
|
||||||
c.table.used_features.comptime_syms[c.unwrap_generic(param.typ)] = true
|
c.table.used_features.comptime_syms[c.unwrap_generic(param.typ)] = true
|
||||||
|
c.table.used_features.comptime_syms[param.typ] = true
|
||||||
}
|
}
|
||||||
if node.return_type.has_flag(.generic) {
|
if node.return_type.has_flag(.generic) {
|
||||||
c.table.used_features.comptime_syms[c.unwrap_generic(node.return_type)] = true
|
c.table.used_features.comptime_syms[c.unwrap_generic(node.return_type)] = true
|
||||||
|
c.table.used_features.comptime_syms[node.return_type] = true
|
||||||
|
}
|
||||||
|
if node.receiver.typ.has_flag(.generic) {
|
||||||
|
c.table.used_features.comptime_syms[node.receiver.typ] = true
|
||||||
|
c.table.used_features.comptime_syms[c.unwrap_generic(node.receiver.typ)] = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if param.name == node.mod && param.name != 'main' {
|
if param.name == node.mod && param.name != 'main' {
|
||||||
|
@ -1895,6 +1901,7 @@ fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool) ast.
|
||||||
c.register_trace_call(node, func)
|
c.register_trace_call(node, func)
|
||||||
if func.return_type.has_flag(.generic) {
|
if func.return_type.has_flag(.generic) {
|
||||||
c.table.used_features.comptime_syms[typ.clear_option_and_result()] = true
|
c.table.used_features.comptime_syms[typ.clear_option_and_result()] = true
|
||||||
|
c.table.used_features.comptime_syms[func.return_type] = true
|
||||||
}
|
}
|
||||||
return typ
|
return typ
|
||||||
}
|
}
|
||||||
|
@ -2028,6 +2035,10 @@ fn (mut c Checker) method_call(mut node ast.CallExpr, mut continue_check &bool)
|
||||||
node.return_type = left_type
|
node.return_type = left_type
|
||||||
node.receiver_type = left_type
|
node.receiver_type = left_type
|
||||||
|
|
||||||
|
if is_generic {
|
||||||
|
c.table.used_features.comptime_syms[c.unwrap_generic(left_type)] = true
|
||||||
|
}
|
||||||
|
|
||||||
if c.table.cur_fn != unsafe { nil } && c.table.cur_fn.generic_names.len > 0 {
|
if c.table.cur_fn != unsafe { nil } && c.table.cur_fn.generic_names.len > 0 {
|
||||||
c.table.unwrap_generic_type(left_type, c.table.cur_fn.generic_names, c.table.cur_concrete_types)
|
c.table.unwrap_generic_type(left_type, c.table.cur_fn.generic_names, c.table.cur_concrete_types)
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,10 +68,6 @@ fn (mut c Checker) struct_decl(mut node ast.StructDecl) {
|
||||||
if node.language != .c && attr.name == 'typedef' {
|
if node.language != .c && attr.name == 'typedef' {
|
||||||
c.error('`typedef` attribute can only be used with C structs', node.pos)
|
c.error('`typedef` attribute can only be used with C structs', node.pos)
|
||||||
}
|
}
|
||||||
aligned := if attr.arg == '' { 0 } else { attr.arg.int() }
|
|
||||||
if aligned > 1 {
|
|
||||||
c.table.used_features.memory_align = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Evaluate the size of the unresolved fixed array
|
// Evaluate the size of the unresolved fixed array
|
||||||
|
@ -533,6 +529,7 @@ fn (mut c Checker) struct_init(mut node ast.StructInit, is_field_zero_struct_ini
|
||||||
true)
|
true)
|
||||||
if c.pref.skip_unused && node.typ.has_flag(.generic) {
|
if c.pref.skip_unused && node.typ.has_flag(.generic) {
|
||||||
c.table.used_features.comptime_syms[c.unwrap_generic(node.typ)] = true
|
c.table.used_features.comptime_syms[c.unwrap_generic(node.typ)] = true
|
||||||
|
c.table.used_features.comptime_syms[node.typ] = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !is_field_zero_struct_init {
|
if !is_field_zero_struct_init {
|
||||||
|
@ -865,8 +862,6 @@ or use an explicit `unsafe{ a[..] }`, if you do not want a copy of the slice.',
|
||||||
mut info := first_sym.info as ast.Struct
|
mut info := first_sym.info as ast.Struct
|
||||||
c.check_uninitialized_struct_fields_and_embeds(node, first_sym, mut info, mut
|
c.check_uninitialized_struct_fields_and_embeds(node, first_sym, mut info, mut
|
||||||
inited_fields)
|
inited_fields)
|
||||||
} else if first_sym.kind == .array {
|
|
||||||
c.table.used_features.arr_init = true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.none {
|
.none {
|
||||||
|
|
|
@ -175,7 +175,6 @@ fn (mut c Checker) markused_infixexpr(check bool) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.table.used_features.index = true
|
c.table.used_features.index = true
|
||||||
c.table.used_features.arr_init = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut c Checker) markused_array_method(check bool, method_name string) {
|
fn (mut c Checker) markused_array_method(check bool, method_name string) {
|
||||||
|
@ -184,7 +183,6 @@ fn (mut c Checker) markused_array_method(check bool, method_name string) {
|
||||||
}
|
}
|
||||||
match method_name {
|
match method_name {
|
||||||
'' { // array init
|
'' { // array init
|
||||||
c.table.used_features.arr_init = true
|
|
||||||
}
|
}
|
||||||
'first' {
|
'first' {
|
||||||
c.table.used_features.arr_first = true
|
c.table.used_features.arr_first = true
|
||||||
|
|
|
@ -1702,6 +1702,9 @@ pub fn (mut g Gen) write_typedef_types() {
|
||||||
type_symbols := g.table.type_symbols.filter(!it.is_builtin
|
type_symbols := g.table.type_symbols.filter(!it.is_builtin
|
||||||
&& it.kind in [.array, .array_fixed, .chan, .map])
|
&& it.kind in [.array, .array_fixed, .chan, .map])
|
||||||
for sym in type_symbols {
|
for sym in type_symbols {
|
||||||
|
if g.pref.skip_unused && sym.idx !in g.table.used_features.used_syms {
|
||||||
|
continue
|
||||||
|
}
|
||||||
match sym.kind {
|
match sym.kind {
|
||||||
.array {
|
.array {
|
||||||
info := sym.info as ast.Array
|
info := sym.info as ast.Array
|
||||||
|
@ -1752,9 +1755,6 @@ pub fn (mut g Gen) write_typedef_types() {
|
||||||
chan_inf := sym.chan_info()
|
chan_inf := sym.chan_info()
|
||||||
chan_elem_type := chan_inf.elem_type
|
chan_elem_type := chan_inf.elem_type
|
||||||
esym := g.table.sym(chan_elem_type)
|
esym := g.table.sym(chan_elem_type)
|
||||||
if g.pref.skip_unused && esym.idx !in g.table.used_features.used_syms {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
g.type_definitions.writeln('typedef chan ${sym.cname};')
|
g.type_definitions.writeln('typedef chan ${sym.cname};')
|
||||||
is_fixed_arr := esym.kind == .array_fixed
|
is_fixed_arr := esym.kind == .array_fixed
|
||||||
if !chan_elem_type.has_flag(.generic) {
|
if !chan_elem_type.has_flag(.generic) {
|
||||||
|
@ -1776,9 +1776,6 @@ static inline void __${sym.cname}_pushval(${sym.cname} ch, ${push_arg} val) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.map {
|
.map {
|
||||||
if g.pref.skip_unused && g.table.used_features.used_maps == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
g.type_definitions.writeln('typedef map ${sym.cname};')
|
g.type_definitions.writeln('typedef map ${sym.cname};')
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -2614,7 +2611,8 @@ fn (mut g Gen) stmt(node ast.Stmt) {
|
||||||
ast.InterfaceDecl {
|
ast.InterfaceDecl {
|
||||||
// definitions are sorted and added in write_types
|
// definitions are sorted and added in write_types
|
||||||
ts := g.table.sym(node.typ)
|
ts := g.table.sym(node.typ)
|
||||||
if !(ts.info as ast.Interface).is_generic {
|
if !(ts.info as ast.Interface).is_generic
|
||||||
|
&& (!g.pref.skip_unused || ts.idx in g.table.used_features.used_syms) {
|
||||||
for method in node.methods {
|
for method in node.methods {
|
||||||
if method.return_type.has_flag(.option) {
|
if method.return_type.has_flag(.option) {
|
||||||
// Register an option if it's not registered yet
|
// Register an option if it's not registered yet
|
||||||
|
@ -6711,7 +6709,8 @@ fn (mut g Gen) write_types(symbols []&ast.TypeSymbol) {
|
||||||
}
|
}
|
||||||
match sym.info {
|
match sym.info {
|
||||||
ast.Struct {
|
ast.Struct {
|
||||||
if !struct_names[name] {
|
if !struct_names[name]
|
||||||
|
&& (!g.pref.skip_unused || sym.idx in g.table.used_features.used_syms) {
|
||||||
// generate field option types for fixed array of option struct before struct declaration
|
// generate field option types for fixed array of option struct before struct declaration
|
||||||
opt_fields := sym.info.fields.filter(g.table.final_sym(it.typ).kind == .array_fixed)
|
opt_fields := sym.info.fields.filter(g.table.final_sym(it.typ).kind == .array_fixed)
|
||||||
for opt_field in opt_fields {
|
for opt_field in opt_fields {
|
||||||
|
@ -6733,15 +6732,13 @@ fn (mut g Gen) write_types(symbols []&ast.TypeSymbol) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if g.pref.skip_unused && sym.idx !in g.table.used_features.used_syms {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
g.struct_decl(sym.info, name, false, false)
|
g.struct_decl(sym.info, name, false, false)
|
||||||
struct_names[name] = true
|
struct_names[name] = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast.Thread {
|
ast.Thread {
|
||||||
if !g.pref.is_bare && !g.pref.no_builtin {
|
if !g.pref.is_bare && !g.pref.no_builtin
|
||||||
|
&& (!g.pref.skip_unused || sym.idx in g.table.used_features.used_syms) {
|
||||||
if g.pref.os == .windows {
|
if g.pref.os == .windows {
|
||||||
if name == '__v_thread' {
|
if name == '__v_thread' {
|
||||||
g.thread_definitions.writeln('typedef HANDLE ${name};')
|
g.thread_definitions.writeln('typedef HANDLE ${name};')
|
||||||
|
@ -6814,7 +6811,8 @@ fn (mut g Gen) write_types(symbols []&ast.TypeSymbol) {
|
||||||
ast.ArrayFixed {
|
ast.ArrayFixed {
|
||||||
elem_sym := g.table.sym(sym.info.elem_type)
|
elem_sym := g.table.sym(sym.info.elem_type)
|
||||||
if !elem_sym.is_builtin() && !sym.info.elem_type.has_flag(.generic)
|
if !elem_sym.is_builtin() && !sym.info.elem_type.has_flag(.generic)
|
||||||
&& !sym.info.is_fn_ret {
|
&& (!g.pref.skip_unused || (!sym.info.is_fn_ret
|
||||||
|
&& sym.idx in g.table.used_features.used_syms)) {
|
||||||
// .array_fixed {
|
// .array_fixed {
|
||||||
styp := sym.cname
|
styp := sym.cname
|
||||||
// array_fixed_char_300 => char x[300]
|
// array_fixed_char_300 => char x[300]
|
||||||
|
@ -6848,10 +6846,6 @@ fn (mut g Gen) write_types(symbols []&ast.TypeSymbol) {
|
||||||
}
|
}
|
||||||
g.type_definitions.writeln('typedef ${fixed_elem_name} ${styp} [${len}];')
|
g.type_definitions.writeln('typedef ${fixed_elem_name} ${styp} [${len}];')
|
||||||
} else if !(elem_sym.info is ast.ArrayFixed && elem_sym.info.is_fn_ret) {
|
} else if !(elem_sym.info is ast.ArrayFixed && elem_sym.info.is_fn_ret) {
|
||||||
if g.pref.skip_unused
|
|
||||||
&& elem_sym.idx !in g.table.used_features.used_syms {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
g.type_definitions.writeln('typedef ${fixed_elem_name} ${styp} [${len}];')
|
g.type_definitions.writeln('typedef ${fixed_elem_name} ${styp} [${len}];')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
pub struct C.atype {}
|
pub struct C.atype {}
|
||||||
|
|
||||||
|
@[markused]
|
||||||
type BType = &C.atype
|
type BType = &C.atype
|
||||||
|
|
1
vlib/v/gen/c/testdata/iface_method_order.vv
vendored
1
vlib/v/gen/c/testdata/iface_method_order.vv
vendored
|
@ -10,6 +10,7 @@ fn (b Bar) b() {}
|
||||||
|
|
||||||
fn (b Bar) a() {}
|
fn (b Bar) a() {}
|
||||||
|
|
||||||
|
@[markused]
|
||||||
struct Baz implements Foo {
|
struct Baz implements Foo {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ 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.
|
||||||
pub fn mark_used(mut table ast.Table, mut pref_ pref.Preferences, ast_files []&ast.File) {
|
pub fn mark_used(mut table ast.Table, mut pref_ pref.Preferences, ast_files []&ast.File) {
|
||||||
mut all_fns, all_consts, all_globals, all_fields, all_decltypes, all_structs := all_global_decl(ast_files)
|
mut all_fns, all_consts, all_globals, all_decltypes, all_structs := all_global_decl(ast_files)
|
||||||
util.timing_start('MARKUSED')
|
util.timing_start('MARKUSED')
|
||||||
defer {
|
defer {
|
||||||
util.timing_measure('MARKUSED')
|
util.timing_measure('MARKUSED')
|
||||||
|
@ -17,11 +17,9 @@ pub fn mark_used(mut table ast.Table, mut pref_ pref.Preferences, ast_files []&a
|
||||||
trace_skip_unused := pref_.compile_values['trace_skip_unused'] == 'true'
|
trace_skip_unused := pref_.compile_values['trace_skip_unused'] == 'true'
|
||||||
trace_skip_unused_all_fns := pref_.compile_values['trace_skip_unused_all_fns'] == 'true'
|
trace_skip_unused_all_fns := pref_.compile_values['trace_skip_unused_all_fns'] == 'true'
|
||||||
trace_skip_unused_fn_names := pref_.compile_values['trace_skip_unused_fn_names'] == 'true'
|
trace_skip_unused_fn_names := pref_.compile_values['trace_skip_unused_fn_names'] == 'true'
|
||||||
trace_skip_unused_interface_methods := pref_.compile_values['trace_skip_unused_interface_methods'] == 'true'
|
|
||||||
trace_skip_unused_just_unused_fns := pref_.compile_values['trace_skip_unused_just_unused_fns'] == 'true'
|
trace_skip_unused_just_unused_fns := pref_.compile_values['trace_skip_unused_just_unused_fns'] == 'true'
|
||||||
used_fns := pref_.compile_values['used_fns']
|
used_fns := pref_.compile_values['used_fns']
|
||||||
|
|
||||||
byteptr_idx_str := ast.byteptr_type_idx.str()
|
|
||||||
charptr_idx_str := ast.charptr_type_idx.str()
|
charptr_idx_str := ast.charptr_type_idx.str()
|
||||||
string_idx_str := ast.string_type_idx.str()
|
string_idx_str := ast.string_type_idx.str()
|
||||||
array_idx_str := ast.array_type_idx.str()
|
array_idx_str := ast.array_type_idx.str()
|
||||||
|
@ -58,23 +56,13 @@ pub fn mark_used(mut table ast.Table, mut pref_ pref.Preferences, ast_files []&a
|
||||||
} else {
|
} else {
|
||||||
mut core_fns := [
|
mut core_fns := [
|
||||||
'main.main',
|
'main.main',
|
||||||
'init_global_allocator', // needed for linux_bare and wasm_bare
|
|
||||||
'memdup',
|
|
||||||
'tos',
|
|
||||||
'tos2',
|
|
||||||
'error',
|
|
||||||
'fast_string_eq',
|
|
||||||
'println',
|
|
||||||
'ptr_str',
|
|
||||||
]
|
]
|
||||||
|
if pref_.is_bare {
|
||||||
|
core_fns << 'init_global_allocator' // needed for linux_bare and wasm_bare
|
||||||
|
}
|
||||||
if ast_files[ast_files.len - 1].imports.len > 0 {
|
if ast_files[ast_files.len - 1].imports.len > 0 {
|
||||||
core_fns << 'builtin_init'
|
core_fns << 'builtin_init'
|
||||||
}
|
}
|
||||||
if ast.float_literal_type.idx() in table.used_features.print_types
|
|
||||||
|| ast.f64_type_idx in table.used_features.print_types
|
|
||||||
|| ast.f32_type_idx in table.used_features.print_types {
|
|
||||||
include_panic_deps = true
|
|
||||||
}
|
|
||||||
if 'use_libbacktrace' in pref_.compile_defines {
|
if 'use_libbacktrace' in pref_.compile_defines {
|
||||||
core_fns << 'print_libbacktrace'
|
core_fns << 'print_libbacktrace'
|
||||||
}
|
}
|
||||||
|
@ -96,13 +84,6 @@ pub fn mark_used(mut table ast.Table, mut pref_ pref.Preferences, ast_files []&a
|
||||||
core_fns << '__new_array_with_array_default'
|
core_fns << '__new_array_with_array_default'
|
||||||
core_fns << '__new_array_with_array_default_noscan'
|
core_fns << '__new_array_with_array_default_noscan'
|
||||||
core_fns << 'new_array_from_c_array'
|
core_fns << 'new_array_from_c_array'
|
||||||
// byteptr and charptr
|
|
||||||
core_fns << byteptr_idx_str + '.vstring'
|
|
||||||
core_fns << byteptr_idx_str + '.vstring_with_len'
|
|
||||||
core_fns << byteptr_idx_str + '.vstring_literal'
|
|
||||||
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 || pref_.is_shared {
|
if table.used_features.index || pref_.is_shared {
|
||||||
include_panic_deps = true
|
include_panic_deps = true
|
||||||
|
@ -132,10 +113,6 @@ pub fn mark_used(mut table ast.Table, mut pref_ pref.Preferences, ast_files []&a
|
||||||
core_fns << string_idx_str + '.repeat'
|
core_fns << string_idx_str + '.repeat'
|
||||||
core_fns << 'tos3'
|
core_fns << 'tos3'
|
||||||
}
|
}
|
||||||
if table.used_features.auto_str_ptr {
|
|
||||||
include_panic_deps = true
|
|
||||||
core_fns << 'isnil'
|
|
||||||
}
|
|
||||||
if table.used_features.arr_prepend {
|
if table.used_features.arr_prepend {
|
||||||
core_fns << ref_array_idx_str + '.prepend_many'
|
core_fns << ref_array_idx_str + '.prepend_many'
|
||||||
}
|
}
|
||||||
|
@ -163,35 +140,10 @@ pub fn mark_used(mut table ast.Table, mut pref_ pref.Preferences, ast_files []&a
|
||||||
builderptr_idx + '.write_rune',
|
builderptr_idx + '.write_rune',
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
if !table.used_features.arr_init {
|
|
||||||
table.used_features.arr_init = table.used_features.print_types.keys().any(table.type_to_str(it).contains('[]'))
|
|
||||||
}
|
|
||||||
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_default'
|
|
||||||
core_fns << '__new_array_with_default_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 << ref_array_idx_str + '.set'
|
|
||||||
}
|
|
||||||
if table.used_features.comptime_for {
|
|
||||||
include_panic_deps = true
|
|
||||||
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'
|
|
||||||
core_fns << ref_array_idx_str + '.set'
|
|
||||||
}
|
|
||||||
if table.used_features.print_options {
|
if table.used_features.print_options {
|
||||||
include_panic_deps = true
|
include_panic_deps = true
|
||||||
core_fns << '_option_ok'
|
core_fns << '_option_ok'
|
||||||
core_fns << '_result_ok'
|
core_fns << '_result_ok'
|
||||||
core_fns << charptr_idx_str + '.vstring_literal'
|
|
||||||
}
|
}
|
||||||
if table.used_features.anon_fn {
|
if table.used_features.anon_fn {
|
||||||
core_fns << 'memdup_uncollectable'
|
core_fns << 'memdup_uncollectable'
|
||||||
|
@ -207,21 +159,9 @@ pub fn mark_used(mut table ast.Table, mut pref_ pref.Preferences, ast_files []&a
|
||||||
core_fns << ref_densearray_idx_str + '.clone'
|
core_fns << ref_densearray_idx_str + '.clone'
|
||||||
core_fns << map_idx_str + '.clone'
|
core_fns << map_idx_str + '.clone'
|
||||||
}
|
}
|
||||||
if table.used_features.map_update {
|
|
||||||
include_panic_deps = true
|
|
||||||
core_fns << 'new_map_update_init'
|
|
||||||
}
|
|
||||||
if table.used_features.asserts {
|
|
||||||
include_panic_deps = true
|
|
||||||
core_fns << '__print_assert_failure'
|
|
||||||
core_fns << 'isnil'
|
|
||||||
}
|
|
||||||
if table.used_features.type_name {
|
if table.used_features.type_name {
|
||||||
core_fns << charptr_idx_str + '.vstring_literal'
|
core_fns << charptr_idx_str + '.vstring_literal'
|
||||||
}
|
}
|
||||||
if table.used_features.memory_align {
|
|
||||||
core_fns << 'memdup_align'
|
|
||||||
}
|
|
||||||
if pref_.trace_calls || pref_.trace_fns.len > 0 {
|
if pref_.trace_calls || pref_.trace_fns.len > 0 {
|
||||||
include_panic_deps = true
|
include_panic_deps = true
|
||||||
core_fns << 'vgettid'
|
core_fns << 'vgettid'
|
||||||
|
@ -234,6 +174,7 @@ pub fn mark_used(mut table ast.Table, mut pref_ pref.Preferences, ast_files []&a
|
||||||
core_fns << '_result_ok'
|
core_fns << '_result_ok'
|
||||||
core_fns << 'tos5'
|
core_fns << 'tos5'
|
||||||
core_fns << 'time.unix' // used by json
|
core_fns << 'time.unix' // used by json
|
||||||
|
core_fns << 'error'
|
||||||
include_panic_deps = true
|
include_panic_deps = true
|
||||||
}
|
}
|
||||||
if pref_.should_use_segfault_handler() {
|
if pref_.should_use_segfault_handler() {
|
||||||
|
@ -277,38 +218,12 @@ pub fn mark_used(mut table ast.Table, mut pref_ pref.Preferences, ast_files []&a
|
||||||
}
|
}
|
||||||
if mfn.is_method {
|
if mfn.is_method {
|
||||||
method_receiver_typename := table.type_to_str(mfn.receiver.typ)
|
method_receiver_typename := table.type_to_str(mfn.receiver.typ)
|
||||||
if method_receiver_typename == '&wyrand.WyRandRNG' {
|
|
||||||
// WyRandRNG is the default rand pseudo random generator
|
|
||||||
all_fn_root_names << k
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if table.used_features.auto_str && method_receiver_typename == '&strings.Builder' {
|
|
||||||
// implicit string builders are generated in auto_eq_methods.v
|
|
||||||
all_fn_root_names << k
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if method_receiver_typename == '&sync.Channel' {
|
if method_receiver_typename == '&sync.Channel' {
|
||||||
all_fn_root_names << k
|
all_fn_root_names << k
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if mfn.name in ['+', '-', '*', '%', '/', '<', '=='] {
|
|
||||||
// TODO: mark the used operators in the checker
|
|
||||||
all_fn_root_names << k
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
has_dot := k.contains('.')
|
has_dot := k.contains('.')
|
||||||
// auto generated string interpolation functions, may
|
|
||||||
// call .str or .auto_str methods for user types:
|
|
||||||
if table.used_features.auto_str || table.used_features.dump || table.used_features.asserts
|
|
||||||
|| table.used_features.debugger
|
|
||||||
|| table.used_features.print_types[mfn.receiver.typ.idx()] {
|
|
||||||
if (has_dot && (k.ends_with('.str') || k.ends_with('.auto_str')))
|
|
||||||
|| (k.starts_with('_Atomic_') && k.ends_with('_str')) {
|
|
||||||
all_fn_root_names << k
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if has_dot {
|
if has_dot {
|
||||||
if k.ends_with('.init') || k.ends_with('.cleanup') {
|
if k.ends_with('.init') || k.ends_with('.cleanup') {
|
||||||
all_fn_root_names << k
|
all_fn_root_names << k
|
||||||
|
@ -319,10 +234,6 @@ pub fn mark_used(mut table ast.Table, mut pref_ pref.Preferences, ast_files []&a
|
||||||
all_fn_root_names << k
|
all_fn_root_names << k
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if (pref_.autofree || include_panic_deps) && k.ends_with('.free') {
|
|
||||||
all_fn_root_names << k
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if k.ends_with('.lock') || k.ends_with('.unlock') || k.ends_with('.rlock')
|
if k.ends_with('.lock') || k.ends_with('.unlock') || k.ends_with('.rlock')
|
||||||
|| k.ends_with('.runlock') {
|
|| k.ends_with('.runlock') {
|
||||||
all_fn_root_names << k
|
all_fn_root_names << k
|
||||||
|
@ -347,12 +258,6 @@ pub fn mark_used(mut table ast.Table, mut pref_ pref.Preferences, ast_files []&a
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if mfn.receiver.typ != ast.void_type && mfn.generic_names.len > 0 {
|
|
||||||
// generic methods may be used in cgen after specialisation :-|
|
|
||||||
// TODO: move generic method specialisation from cgen to before markused
|
|
||||||
all_fn_root_names << k
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if pref_.prealloc && k.starts_with('prealloc_') {
|
if pref_.prealloc && k.starts_with('prealloc_') {
|
||||||
all_fn_root_names << k
|
all_fn_root_names << k
|
||||||
continue
|
continue
|
||||||
|
@ -376,44 +281,6 @@ pub fn mark_used(mut table ast.Table, mut pref_ pref.Preferences, ast_files []&a
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle interface implementation methods:
|
|
||||||
for isym in table.type_symbols {
|
|
||||||
if isym.kind != .interface {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if isym.info !is ast.Interface {
|
|
||||||
// Do not remove this check, isym.info could be &IError.
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
interface_info := isym.info as ast.Interface
|
|
||||||
if interface_info.methods.len == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for itype in interface_info.types {
|
|
||||||
ptype := itype.set_nr_muls(1)
|
|
||||||
ntype := itype.set_nr_muls(0)
|
|
||||||
interface_types := [ptype, ntype]
|
|
||||||
for method in interface_info.methods {
|
|
||||||
for typ in interface_types {
|
|
||||||
interface_implementation_method_name := int(typ.clear_flags()).str() + '.' +
|
|
||||||
method.name
|
|
||||||
if trace_skip_unused_interface_methods {
|
|
||||||
eprintln('>> isym.name: ${isym.name} | interface_implementation_method_name: ${interface_implementation_method_name}')
|
|
||||||
}
|
|
||||||
all_fn_root_names << interface_implementation_method_name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for embed_method in table.get_embed_methods(table.sym(itype)) {
|
|
||||||
interface_implementation_method_name :=
|
|
||||||
int(embed_method.params[0].typ.clear_flags()).str() + '.' + embed_method.name
|
|
||||||
if trace_skip_unused_interface_methods {
|
|
||||||
eprintln('>> isym.name: ${isym.name} | interface_implementation_method_name: ${interface_implementation_method_name} (embeded)')
|
|
||||||
}
|
|
||||||
all_fn_root_names << interface_implementation_method_name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
handle_vweb(mut table, mut all_fn_root_names, 'veb.Result', 'veb.filter', 'veb.Context')
|
handle_vweb(mut table, mut all_fn_root_names, 'veb.Result', 'veb.filter', 'veb.Context')
|
||||||
handle_vweb(mut table, mut all_fn_root_names, 'vweb.Result', 'vweb.filter', 'vweb.Context')
|
handle_vweb(mut table, mut all_fn_root_names, 'vweb.Result', 'vweb.filter', 'vweb.Context')
|
||||||
handle_vweb(mut table, mut all_fn_root_names, 'x.vweb.Result', 'x.vweb.filter', 'x.vweb.Context')
|
handle_vweb(mut table, mut all_fn_root_names, 'x.vweb.Result', 'x.vweb.filter', 'x.vweb.Context')
|
||||||
|
@ -448,24 +315,20 @@ pub fn mark_used(mut table ast.Table, mut pref_ pref.Preferences, ast_files []&a
|
||||||
all_fns: all_fns
|
all_fns: all_fns
|
||||||
all_consts: all_consts
|
all_consts: all_consts
|
||||||
all_globals: all_globals
|
all_globals: all_globals
|
||||||
all_fields: all_fields
|
|
||||||
all_decltypes: all_decltypes
|
all_decltypes: all_decltypes
|
||||||
all_structs: all_structs
|
all_structs: all_structs
|
||||||
pref: pref_
|
pref: pref_
|
||||||
|
trace_enabled: 'trace_skip_unused_walker' in pref_.compile_defines
|
||||||
)
|
)
|
||||||
walker.mark_markused_consts() // tagged with `@[markused]`
|
walker.mark_markused_consts() // tagged with `@[markused]`
|
||||||
walker.mark_markused_globals() // tagged with `@[markused]`
|
walker.mark_markused_globals() // tagged with `@[markused]`
|
||||||
walker.mark_markused_syms() // tagged with `@[markused]`
|
walker.mark_markused_syms() // tagged with `@[markused]`
|
||||||
walker.mark_markused_fns() // tagged with `@[markused]`, `@[export]` and veb actions
|
walker.mark_markused_fns() // tagged with `@[markused]`, `@[export]` and veb actions
|
||||||
walker.mark_markused_decltypes() // tagged with `@[markused]`
|
walker.mark_markused_decltypes() // tagged with `@[markused]`
|
||||||
walker.mark_struct_field_default_expr()
|
walker.mark_generic_types()
|
||||||
|
|
||||||
for k, _ in table.used_features.comptime_calls {
|
if pref_.use_cache {
|
||||||
walker.fn_by_name(k)
|
walker.mark_by_sym_name('IError')
|
||||||
}
|
|
||||||
|
|
||||||
for k, _ in table.used_features.comptime_syms {
|
|
||||||
walker.mark_by_sym(table.sym(k))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
walker.mark_root_fns(all_fn_root_names)
|
walker.mark_root_fns(all_fn_root_names)
|
||||||
|
@ -473,6 +336,30 @@ pub fn mark_used(mut table ast.Table, mut pref_ pref.Preferences, ast_files []&a
|
||||||
walker.mark_by_sym_name('vweb.RedirectParams')
|
walker.mark_by_sym_name('vweb.RedirectParams')
|
||||||
walker.mark_by_sym_name('vweb.RequestParams')
|
walker.mark_by_sym_name('vweb.RequestParams')
|
||||||
|
|
||||||
|
for kcon, con in all_consts {
|
||||||
|
if pref_.is_shared && con.is_pub {
|
||||||
|
walker.mark_const_as_used(kcon)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if pref_.translated && con.attrs.any(it.name == 'export') {
|
||||||
|
walker.mark_const_as_used(kcon)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if trace_skip_unused_fn_names {
|
||||||
|
for key, _ in walker.used_fns {
|
||||||
|
println('> used fn key: ${key}')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
walker.finalize(include_panic_deps)
|
||||||
|
|
||||||
|
table.used_features.used_none = walker.used_none
|
||||||
|
if walker.used_none == 0 {
|
||||||
|
walker.used_fns.delete('${int(ast.none_type)}.str')
|
||||||
|
}
|
||||||
|
|
||||||
if table.used_features.used_maps > 0 {
|
if table.used_features.used_maps > 0 {
|
||||||
for k, mut mfn in all_fns {
|
for k, mut mfn in all_fns {
|
||||||
mut method_receiver_typename := ''
|
mut method_receiver_typename := ''
|
||||||
|
@ -508,30 +395,6 @@ pub fn mark_used(mut table ast.Table, mut pref_ pref.Preferences, ast_files []&a
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for kcon, con in all_consts {
|
|
||||||
if pref_.is_shared && con.is_pub {
|
|
||||||
walker.mark_const_as_used(kcon)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if pref_.translated && con.attrs.any(it.name == 'export') {
|
|
||||||
walker.mark_const_as_used(kcon)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if trace_skip_unused_fn_names {
|
|
||||||
for key, _ in walker.used_fns {
|
|
||||||
println('> used fn key: ${key}')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
table.used_features.used_none = walker.used_none
|
|
||||||
if walker.used_none == 0 {
|
|
||||||
walker.used_fns.delete('${int(ast.none_type)}.str')
|
|
||||||
}
|
|
||||||
|
|
||||||
walker.finalize(include_panic_deps)
|
|
||||||
|
|
||||||
table.used_features.used_fns = walker.used_fns.move()
|
table.used_features.used_fns = walker.used_fns.move()
|
||||||
table.used_features.used_consts = walker.used_consts.move()
|
table.used_features.used_consts = walker.used_consts.move()
|
||||||
table.used_features.used_globals = walker.used_globals.move()
|
table.used_features.used_globals = walker.used_globals.move()
|
||||||
|
@ -556,7 +419,7 @@ pub fn mark_used(mut table ast.Table, mut pref_ pref.Preferences, ast_files []&a
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn all_global_decl(ast_files []&ast.File) (map[string]ast.FnDecl, map[string]ast.ConstField, map[string]ast.GlobalField, map[string]ast.StructField, map[string]ast.Type, map[string]ast.StructDecl) {
|
fn all_global_decl(ast_files []&ast.File) (map[string]ast.FnDecl, map[string]ast.ConstField, map[string]ast.GlobalField, map[string]ast.TypeDecl, map[string]ast.StructDecl) {
|
||||||
util.timing_start(@METHOD)
|
util.timing_start(@METHOD)
|
||||||
defer {
|
defer {
|
||||||
util.timing_measure(@METHOD)
|
util.timing_measure(@METHOD)
|
||||||
|
@ -564,8 +427,7 @@ fn all_global_decl(ast_files []&ast.File) (map[string]ast.FnDecl, map[string]ast
|
||||||
mut all_fns := map[string]ast.FnDecl{}
|
mut all_fns := map[string]ast.FnDecl{}
|
||||||
mut all_consts := map[string]ast.ConstField{}
|
mut all_consts := map[string]ast.ConstField{}
|
||||||
mut all_globals := map[string]ast.GlobalField{}
|
mut all_globals := map[string]ast.GlobalField{}
|
||||||
mut all_fields := map[string]ast.StructField{}
|
mut all_decltypes := map[string]ast.TypeDecl{}
|
||||||
mut all_decltypes := map[string]ast.Type{}
|
|
||||||
mut all_structs := map[string]ast.StructDecl{}
|
mut all_structs := map[string]ast.StructDecl{}
|
||||||
for i in 0 .. ast_files.len {
|
for i in 0 .. ast_files.len {
|
||||||
for node in ast_files[i].stmts {
|
for node in ast_files[i].stmts {
|
||||||
|
@ -589,20 +451,18 @@ fn all_global_decl(ast_files []&ast.File) (map[string]ast.FnDecl, map[string]ast
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast.StructDecl {
|
ast.StructDecl {
|
||||||
for sfield in node.fields {
|
|
||||||
sfkey := sfield.sfkey()
|
|
||||||
all_fields[sfkey] = sfield
|
|
||||||
}
|
|
||||||
all_structs[node.name] = node
|
all_structs[node.name] = node
|
||||||
}
|
}
|
||||||
ast.TypeDecl {
|
ast.TypeDecl {
|
||||||
all_decltypes[node.name] = node.typ
|
if node.is_markused {
|
||||||
|
all_decltypes[node.name] = node
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {}
|
else {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return all_fns, all_consts, all_globals, all_fields, all_decltypes, all_structs
|
return all_fns, all_consts, all_globals, all_decltypes, all_structs
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mark_all_methods_used(mut table ast.Table, mut all_fn_root_names []string, typ ast.Type) {
|
fn mark_all_methods_used(mut table ast.Table, mut all_fn_root_names []string, typ ast.Type) {
|
||||||
|
|
|
@ -9,32 +9,33 @@ import v.pref
|
||||||
|
|
||||||
pub struct Walker {
|
pub struct Walker {
|
||||||
pub mut:
|
pub mut:
|
||||||
table &ast.Table = unsafe { nil }
|
table &ast.Table = unsafe { nil }
|
||||||
features &ast.UsedFeatures = unsafe { nil }
|
features &ast.UsedFeatures = unsafe { nil }
|
||||||
used_fns map[string]bool // used_fns['println'] == true
|
used_fns map[string]bool // used_fns['println'] == true
|
||||||
used_consts map[string]bool // used_consts['os.args'] == true
|
trace_enabled bool
|
||||||
used_globals map[string]bool
|
used_consts map[string]bool // used_consts['os.args'] == true
|
||||||
used_fields map[string]bool
|
used_globals map[string]bool
|
||||||
used_syms map[int]bool
|
used_fields map[string]bool
|
||||||
used_none int // _option_none
|
used_syms map[int]bool
|
||||||
used_option int // _option_ok
|
used_none int // _option_none
|
||||||
used_result int // _result_ok
|
used_option int // _option_ok
|
||||||
used_panic int // option/result propagation
|
used_result int // _result_ok
|
||||||
used_interp int // str interpolation
|
used_panic int // option/result propagation
|
||||||
n_asserts int
|
pref &pref.Preferences = unsafe { nil }
|
||||||
pref &pref.Preferences = unsafe { nil }
|
|
||||||
mut:
|
mut:
|
||||||
files []&ast.File
|
files []&ast.File
|
||||||
all_fns map[string]ast.FnDecl
|
all_fns map[string]ast.FnDecl
|
||||||
all_consts map[string]ast.ConstField
|
all_consts map[string]ast.ConstField
|
||||||
all_globals map[string]ast.GlobalField
|
all_globals map[string]ast.GlobalField
|
||||||
all_fields map[string]ast.StructField
|
all_fields map[string]ast.StructField
|
||||||
all_decltypes map[string]ast.Type
|
all_decltypes map[string]ast.TypeDecl
|
||||||
all_structs map[string]ast.StructDecl
|
all_structs map[string]ast.StructDecl
|
||||||
|
|
||||||
|
level int
|
||||||
is_builtin_mod bool
|
is_builtin_mod bool
|
||||||
|
|
||||||
// dependencies finding flags
|
// dependencies finding flags
|
||||||
|
uses_atomic bool // has atomic
|
||||||
uses_array bool // has array
|
uses_array bool // has array
|
||||||
uses_channel bool // has chan dep
|
uses_channel bool // has chan dep
|
||||||
uses_lock bool // has mutex dep
|
uses_lock bool // has mutex dep
|
||||||
|
@ -46,6 +47,20 @@ mut:
|
||||||
uses_ct_attribute bool // $for .attributes
|
uses_ct_attribute bool // $for .attributes
|
||||||
uses_external_type bool
|
uses_external_type bool
|
||||||
uses_err bool // err var
|
uses_err bool // err var
|
||||||
|
uses_asserts bool // assert
|
||||||
|
uses_map_update bool // has {...expr}
|
||||||
|
uses_debugger bool // has debugger;
|
||||||
|
uses_mem_align bool // @[aligned:N] for structs
|
||||||
|
uses_eq bool // has == op
|
||||||
|
uses_interp bool // string interpolation
|
||||||
|
uses_guard bool
|
||||||
|
uses_orm bool
|
||||||
|
uses_str bool // has .str() call
|
||||||
|
uses_free bool // has .free() call
|
||||||
|
uses_spawn bool
|
||||||
|
uses_dump bool
|
||||||
|
uses_memdup bool // sumtype cast and &Struct{}
|
||||||
|
uses_arr_void bool // auto arr methods
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn Walker.new(params Walker) &Walker {
|
pub fn Walker.new(params Walker) &Walker {
|
||||||
|
@ -92,6 +107,9 @@ pub fn (mut w Walker) mark_const_as_used(ckey string) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
w.used_consts[ckey] = true
|
w.used_consts[ckey] = true
|
||||||
|
if ckey == 'c' {
|
||||||
|
println(ckey)
|
||||||
|
}
|
||||||
cfield := w.all_consts[ckey] or { return }
|
cfield := w.all_consts[ckey] or { return }
|
||||||
w.expr(cfield.expr)
|
w.expr(cfield.expr)
|
||||||
w.mark_by_type(cfield.typ)
|
w.mark_by_type(cfield.typ)
|
||||||
|
@ -118,7 +136,6 @@ pub fn (mut w Walker) mark_struct_field_default_expr_as_used(sfkey string) {
|
||||||
}
|
}
|
||||||
w.used_fields[sfkey] = true
|
w.used_fields[sfkey] = true
|
||||||
sfield := w.all_fields[sfkey] or { return }
|
sfield := w.all_fields[sfkey] or { return }
|
||||||
|
|
||||||
w.expr(sfield.default_expr)
|
w.expr(sfield.default_expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,6 +166,9 @@ pub fn (mut w Walker) mark_markused_fns() {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut w Walker) mark_root_fns(all_fn_root_names []string) {
|
pub fn (mut w Walker) mark_root_fns(all_fn_root_names []string) {
|
||||||
|
if w.trace_enabled {
|
||||||
|
eprintln('>>>>>>> ROOT ${all_fn_root_names}')
|
||||||
|
}
|
||||||
for fn_name in all_fn_root_names {
|
for fn_name in all_fn_root_names {
|
||||||
if fn_name !in w.used_fns {
|
if fn_name !in w.used_fns {
|
||||||
$if trace_skip_unused_roots ? {
|
$if trace_skip_unused_roots ? {
|
||||||
|
@ -192,15 +212,9 @@ pub fn (mut w Walker) mark_markused_syms() {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut w Walker) mark_markused_decltypes() {
|
pub fn (mut w Walker) mark_markused_decltypes() {
|
||||||
for _, typ in w.all_decltypes {
|
for _, decl in w.all_decltypes {
|
||||||
w.mark_by_type(typ)
|
if decl.is_markused {
|
||||||
}
|
w.mark_by_type(decl.typ)
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (mut w Walker) mark_struct_field_default_expr() {
|
|
||||||
for sfkey, mut structfield in w.all_fields {
|
|
||||||
if structfield.has_default_expr {
|
|
||||||
w.mark_struct_field_default_expr_as_used(sfkey)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -209,14 +223,16 @@ pub fn (mut w Walker) stmt(node_ ast.Stmt) {
|
||||||
mut node := unsafe { node_ }
|
mut node := unsafe { node_ }
|
||||||
match mut node {
|
match mut node {
|
||||||
ast.EmptyStmt {}
|
ast.EmptyStmt {}
|
||||||
ast.DebuggerStmt {}
|
ast.DebuggerStmt {
|
||||||
|
w.uses_debugger = true
|
||||||
|
}
|
||||||
ast.AsmStmt {
|
ast.AsmStmt {
|
||||||
w.asm_io(node.output)
|
w.asm_io(node.output)
|
||||||
w.asm_io(node.input)
|
w.asm_io(node.input)
|
||||||
}
|
}
|
||||||
ast.AssertStmt {
|
ast.AssertStmt {
|
||||||
if node.is_used {
|
if node.is_used {
|
||||||
w.n_asserts++
|
w.uses_asserts = true
|
||||||
w.expr(node.expr)
|
w.expr(node.expr)
|
||||||
if node.extra !is ast.EmptyExpr {
|
if node.extra !is ast.EmptyExpr {
|
||||||
w.expr(node.extra)
|
w.expr(node.extra)
|
||||||
|
@ -314,12 +330,16 @@ pub fn (mut w Walker) stmt(node_ ast.Stmt) {
|
||||||
w.expr(line.where_expr)
|
w.expr(line.where_expr)
|
||||||
w.exprs(line.update_exprs)
|
w.exprs(line.update_exprs)
|
||||||
}
|
}
|
||||||
|
w.uses_orm = true
|
||||||
}
|
}
|
||||||
ast.StructDecl {
|
ast.StructDecl {
|
||||||
for typ in node.implements_types {
|
for typ in node.implements_types {
|
||||||
w.mark_by_type(typ.typ)
|
w.mark_by_type(typ.typ)
|
||||||
}
|
}
|
||||||
w.struct_fields(node.fields)
|
w.struct_fields(node.fields)
|
||||||
|
if !w.uses_mem_align {
|
||||||
|
w.uses_mem_align = node.attrs.contains('aligned')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ast.DeferStmt {
|
ast.DeferStmt {
|
||||||
w.stmts(node.stmts)
|
w.stmts(node.stmts)
|
||||||
|
@ -381,7 +401,12 @@ fn (mut w Walker) expr(node_ ast.Expr) {
|
||||||
w.fn_decl(mut node.decl)
|
w.fn_decl(mut node.decl)
|
||||||
}
|
}
|
||||||
ast.ArrayInit {
|
ast.ArrayInit {
|
||||||
w.mark_by_type(node.elem_type)
|
sym := w.table.sym(node.elem_type)
|
||||||
|
w.mark_by_sym(sym)
|
||||||
|
if sym.info is ast.Thread {
|
||||||
|
w.mark_by_type(w.table.find_or_register_array(sym.info.return_type))
|
||||||
|
}
|
||||||
|
w.mark_by_type(node.typ)
|
||||||
w.expr(node.len_expr)
|
w.expr(node.len_expr)
|
||||||
w.expr(node.cap_expr)
|
w.expr(node.cap_expr)
|
||||||
w.expr(node.init_expr)
|
w.expr(node.init_expr)
|
||||||
|
@ -398,18 +423,35 @@ fn (mut w Walker) expr(node_ ast.Expr) {
|
||||||
w.call_expr(mut node)
|
w.call_expr(mut node)
|
||||||
if node.name == 'json.decode' {
|
if node.name == 'json.decode' {
|
||||||
w.mark_by_type((node.args[0].expr as ast.TypeNode).typ)
|
w.mark_by_type((node.args[0].expr as ast.TypeNode).typ)
|
||||||
|
} else if node.name == 'json.encode' && node.args[0].typ != 0 {
|
||||||
|
sym := w.table.final_sym(node.args[0].typ)
|
||||||
|
if sym.info is ast.Map {
|
||||||
|
w.mark_by_type(w.table.find_or_register_array(sym.info.key_type))
|
||||||
|
}
|
||||||
|
} else if !w.uses_str && node.is_method && node.name == 'str' {
|
||||||
|
w.uses_str = true
|
||||||
|
} else if !w.uses_free && node.is_method && node.name == 'free' {
|
||||||
|
w.uses_free = true
|
||||||
}
|
}
|
||||||
if !w.is_builtin_mod && !w.uses_external_type {
|
if !w.is_builtin_mod && !w.uses_external_type {
|
||||||
if node.is_method {
|
if node.is_method {
|
||||||
w.uses_external_type = node.mod == 'builtin'
|
w.uses_external_type = node.mod == 'builtin'
|
||||||
} else if node.name.contains('.') {
|
} else if node.name.contains('.') && node.name.all_before_last('.').len > 1 {
|
||||||
w.uses_external_type = true
|
w.uses_external_type = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if node.is_method && node.left_type != 0
|
||||||
|
&& w.table.final_sym(node.left_type).kind in [.array_fixed, .array] {
|
||||||
|
w.mark_by_type(node.return_type)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ast.CastExpr {
|
ast.CastExpr {
|
||||||
w.expr(node.expr)
|
w.expr(node.expr)
|
||||||
w.expr(node.arg)
|
w.expr(node.arg)
|
||||||
|
if !w.uses_memdup {
|
||||||
|
fsym := w.table.final_sym(node.typ)
|
||||||
|
w.uses_memdup = fsym.kind == .sum_type
|
||||||
|
}
|
||||||
w.mark_by_type(node.typ)
|
w.mark_by_type(node.typ)
|
||||||
if node.typ.has_flag(.option) {
|
if node.typ.has_flag(.option) {
|
||||||
w.used_option++
|
w.used_option++
|
||||||
|
@ -441,8 +483,7 @@ fn (mut w Walker) expr(node_ ast.Expr) {
|
||||||
}
|
}
|
||||||
ast.DumpExpr {
|
ast.DumpExpr {
|
||||||
w.expr(node.expr)
|
w.expr(node.expr)
|
||||||
w.fn_by_name('eprint')
|
w.uses_dump = true
|
||||||
w.fn_by_name('eprintln')
|
|
||||||
w.mark_by_type(node.expr_type)
|
w.mark_by_type(node.expr_type)
|
||||||
}
|
}
|
||||||
ast.SpawnExpr {
|
ast.SpawnExpr {
|
||||||
|
@ -450,7 +491,8 @@ fn (mut w Walker) expr(node_ ast.Expr) {
|
||||||
w.fn_by_name('free')
|
w.fn_by_name('free')
|
||||||
}
|
}
|
||||||
w.expr(node.call_expr)
|
w.expr(node.call_expr)
|
||||||
w.fn_by_name('tos3')
|
w.uses_spawn = true
|
||||||
|
|
||||||
if w.pref.os == .windows {
|
if w.pref.os == .windows {
|
||||||
w.fn_by_name('panic_lasterr')
|
w.fn_by_name('panic_lasterr')
|
||||||
w.fn_by_name('winapi_lasterr_str')
|
w.fn_by_name('winapi_lasterr_str')
|
||||||
|
@ -463,11 +505,16 @@ fn (mut w Walker) expr(node_ ast.Expr) {
|
||||||
if node.is_expr {
|
if node.is_expr {
|
||||||
w.fn_by_name('free')
|
w.fn_by_name('free')
|
||||||
}
|
}
|
||||||
|
w.mark_by_type(node.call_expr.return_type)
|
||||||
w.expr(node.call_expr)
|
w.expr(node.call_expr)
|
||||||
}
|
}
|
||||||
ast.IndexExpr {
|
ast.IndexExpr {
|
||||||
w.expr(node.left)
|
w.expr(node.left)
|
||||||
w.expr(node.index)
|
w.expr(node.index)
|
||||||
|
if node.or_expr.kind == .block {
|
||||||
|
w.uses_guard = true
|
||||||
|
}
|
||||||
|
w.mark_by_type(node.typ)
|
||||||
w.or_block(node.or_expr)
|
w.or_block(node.or_expr)
|
||||||
if node.left_type == 0 {
|
if node.left_type == 0 {
|
||||||
return
|
return
|
||||||
|
@ -505,8 +552,8 @@ fn (mut w Walker) expr(node_ ast.Expr) {
|
||||||
w.expr(node.right)
|
w.expr(node.right)
|
||||||
w.or_block(node.or_block)
|
w.or_block(node.or_block)
|
||||||
if node.left_type != 0 {
|
if node.left_type != 0 {
|
||||||
w.mark_by_type(node.left_type)
|
|
||||||
sym := w.table.sym(node.left_type)
|
sym := w.table.sym(node.left_type)
|
||||||
|
w.mark_by_sym(sym)
|
||||||
if sym.kind == .struct {
|
if sym.kind == .struct {
|
||||||
if opmethod := sym.find_method(node.op.str()) {
|
if opmethod := sym.find_method(node.op.str()) {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -527,14 +574,21 @@ fn (mut w Walker) expr(node_ ast.Expr) {
|
||||||
if right_sym.kind == .map {
|
if right_sym.kind == .map {
|
||||||
w.features.used_maps++
|
w.features.used_maps++
|
||||||
}
|
}
|
||||||
|
if !w.uses_arr_void && right_sym.kind in [.array, .array_fixed] {
|
||||||
|
w.uses_arr_void = true
|
||||||
|
}
|
||||||
} else if node.op in [.key_is, .not_is] {
|
} else if node.op in [.key_is, .not_is] {
|
||||||
w.mark_by_sym(right_sym)
|
w.mark_by_sym(right_sym)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if !w.uses_eq && node.op in [.eq, .ne] {
|
||||||
|
w.uses_eq = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ast.IfGuardExpr {
|
ast.IfGuardExpr {
|
||||||
w.expr(node.expr)
|
w.expr(node.expr)
|
||||||
w.mark_by_type(node.expr_type)
|
w.mark_by_type(node.expr_type)
|
||||||
|
w.uses_guard = true
|
||||||
}
|
}
|
||||||
ast.IfExpr {
|
ast.IfExpr {
|
||||||
w.expr(node.left)
|
w.expr(node.left)
|
||||||
|
@ -557,8 +611,9 @@ fn (mut w Walker) expr(node_ ast.Expr) {
|
||||||
.global {
|
.global {
|
||||||
w.mark_global_as_used(node.name)
|
w.mark_global_as_used(node.name)
|
||||||
}
|
}
|
||||||
|
.blank_ident {}
|
||||||
else {
|
else {
|
||||||
// `.unresolved`, `.blank_ident`, `.variable`, `.function`
|
// `.unresolved`, `.variable`
|
||||||
// println('>>> else, ast.Ident ${node.name} kind: $node.kind ')
|
// println('>>> else, ast.Ident ${node.name} kind: $node.kind ')
|
||||||
if node.name in w.all_consts {
|
if node.name in w.all_consts {
|
||||||
w.mark_const_as_used(node.name)
|
w.mark_const_as_used(node.name)
|
||||||
|
@ -571,6 +626,9 @@ fn (mut w Walker) expr(node_ ast.Expr) {
|
||||||
}
|
}
|
||||||
w.fn_by_name(node.name)
|
w.fn_by_name(node.name)
|
||||||
}
|
}
|
||||||
|
if !w.uses_atomic && node.info is ast.IdentVar {
|
||||||
|
w.uses_atomic = node.info.typ.has_flag(.atomic_f)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
w.or_block(node.or_expr)
|
w.or_block(node.or_expr)
|
||||||
|
@ -587,6 +645,9 @@ fn (mut w Walker) expr(node_ ast.Expr) {
|
||||||
if node.has_update_expr {
|
if node.has_update_expr {
|
||||||
w.expr(node.update_expr)
|
w.expr(node.update_expr)
|
||||||
}
|
}
|
||||||
|
if node.vals.len > 0 && node.has_update_expr {
|
||||||
|
w.uses_map_update = true
|
||||||
|
}
|
||||||
mapinfo := w.table.final_sym(node.typ).map_info()
|
mapinfo := w.table.final_sym(node.typ).map_info()
|
||||||
ksym := w.table.sym(mapinfo.key_type)
|
ksym := w.table.sym(mapinfo.key_type)
|
||||||
vsym := w.table.sym(mapinfo.value_type)
|
vsym := w.table.sym(mapinfo.value_type)
|
||||||
|
@ -596,6 +657,7 @@ fn (mut w Walker) expr(node_ ast.Expr) {
|
||||||
w.mark_by_sym(ksym)
|
w.mark_by_sym(ksym)
|
||||||
w.mark_by_sym(vsym)
|
w.mark_by_sym(vsym)
|
||||||
w.features.used_maps++
|
w.features.used_maps++
|
||||||
|
w.mark_by_type(node.typ)
|
||||||
}
|
}
|
||||||
ast.MatchExpr {
|
ast.MatchExpr {
|
||||||
w.expr(node.cond)
|
w.expr(node.cond)
|
||||||
|
@ -617,6 +679,9 @@ fn (mut w Walker) expr(node_ ast.Expr) {
|
||||||
w.expr(node.expr)
|
w.expr(node.expr)
|
||||||
}
|
}
|
||||||
ast.PrefixExpr {
|
ast.PrefixExpr {
|
||||||
|
if !w.uses_memdup && node.op == .amp {
|
||||||
|
w.uses_memdup = true
|
||||||
|
}
|
||||||
w.expr(node.right)
|
w.expr(node.right)
|
||||||
}
|
}
|
||||||
ast.PostfixExpr {
|
ast.PostfixExpr {
|
||||||
|
@ -635,7 +700,7 @@ fn (mut w Walker) expr(node_ ast.Expr) {
|
||||||
w.mark_by_type(node.typ)
|
w.mark_by_type(node.typ)
|
||||||
}
|
}
|
||||||
ast.StringInterLiteral {
|
ast.StringInterLiteral {
|
||||||
w.used_interp++
|
w.uses_interp = true
|
||||||
w.exprs(node.exprs)
|
w.exprs(node.exprs)
|
||||||
}
|
}
|
||||||
ast.SelectorExpr {
|
ast.SelectorExpr {
|
||||||
|
@ -657,6 +722,7 @@ fn (mut w Walker) expr(node_ ast.Expr) {
|
||||||
w.expr(node.limit_expr)
|
w.expr(node.limit_expr)
|
||||||
w.expr(node.where_expr)
|
w.expr(node.where_expr)
|
||||||
w.mark_by_type(node.typ)
|
w.mark_by_type(node.typ)
|
||||||
|
w.uses_orm = true
|
||||||
}
|
}
|
||||||
ast.StructInit {
|
ast.StructInit {
|
||||||
if node.typ == 0 {
|
if node.typ == 0 {
|
||||||
|
@ -730,6 +796,13 @@ pub fn (mut w Walker) fn_decl(mut node ast.FnDecl) {
|
||||||
if node == unsafe { nil } {
|
if node == unsafe { nil } {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if w.level == 0 {
|
||||||
|
last_is_builtin_mod := w.is_builtin_mod
|
||||||
|
w.is_builtin_mod = node.mod in ['builtin', 'os', 'strconv', 'builtin.closure']
|
||||||
|
defer {
|
||||||
|
w.is_builtin_mod = last_is_builtin_mod
|
||||||
|
}
|
||||||
|
}
|
||||||
if node.language == .c {
|
if node.language == .c {
|
||||||
w.mark_fn_as_used(node.fkey())
|
w.mark_fn_as_used(node.fkey())
|
||||||
w.mark_fn_ret_and_params(node.return_type, node.params)
|
w.mark_fn_ret_and_params(node.return_type, node.params)
|
||||||
|
@ -742,15 +815,22 @@ pub fn (mut w Walker) fn_decl(mut node ast.FnDecl) {
|
||||||
if node.no_body {
|
if node.no_body {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if w.trace_enabled {
|
||||||
|
w.level++
|
||||||
|
defer { w.level-- }
|
||||||
|
receiver_name := if node.is_method && node.receiver.typ != 0 {
|
||||||
|
w.table.type_to_str(node.receiver.typ) + '.'
|
||||||
|
} else {
|
||||||
|
''
|
||||||
|
}
|
||||||
|
eprintln('>>>${' '.repeat(w.level)}${receiver_name}${node.name} [decl]')
|
||||||
|
}
|
||||||
if node.is_method {
|
if node.is_method {
|
||||||
w.mark_by_type(node.receiver.typ)
|
w.mark_by_type(node.receiver.typ)
|
||||||
}
|
}
|
||||||
w.mark_fn_ret_and_params(node.return_type, node.params)
|
w.mark_fn_ret_and_params(node.return_type, node.params)
|
||||||
w.mark_fn_as_used(fkey)
|
w.mark_fn_as_used(fkey)
|
||||||
last_is_builtin_mod := w.is_builtin_mod
|
|
||||||
w.is_builtin_mod = node.mod in ['builtin', 'os', 'strconv', 'builtin.closure']
|
|
||||||
w.stmts(node.stmts)
|
w.stmts(node.stmts)
|
||||||
w.is_builtin_mod = last_is_builtin_mod
|
|
||||||
w.defer_stmts(node.defer_stmts)
|
w.defer_stmts(node.defer_stmts)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -768,9 +848,7 @@ pub fn (mut w Walker) call_expr(mut node ast.CallExpr) {
|
||||||
if node.name in ['C.wyhash', 'C.wyhash64'] {
|
if node.name in ['C.wyhash', 'C.wyhash64'] {
|
||||||
w.features.used_maps++
|
w.features.used_maps++
|
||||||
}
|
}
|
||||||
if node.return_type != 0 {
|
w.mark_by_type(node.return_type)
|
||||||
w.mark_by_type(node.return_type)
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if node.is_method && node.left_type != 0 {
|
if node.is_method && node.left_type != 0 {
|
||||||
|
@ -804,6 +882,17 @@ pub fn (mut w Walker) call_expr(mut node ast.CallExpr) {
|
||||||
fn_embed := '${int(embed_types.last())}.${node.name}'
|
fn_embed := '${int(embed_types.last())}.${node.name}'
|
||||||
w.fn_by_name(fn_embed)
|
w.fn_by_name(fn_embed)
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
match left_sym.info {
|
||||||
|
ast.Array, ast.ArrayFixed {
|
||||||
|
if !w.uses_arr_void && node.name in ['contains', 'index'] {
|
||||||
|
if w.table.final_sym(left_sym.info.elem_type).kind == .function {
|
||||||
|
w.uses_arr_void = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
w.expr(node.left)
|
w.expr(node.left)
|
||||||
|
@ -844,9 +933,22 @@ pub fn (mut w Walker) call_expr(mut node ast.CallExpr) {
|
||||||
receiver_typ = node.receiver_concrete_type
|
receiver_typ = node.receiver_concrete_type
|
||||||
w.mark_fn_as_used(fn_name)
|
w.mark_fn_as_used(fn_name)
|
||||||
}
|
}
|
||||||
|
w.mark_by_type(node.return_type)
|
||||||
stmt := w.all_fns[fn_name] or { return }
|
stmt := w.all_fns[fn_name] or { return }
|
||||||
if !stmt.should_be_skipped && stmt.name == node.name {
|
if !stmt.should_be_skipped && stmt.name == node.name {
|
||||||
if !node.is_method || receiver_typ == stmt.receiver.typ {
|
if !node.is_method || receiver_typ == stmt.receiver.typ {
|
||||||
|
if w.trace_enabled {
|
||||||
|
w.level++
|
||||||
|
defer {
|
||||||
|
w.level--
|
||||||
|
}
|
||||||
|
receiver_name := if node.receiver_type != 0 {
|
||||||
|
w.table.type_to_str(node.receiver_type) + '.'
|
||||||
|
} else {
|
||||||
|
''
|
||||||
|
}
|
||||||
|
eprintln('>>>${' '.repeat(w.level)}${receiver_name}${node.name} [call]')
|
||||||
|
}
|
||||||
w.mark_fn_ret_and_params(stmt.return_type, stmt.params)
|
w.mark_fn_ret_and_params(stmt.return_type, stmt.params)
|
||||||
w.stmts(stmt.stmts)
|
w.stmts(stmt.stmts)
|
||||||
}
|
}
|
||||||
|
@ -863,6 +965,18 @@ pub fn (mut w Walker) fn_by_name(fn_name string) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
stmt := w.all_fns[fn_name] or { return }
|
stmt := w.all_fns[fn_name] or { return }
|
||||||
|
if w.trace_enabled {
|
||||||
|
w.level++
|
||||||
|
defer {
|
||||||
|
w.level--
|
||||||
|
}
|
||||||
|
receiver_name := if fn_name.contains('.') && fn_name.all_before_last('.').int() > 0 {
|
||||||
|
w.table.type_to_str(fn_name.all_before_last('.').int()) + '.'
|
||||||
|
} else {
|
||||||
|
''
|
||||||
|
}
|
||||||
|
eprintln('>>>${' '.repeat(w.level)}${receiver_name}${fn_name.all_after_last('.')} [by_name]')
|
||||||
|
}
|
||||||
w.mark_fn_as_used(fn_name)
|
w.mark_fn_as_used(fn_name)
|
||||||
w.mark_fn_ret_and_params(stmt.return_type, stmt.params)
|
w.mark_fn_ret_and_params(stmt.return_type, stmt.params)
|
||||||
w.stmts(stmt.stmts)
|
w.stmts(stmt.stmts)
|
||||||
|
@ -873,6 +987,9 @@ pub fn (mut w Walker) struct_fields(sfields []ast.StructField) {
|
||||||
if sf.has_default_expr {
|
if sf.has_default_expr {
|
||||||
w.expr(sf.default_expr)
|
w.expr(sf.default_expr)
|
||||||
}
|
}
|
||||||
|
if !w.uses_atomic && sf.typ.has_flag(.atomic_f) {
|
||||||
|
w.uses_atomic = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -895,27 +1012,6 @@ pub fn (mut w Walker) or_block(node ast.OrExpr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut w Walker) mark_panic_deps() {
|
|
||||||
ref_array_idx_str := int(ast.array_type.ref()).str()
|
|
||||||
string_idx_str := ast.string_type_idx.str()
|
|
||||||
array_idx_str := ast.array_type_idx.str()
|
|
||||||
charptr_idx_str := ast.charptr_type_idx.str()
|
|
||||||
|
|
||||||
w.fn_by_name('__new_array_with_default')
|
|
||||||
w.fn_by_name('__new_array_with_default_noscan')
|
|
||||||
w.fn_by_name('str_intp')
|
|
||||||
w.fn_by_name(ref_array_idx_str + '.push')
|
|
||||||
w.fn_by_name(ref_array_idx_str + '.push_noscan')
|
|
||||||
w.fn_by_name(string_idx_str + '.substr')
|
|
||||||
w.fn_by_name(array_idx_str + '.slice')
|
|
||||||
w.fn_by_name(array_idx_str + '.get')
|
|
||||||
w.fn_by_name('v_fixed_index')
|
|
||||||
w.fn_by_name(charptr_idx_str + '.vstring_literal')
|
|
||||||
|
|
||||||
w.mark_by_sym_name('StrIntpData')
|
|
||||||
w.mark_by_sym_name('StrIntpMem')
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn (mut w Walker) mark_fn_ret_and_params(return_type ast.Type, params []ast.Param) {
|
pub fn (mut w Walker) mark_fn_ret_and_params(return_type ast.Type, params []ast.Param) {
|
||||||
if return_type != 0 {
|
if return_type != 0 {
|
||||||
if return_type.has_flag(.option) {
|
if return_type.has_flag(.option) {
|
||||||
|
@ -930,6 +1026,7 @@ pub fn (mut w Walker) mark_fn_ret_and_params(return_type ast.Type, params []ast.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@[inline]
|
||||||
pub fn (mut w Walker) mark_by_sym_name(name string) {
|
pub fn (mut w Walker) mark_by_sym_name(name string) {
|
||||||
if sym := w.table.find_sym(name) {
|
if sym := w.table.find_sym(name) {
|
||||||
w.mark_by_sym(sym)
|
w.mark_by_sym(sym)
|
||||||
|
@ -956,7 +1053,7 @@ pub fn (mut w Walker) mark_by_sym(isym ast.TypeSymbol) {
|
||||||
w.expr(ifield.default_expr)
|
w.expr(ifield.default_expr)
|
||||||
}
|
}
|
||||||
if ifield.typ != 0 {
|
if ifield.typ != 0 {
|
||||||
fsym := w.table.sym(ifield.typ)
|
fsym := w.table.sym(ifield.typ.idx())
|
||||||
if ifield.typ.has_flag(.option) {
|
if ifield.typ.has_flag(.option) {
|
||||||
w.used_option++
|
w.used_option++
|
||||||
if !ifield.has_default_expr {
|
if !ifield.has_default_expr {
|
||||||
|
@ -964,9 +1061,6 @@ pub fn (mut w Walker) mark_by_sym(isym ast.TypeSymbol) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
match fsym.info {
|
match fsym.info {
|
||||||
ast.Array, ast.ArrayFixed {
|
|
||||||
w.mark_by_sym(fsym)
|
|
||||||
}
|
|
||||||
ast.Map {
|
ast.Map {
|
||||||
w.features.used_maps++
|
w.features.used_maps++
|
||||||
w.mark_by_sym(fsym)
|
w.mark_by_sym(fsym)
|
||||||
|
@ -976,17 +1070,26 @@ pub fn (mut w Walker) mark_by_sym(isym ast.TypeSymbol) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if !w.features.auto_str_ptr && ifield.typ.is_ptr()
|
||||||
|
&& isym.idx in w.features.print_types {
|
||||||
|
w.features.auto_str_ptr = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for embed in isym.info.embeds {
|
for embed in isym.info.embeds {
|
||||||
w.mark_by_type(embed)
|
w.mark_by_type(embed)
|
||||||
}
|
}
|
||||||
if decl := w.all_structs[isym.name] {
|
if decl := w.all_structs[isym.name] {
|
||||||
|
w.struct_fields(decl.fields)
|
||||||
|
if !w.uses_mem_align {
|
||||||
|
w.uses_mem_align = decl.attrs.contains('aligned')
|
||||||
|
}
|
||||||
for iface_typ in decl.implements_types {
|
for iface_typ in decl.implements_types {
|
||||||
w.mark_by_type(iface_typ.typ)
|
w.mark_by_type(iface_typ.typ)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast.ArrayFixed, ast.Array {
|
ast.ArrayFixed, ast.Array {
|
||||||
|
w.uses_array = true
|
||||||
w.mark_by_type(isym.info.elem_type)
|
w.mark_by_type(isym.info.elem_type)
|
||||||
}
|
}
|
||||||
ast.SumType {
|
ast.SumType {
|
||||||
|
@ -1030,6 +1133,13 @@ pub fn (mut w Walker) mark_by_sym(isym ast.TypeSymbol) {
|
||||||
}
|
}
|
||||||
ast.Enum {
|
ast.Enum {
|
||||||
w.mark_by_type(isym.info.typ)
|
w.mark_by_type(isym.info.typ)
|
||||||
|
if enum_ := w.table.enum_decls[isym.name] {
|
||||||
|
for field in enum_.fields {
|
||||||
|
if field.has_expr {
|
||||||
|
w.expr(field.expr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ast.Interface {
|
ast.Interface {
|
||||||
for typ in isym.info.types {
|
for typ in isym.info.types {
|
||||||
|
@ -1037,6 +1147,17 @@ pub fn (mut w Walker) mark_by_sym(isym ast.TypeSymbol) {
|
||||||
w.features.used_maps++
|
w.features.used_maps++
|
||||||
}
|
}
|
||||||
w.mark_by_type(typ)
|
w.mark_by_type(typ)
|
||||||
|
for method in isym.info.methods {
|
||||||
|
for ityp in [typ.set_nr_muls(1), typ.set_nr_muls(0)] {
|
||||||
|
mname := int(ityp.clear_flags()).str() + '.' + method.name
|
||||||
|
w.fn_by_name(mname)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for embed_method in w.table.get_embed_methods(w.table.sym(typ)) {
|
||||||
|
mname := int(embed_method.params[0].typ.clear_flags()).str() + '.' +
|
||||||
|
embed_method.name
|
||||||
|
w.fn_by_name(mname)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for embed in isym.info.embeds {
|
for embed in isym.info.embeds {
|
||||||
w.mark_by_type(embed)
|
w.mark_by_type(embed)
|
||||||
|
@ -1053,6 +1174,9 @@ pub fn (mut w Walker) mark_by_sym(isym ast.TypeSymbol) {
|
||||||
w.mark_fn_ret_and_params(method.return_type, method.params)
|
w.mark_fn_ret_and_params(method.return_type, method.params)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ast.Thread {
|
||||||
|
w.mark_by_type(isym.info.return_type)
|
||||||
|
}
|
||||||
else {}
|
else {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1087,6 +1211,17 @@ fn (mut w Walker) remove_unused_dump_type() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut w Walker) mark_resource_dependencies() {
|
fn (mut w Walker) mark_resource_dependencies() {
|
||||||
|
if w.trace_enabled {
|
||||||
|
eprintln('>>>>>>>>>> DEPS USAGE')
|
||||||
|
}
|
||||||
|
if w.uses_eq {
|
||||||
|
w.fn_by_name('fast_string_eq')
|
||||||
|
}
|
||||||
|
if w.features.auto_str_ptr {
|
||||||
|
w.fn_by_name('isnil')
|
||||||
|
w.fn_by_name('tos4')
|
||||||
|
w.fn_by_name('str_intp')
|
||||||
|
}
|
||||||
if w.uses_channel {
|
if w.uses_channel {
|
||||||
w.fn_by_name('sync.new_channel_st')
|
w.fn_by_name('sync.new_channel_st')
|
||||||
w.fn_by_name('sync.channel_select')
|
w.fn_by_name('sync.channel_select')
|
||||||
|
@ -1094,6 +1229,28 @@ fn (mut w Walker) mark_resource_dependencies() {
|
||||||
if w.uses_lock {
|
if w.uses_lock {
|
||||||
w.mark_by_sym_name('sync.RwMutex')
|
w.mark_by_sym_name('sync.RwMutex')
|
||||||
}
|
}
|
||||||
|
if w.uses_array {
|
||||||
|
if w.pref.gc_mode in [.boehm_full_opt, .boehm_incr_opt] {
|
||||||
|
w.fn_by_name('__new_array_noscan')
|
||||||
|
w.fn_by_name('new_array_from_c_array_noscan')
|
||||||
|
w.fn_by_name('__new_array_with_multi_default_noscan')
|
||||||
|
w.fn_by_name('__new_array_with_array_default_noscan')
|
||||||
|
w.fn_by_name('__new_array_with_default_noscan')
|
||||||
|
}
|
||||||
|
w.fn_by_name('__new_array')
|
||||||
|
w.fn_by_name('new_array_from_c_array')
|
||||||
|
w.fn_by_name('__new_array_with_multi_default')
|
||||||
|
w.fn_by_name('__new_array_with_array_default')
|
||||||
|
w.fn_by_name('__new_array_with_default')
|
||||||
|
w.fn_by_name(int(ast.array_type.ref()).str() + '.set')
|
||||||
|
}
|
||||||
|
if w.uses_orm {
|
||||||
|
w.fn_by_name('__new_array_with_default_noscan')
|
||||||
|
w.fn_by_name('new_array_from_c_array')
|
||||||
|
w.fn_by_name('__new_array')
|
||||||
|
w.fn_by_name('${ast.array_type_idx}.get')
|
||||||
|
w.fn_by_name(int(ast.array_type.ref()).str() + '.push')
|
||||||
|
}
|
||||||
if w.uses_ct_fields {
|
if w.uses_ct_fields {
|
||||||
w.mark_by_sym_name('FieldData')
|
w.mark_by_sym_name('FieldData')
|
||||||
}
|
}
|
||||||
|
@ -1112,14 +1269,91 @@ fn (mut w Walker) mark_resource_dependencies() {
|
||||||
if w.uses_ct_attribute {
|
if w.uses_ct_attribute {
|
||||||
w.mark_by_sym_name('VAttribute')
|
w.mark_by_sym_name('VAttribute')
|
||||||
}
|
}
|
||||||
|
if w.uses_map_update {
|
||||||
|
w.fn_by_name('new_map_update_init')
|
||||||
|
}
|
||||||
|
if w.uses_mem_align {
|
||||||
|
w.fn_by_name('memdup_align')
|
||||||
|
}
|
||||||
|
if w.uses_guard {
|
||||||
|
w.fn_by_name('error')
|
||||||
|
}
|
||||||
|
if w.uses_dump {
|
||||||
|
w.fn_by_name('eprint')
|
||||||
|
w.fn_by_name('eprintln')
|
||||||
|
}
|
||||||
|
if w.uses_spawn {
|
||||||
|
w.fn_by_name('malloc')
|
||||||
|
w.fn_by_name('tos3')
|
||||||
|
}
|
||||||
|
if w.uses_memdup {
|
||||||
|
w.fn_by_name('memdup')
|
||||||
|
}
|
||||||
|
if w.uses_debugger {
|
||||||
|
w.mark_by_type(w.table.find_or_register_map(ast.string_type, ast.string_type))
|
||||||
|
}
|
||||||
|
if w.uses_arr_void {
|
||||||
|
w.mark_by_type(w.table.find_or_register_array(ast.voidptr_type))
|
||||||
|
}
|
||||||
|
if w.trace_enabled {
|
||||||
|
types := w.table.used_features.print_types.keys().map(w.table.type_to_str(it))
|
||||||
|
eprintln('>>>>>>>>>> PRINT TYPES ${types}')
|
||||||
|
}
|
||||||
|
for typ, _ in w.table.used_features.print_types {
|
||||||
|
w.mark_by_type(typ)
|
||||||
|
}
|
||||||
|
if w.trace_enabled {
|
||||||
|
eprintln('>>>>>>>>>> ALL_FNS LOOP')
|
||||||
|
}
|
||||||
|
mut has_ptr_print := false
|
||||||
|
has_str_call := w.uses_interp || w.uses_asserts || w.uses_str || w.features.print_types.len > 0
|
||||||
|
for k, mut func in w.all_fns {
|
||||||
|
if has_str_call && k.ends_with('.str') {
|
||||||
|
if func.receiver.typ.idx() in w.used_syms {
|
||||||
|
w.fn_by_name(k)
|
||||||
|
if !has_ptr_print && func.receiver.typ.is_ptr() {
|
||||||
|
w.fn_by_name('ptr_str')
|
||||||
|
has_ptr_print = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if w.pref.autofree || (w.uses_free && k.ends_with('.free')
|
||||||
|
&& func.receiver.typ.idx() in w.used_syms) {
|
||||||
|
w.fn_by_name(k)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if w.uses_atomic && k.starts_with('_Atomic') {
|
||||||
|
w.fn_by_name(k)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if func.name in ['+', '-', '*', '%', '/', '<', '=='] {
|
||||||
|
if func.receiver.typ.idx() in w.used_syms {
|
||||||
|
w.fn_by_name(k)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !func.is_static_type_method && func.receiver.typ != ast.void_type
|
||||||
|
&& func.generic_names.len > 0 {
|
||||||
|
if func.receiver.typ.set_nr_muls(0) in w.table.used_features.comptime_syms
|
||||||
|
|| func.receiver.typ in w.table.used_features.comptime_syms {
|
||||||
|
w.fn_by_name(k)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut w Walker) finalize(include_panic_deps bool) {
|
pub fn (mut w Walker) finalize(include_panic_deps bool) {
|
||||||
if include_panic_deps || w.used_interp > 0 || w.uses_external_type {
|
|
||||||
w.mark_panic_deps()
|
|
||||||
}
|
|
||||||
w.mark_resource_dependencies()
|
w.mark_resource_dependencies()
|
||||||
|
if w.trace_enabled {
|
||||||
|
eprintln('>>>>>>>>>> FINALIZE')
|
||||||
|
}
|
||||||
|
if w.uses_asserts {
|
||||||
|
w.fn_by_name('__print_assert_failure')
|
||||||
|
w.fn_by_name('isnil')
|
||||||
|
w.mark_by_sym_name('VAssertMetaInfo')
|
||||||
|
}
|
||||||
if w.used_panic > 0 {
|
if w.used_panic > 0 {
|
||||||
w.mark_fn_as_used('panic_option_not_set')
|
w.mark_fn_as_used('panic_option_not_set')
|
||||||
w.mark_fn_as_used('panic_result_not_set')
|
w.mark_fn_as_used('panic_result_not_set')
|
||||||
|
@ -1140,13 +1374,50 @@ pub fn (mut w Walker) finalize(include_panic_deps bool) {
|
||||||
if (w.used_option + w.used_result + w.used_none) > 0 {
|
if (w.used_option + w.used_result + w.used_none) > 0 {
|
||||||
w.mark_const_as_used('none__')
|
w.mark_const_as_used('none__')
|
||||||
}
|
}
|
||||||
w.mark_by_sym_name('array')
|
if include_panic_deps || w.uses_external_type || w.uses_asserts || w.uses_debugger
|
||||||
|
|| w.uses_interp {
|
||||||
|
if w.trace_enabled {
|
||||||
|
println('>>>>> PANIC DEPS ${include_panic_deps} | external_type=${w.uses_external_type} | asserts=${w.uses_asserts} | dbg=${w.uses_debugger}')
|
||||||
|
}
|
||||||
|
ref_array_idx_str := int(ast.array_type.ref()).str()
|
||||||
|
string_idx_str := ast.string_type_idx.str()
|
||||||
|
|
||||||
if w.table.used_features.asserts {
|
if w.pref.gc_mode in [.boehm_full_opt, .boehm_incr_opt] {
|
||||||
w.mark_by_sym_name('VAssertMetaInfo')
|
w.fn_by_name('__new_array_with_default_noscan')
|
||||||
|
w.fn_by_name(ref_array_idx_str + '.push_noscan')
|
||||||
|
}
|
||||||
|
w.fn_by_name('str_intp')
|
||||||
|
w.fn_by_name('__new_array_with_default')
|
||||||
|
w.fn_by_name(ref_array_idx_str + '.push')
|
||||||
|
w.fn_by_name(string_idx_str + '.substr')
|
||||||
|
w.fn_by_name('v_fixed_index')
|
||||||
|
w.mark_by_sym_name('StrIntpData')
|
||||||
|
w.mark_by_sym_name('StrIntpMem')
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove unused symbols
|
// remove unused symbols
|
||||||
w.remove_unused_fn_generic_types()
|
w.remove_unused_fn_generic_types()
|
||||||
w.remove_unused_dump_type()
|
w.remove_unused_dump_type()
|
||||||
|
|
||||||
|
if w.trace_enabled {
|
||||||
|
syms := w.used_syms.keys().map(w.table.type_to_str(it))
|
||||||
|
eprintln('>>>>>>>>>> USED SYMS ${syms}')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn (mut w Walker) mark_generic_types() {
|
||||||
|
if w.trace_enabled {
|
||||||
|
eprintln('>>>>>>>>>> COMPTIME SYMS+CALLS')
|
||||||
|
}
|
||||||
|
for k, _ in w.table.used_features.comptime_calls {
|
||||||
|
w.fn_by_name(k)
|
||||||
|
}
|
||||||
|
|
||||||
|
for k, _ in w.table.used_features.comptime_syms {
|
||||||
|
sym := w.table.sym(k)
|
||||||
|
w.mark_by_sym(sym)
|
||||||
|
for method in sym.get_methods() {
|
||||||
|
w.fn_by_name('${k}.${method.name}')
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,8 @@ pub fn (t &ResolverInfo) has_comptime_expr(node ast.Expr) bool {
|
||||||
&& node.init_fields.any(it.expr is ast.AnonFn && it.expr.decl.generic_names.len > 0))
|
&& node.init_fields.any(it.expr is ast.AnonFn && it.expr.decl.generic_names.len > 0))
|
||||||
|| (node is ast.PostfixExpr && t.has_comptime_expr(node.expr))
|
|| (node is ast.PostfixExpr && t.has_comptime_expr(node.expr))
|
||||||
|| (node is ast.SelectorExpr && t.has_comptime_expr(node.expr))
|
|| (node is ast.SelectorExpr && t.has_comptime_expr(node.expr))
|
||||||
|
|| (node is ast.ArrayInit && node.elem_type.has_flag(.generic))
|
||||||
|
|| (node is ast.MapInit && node.typ.has_flag(.generic))
|
||||||
|| (node is ast.InfixExpr && (t.has_comptime_expr(node.left)
|
|| (node is ast.InfixExpr && (t.has_comptime_expr(node.left)
|
||||||
|| t.has_comptime_expr(node.right)))
|
|| t.has_comptime_expr(node.right)))
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue