diff options
-rw-r--r-- | changelog.md | 2 | ||||
-rw-r--r-- | compiler/options.nim | 1 | ||||
-rw-r--r-- | compiler/vm.nim | 7 | ||||
-rw-r--r-- | compiler/vmops.nim | 3 | ||||
-rw-r--r-- | lib/std/vmutils.nim | 11 | ||||
-rw-r--r-- | tests/stdlib/tvmutils.nim | 31 |
6 files changed, 53 insertions, 2 deletions
diff --git a/changelog.md b/changelog.md index 570aff542..6672f7538 100644 --- a/changelog.md +++ b/changelog.md @@ -387,6 +387,8 @@ - Added `--declaredlocs` to show symbol declaration location in messages. +- You can now enable/disable VM tracing in user code via `vmutils.vmTrace`. + - Deprecated `TaintedString` and `--taintmode`. - Deprecated `--nilseqs` which is now a noop. diff --git a/compiler/options.nim b/compiler/options.nim index ffb0f4501..135ecf1de 100644 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -330,6 +330,7 @@ type warnCounter*: int errorMax*: int maxLoopIterationsVM*: int ## VM: max iterations of all loops + isVmTrace*: bool configVars*: StringTableRef symbols*: StringTableRef ## We need to use a StringTableRef here as defined ## symbols are always guaranteed to be style diff --git a/compiler/vm.nim b/compiler/vm.nim index 837a1c366..9541af701 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -548,9 +548,12 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = "pc", $pc, "opcode", alignLeft($c.code[pc].opcode, 15), "ra", regDescr("ra", ra), "rb", regDescr("rb", instr.regB), "rc", regDescr("rc", instr.regC)] - + if c.config.isVmTrace: + # unlike nimVMDebug, this doesn't require re-compiling nim and is controlled by user code + let info = c.debug[pc] + # other useful variables: c.loopIterations + echo "$# [$#] $#" % [c.config$info, $instr.opcode, c.config.sourceLine(info)] c.profiler.enter(c, tos) - case instr.opcode of opcEof: return regs[ra] of opcRet: diff --git a/compiler/vmops.nim b/compiler/vmops.nim index 85729fd59..67a196b8f 100644 --- a/compiler/vmops.nim +++ b/compiler/vmops.nim @@ -249,6 +249,9 @@ proc registerAdditionalOps*(c: PCtx) = "isExported() requires a symbol. '" & $n & "' is of kind '" & $n.kind & "'", n.info) setResult(a, sfExported in n.sym.flags) + registerCallback c, "stdlib.vmutils.vmTrace", proc (a: VmArgs) = + c.config.isVmTrace = getBool(a, 0) + proc hashVmImpl(a: VmArgs) = var res = hashes.hash(a.getString(0), a.getInt(1).int, a.getInt(2).int) if c.config.backend == backendJs: diff --git a/lib/std/vmutils.nim b/lib/std/vmutils.nim new file mode 100644 index 000000000..e16912a3c --- /dev/null +++ b/lib/std/vmutils.nim @@ -0,0 +1,11 @@ +##[ +Experimental API, subject to change. +]## + +proc vmTrace*(on: bool) {.compileTime.} = + runnableExamples: + static: vmTrace(true) + proc fn = + var a = 1 + vmTrace(false) + static: fn() diff --git a/tests/stdlib/tvmutils.nim b/tests/stdlib/tvmutils.nim new file mode 100644 index 000000000..f43557ad8 --- /dev/null +++ b/tests/stdlib/tvmutils.nim @@ -0,0 +1,31 @@ +discard """ + joinable: false + nimout: ''' +0 +1 +2 +tvmutils.nim(28, 13) [opcLdImmInt] if i == 4: +tvmutils.nim(28, 10) [opcEqInt] if i == 4: +tvmutils.nim(28, 10) [opcFJmp] if i == 4: +tvmutils.nim(28, 13) [opcLdImmInt] if i == 4: +tvmutils.nim(28, 10) [opcEqInt] if i == 4: +tvmutils.nim(28, 10) [opcFJmp] if i == 4: +tvmutils.nim(29, 7) [opcLdConst] vmTrace(false) +tvmutils.nim(29, 15) [opcLdImmInt] vmTrace(false) +tvmutils.nim(29, 14) [opcIndCall] vmTrace(false) +5 +6 +''' +""" +# line 20 (only showing a subset of nimout to avoid making the test rigid) +import std/vmutils + +proc main() = + for i in 0..<7: + echo i + if i == 2: + vmTrace(true) + if i == 4: + vmTrace(false) + +static: main() |