mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
v.pref: support v -trace-calls run file.v
(#15450)
This commit is contained in:
parent
d3307fd2e3
commit
af8bd10761
@ -77,6 +77,7 @@ fn test_all() {
|
||||
global_run_dir := '$checker_dir/globals_run'
|
||||
run_dir := '$checker_dir/run'
|
||||
skip_unused_dir := 'vlib/v/tests/skip_unused'
|
||||
trace_calls_dir := 'vlib/v/tests/trace_calls'
|
||||
//
|
||||
checker_tests := get_tests_in_dir(checker_dir, false)
|
||||
parser_tests := get_tests_in_dir(parser_dir, false)
|
||||
@ -86,6 +87,7 @@ fn test_all() {
|
||||
module_tests := get_tests_in_dir(module_dir, true)
|
||||
run_tests := get_tests_in_dir(run_dir, false)
|
||||
skip_unused_dir_tests := get_tests_in_dir(skip_unused_dir, false)
|
||||
trace_calls_dir_tests := get_tests_in_dir(trace_calls_dir, false)
|
||||
mut tasks := Tasks{
|
||||
vexe: vexe
|
||||
label: 'all tests'
|
||||
@ -113,6 +115,15 @@ fn test_all() {
|
||||
skip_unused_tasks.add('', skip_unused_dir, '-d no_backtrace -skip-unused run',
|
||||
'.skip_unused.run.out', skip_unused_dir_tests, false)
|
||||
skip_unused_tasks.run()
|
||||
//
|
||||
mut trace_calls_tasks := Tasks{
|
||||
vexe: vexe
|
||||
parallel_jobs: 1
|
||||
label: '-trace-calls tests'
|
||||
}
|
||||
trace_calls_tasks.add('', trace_calls_dir, '-trace-calls run', '.run.out', trace_calls_dir_tests,
|
||||
false)
|
||||
trace_calls_tasks.run()
|
||||
}
|
||||
//
|
||||
if github_job == 'ubuntu-tcc' {
|
||||
|
@ -158,7 +158,8 @@ pub mut:
|
||||
building_v bool
|
||||
autofree bool // `v -manualfree` => false, `v -autofree` => true; false by default for now.
|
||||
// Disabling `free()` insertion results in better performance in some applications (e.g. compilers)
|
||||
compress bool // when set, use `upx` to compress the generated executable
|
||||
trace_calls bool // -trace-calls true = the transformer stage will generate and inject print calls for tracing function calls
|
||||
compress bool // when set, use `upx` to compress the generated executable
|
||||
// generating_vh bool
|
||||
no_builtin bool // Skip adding the `builtin` module implicitly. The generated C code may not compile.
|
||||
enable_globals bool // allow __global for low level code
|
||||
@ -429,6 +430,9 @@ pub fn parse_args_and_show_errors(known_external_commands []string, args []strin
|
||||
res.autofree = true
|
||||
res.build_options << arg
|
||||
}
|
||||
'-trace-calls' {
|
||||
res.trace_calls = true
|
||||
}
|
||||
'-manualfree' {
|
||||
res.autofree = false
|
||||
res.build_options << arg
|
||||
|
6
vlib/v/tests/trace_calls/simple.run.out
Normal file
6
vlib/v/tests/trace_calls/simple.run.out
Normal file
@ -0,0 +1,6 @@
|
||||
> trace fn main()
|
||||
> trace fn foo()
|
||||
> trace fn bar()
|
||||
> trace fn baz()
|
||||
> trace fn (b Boo) call_1()
|
||||
end
|
25
vlib/v/tests/trace_calls/simple.vv
Normal file
25
vlib/v/tests/trace_calls/simple.vv
Normal file
@ -0,0 +1,25 @@
|
||||
module main
|
||||
|
||||
fn C.test()
|
||||
|
||||
struct Boo {}
|
||||
|
||||
fn (b Boo) call_1() {}
|
||||
|
||||
fn foo() {
|
||||
bar()
|
||||
}
|
||||
|
||||
fn bar() {
|
||||
baz()
|
||||
}
|
||||
|
||||
fn baz() {
|
||||
boo := Boo{}
|
||||
boo.call_1()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
foo()
|
||||
eprintln('end')
|
||||
}
|
8
vlib/v/tests/trace_calls/with_modules.run.out
Normal file
8
vlib/v/tests/trace_calls/with_modules.run.out
Normal file
@ -0,0 +1,8 @@
|
||||
> trace fn init_os_args(argc int, argv &&u8) []string
|
||||
> trace pub fn getwd() string
|
||||
> trace fn main()
|
||||
> trace fn f1()
|
||||
> trace fn f2()
|
||||
> trace fn f3()
|
||||
> trace pub fn join_path(base string, dirs ...string) string
|
||||
end
|
20
vlib/v/tests/trace_calls/with_modules.vv
Normal file
20
vlib/v/tests/trace_calls/with_modules.vv
Normal file
@ -0,0 +1,20 @@
|
||||
module main
|
||||
|
||||
import os
|
||||
|
||||
fn f1() {
|
||||
f2()
|
||||
}
|
||||
|
||||
fn f2() {
|
||||
f3()
|
||||
}
|
||||
|
||||
fn f3() {
|
||||
_ := os.join_path('1', '2', '3')
|
||||
}
|
||||
|
||||
fn main() {
|
||||
f1()
|
||||
eprintln('end')
|
||||
}
|
@ -226,6 +226,7 @@ pub fn (mut t Transformer) stmt(mut node ast.Stmt) ast.Stmt {
|
||||
}
|
||||
}
|
||||
ast.FnDecl {
|
||||
t.fn_decl(mut node)
|
||||
t.index.indent(true)
|
||||
for mut stmt in node.stmts {
|
||||
stmt = t.stmt(mut stmt)
|
||||
@ -1034,3 +1035,51 @@ pub fn (mut t Transformer) sql_expr(mut node ast.SqlExpr) ast.Expr {
|
||||
}
|
||||
return node
|
||||
}
|
||||
|
||||
// fn_decl mutates `node`.
|
||||
// if `pref.trace_calls` is true ast Nodes for `eprintln(...)` is prepended to the `FnDecl`'s
|
||||
// stmts list to let the gen backend generate the target specific code for the print.
|
||||
pub fn (mut t Transformer) fn_decl(mut node ast.FnDecl) {
|
||||
if t.pref.trace_calls {
|
||||
// Skip `C.fn()` and all of builtin
|
||||
// builtin could probably be traced also but would need
|
||||
// special cases for, at least, println/eprintln
|
||||
if node.no_body || node.is_builtin {
|
||||
return
|
||||
}
|
||||
call_expr := t.gen_trace_print_call_expr(node)
|
||||
expr_stmt := ast.ExprStmt{
|
||||
expr: call_expr
|
||||
}
|
||||
node.stmts.prepend(expr_stmt)
|
||||
}
|
||||
}
|
||||
|
||||
// gen_trace_print_expr_stmt generates an ast.CallExpr representation of a
|
||||
// `eprint(...)` V code statement.
|
||||
fn (t Transformer) gen_trace_print_call_expr(node ast.FnDecl) ast.CallExpr {
|
||||
print_str := '> trace ' + node.stringify(t.table, node.mod, map[string]string{})
|
||||
|
||||
call_arg := ast.CallArg{
|
||||
expr: ast.StringLiteral{
|
||||
val: print_str
|
||||
}
|
||||
typ: ast.string_type_idx
|
||||
}
|
||||
args := [call_arg]
|
||||
|
||||
fn_name := 'eprintln'
|
||||
call_expr := ast.CallExpr{
|
||||
name: fn_name
|
||||
args: args
|
||||
mod: node.mod
|
||||
pos: node.pos
|
||||
language: node.language
|
||||
scope: node.scope
|
||||
comments: [ast.Comment{
|
||||
text: 'fn $node.short_name trace call'
|
||||
}]
|
||||
}
|
||||
|
||||
return call_expr
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user