Skip to content

Commit

Permalink
make into option
Browse files Browse the repository at this point in the history
  • Loading branch information
metagn committed Dec 5, 2024
1 parent d9d2c6f commit 1e5bc46
Show file tree
Hide file tree
Showing 6 changed files with 26 additions and 9 deletions.
6 changes: 6 additions & 0 deletions compiler/commands.nim
Original file line number Diff line number Diff line change
Expand Up @@ -919,6 +919,12 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
discard parseSaturatedNatural(arg, value)
if not value > 0: localError(conf, info, "maxLoopIterationsVM must be a positive integer greater than zero")
conf.maxLoopIterationsVM = value
of "maxcalldepthvm":
expectArg(conf, switch, arg, pass, info)
var value: int = 2_000
discard parseSaturatedNatural(arg, value)
if not value > 0: localError(conf, info, "maxCallDepthVM must be a positive integer greater than zero")
conf.maxCallDepthVM = value
of "errormax":
expectArg(conf, switch, arg, pass, info)
# Note: `nim check` (etc) can overwrite this.
Expand Down
2 changes: 2 additions & 0 deletions compiler/options.nim
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,7 @@ type
warnCounter*: int
errorMax*: int
maxLoopIterationsVM*: int ## VM: max iterations of all loops
maxCallDepthVM*: int ## VM: max call depth
isVmTrace*: bool
configVars*: StringTableRef
symbols*: StringTableRef ## We need to use a StringTableRef here as defined
Expand Down Expand Up @@ -600,6 +601,7 @@ proc newConfigRef*(): ConfigRef =
arguments: "",
suggestMaxResults: 10_000,
maxLoopIterationsVM: 10_000_000,
maxCallDepthVM: 2_000,
vmProfileData: newProfileData(),
spellSuggestMax: spellSuggestSecretSauce,
currentConfigDir: ""
Expand Down
19 changes: 12 additions & 7 deletions compiler/vm.nim
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,8 @@ const
errIllegalConvFromXtoY = "illegal conversion from '$1' to '$2'"
errTooManyIterations = "interpretation requires too many iterations; " &
"if you are sure this is not a bug in your code, compile with `--maxLoopIterationsVM:number` (current value: $1)"
errCallDepthExceeded = "maximum call depth for the VM exceeded; " &
"if you are sure this is not a bug in your code, compile with `--maxCallDepthVM:number` (current value: $1)"
errFieldXNotFound = "node lacks field: "


Expand Down Expand Up @@ -590,7 +592,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
let newPc = c.cleanUpOnReturn(tos)
# Perform any cleanup action before returning
if newPc < 0:
dec c.callDepth
inc(c.callDepth)
pc = tos.comesFrom
let retVal = regs[0]
tos = tos.next
Expand Down Expand Up @@ -1446,12 +1448,14 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
newFrame.slots[i] = regs[rb+i]
if isClosure:
newFrame.slots[rc] = TFullReg(kind: rkNode, node: regs[rb].node[1])
if c.callDepth > 2000:
msgWriteln(c.config, "stack trace: (most recent call last)", {msgNoUnitSep})
stackTraceAux(c, tos, pc)
globalError(c.config, c.debug[pc], "maximum call depth exceeded (2000)")
else:
inc c.callDepth
if c.callDepth <= 0:
if allowInfiniteRecursion in c.features:
c.callDepth = c.config.maxCallDepthVM
else:
msgWriteln(c.config, "stack trace: (most recent call last)", {msgNoUnitSep})
stackTraceAux(c, tos, pc)
globalError(c.config, c.debug[pc], errCallDepthExceeded % $c.config.maxCallDepthVM)
dec(c.callDepth)
tos = newFrame
updateRegsAlias
# -1 for the following 'inc pc'
Expand Down Expand Up @@ -2318,6 +2322,7 @@ proc execute(c: PCtx, start: int): PNode =

proc execProc*(c: PCtx; sym: PSym; args: openArray[PNode]): PNode =
c.loopIterations = c.config.maxLoopIterationsVM
c.callDepth = c.config.maxCallDepthVM
if sym.kind in routineKinds:
if sym.typ.paramsLen != args.len:
result = nil
Expand Down
5 changes: 4 additions & 1 deletion compiler/vmdef.nim
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ type
TSandboxFlag* = enum ## what the evaluation engine should allow
allowCast, ## allow unsafe language feature: 'cast'
allowInfiniteLoops ## allow endless loops
allowInfiniteRecursion ## allow infinite recursion
TSandboxFlags* = set[TSandboxFlag]

TSlotKind* = enum # We try to re-use slots in a smart way to
Expand Down Expand Up @@ -293,14 +294,16 @@ type
proc newCtx*(module: PSym; cache: IdentCache; g: ModuleGraph; idgen: IdGenerator): PCtx =
PCtx(code: @[], debug: @[],
globals: newNode(nkStmtListExpr), constants: newNode(nkStmtList), types: @[],
prc: PProc(blocks: @[]), module: module, loopIterations: g.config.maxLoopIterationsVM, callDepth: 0,
prc: PProc(blocks: @[]), module: module, loopIterations: g.config.maxLoopIterationsVM,
callDepth: g.config.maxCallDepthVM,
comesFromHeuristic: unknownLineInfo, callbacks: @[], callbackIndex: initTable[string, int](), errorFlag: "",
cache: cache, config: g.config, graph: g, idgen: idgen)

proc refresh*(c: PCtx, module: PSym; idgen: IdGenerator) =
c.module = module
c.prc = PProc(blocks: @[])
c.loopIterations = c.config.maxLoopIterationsVM
c.callDepth = c.config.maxCallDepthVM
c.idgen = idgen

proc reverseName(s: string): string =
Expand Down
1 change: 1 addition & 0 deletions doc/advopt.txt
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ Advanced options:
--verbosity:0|1|2|3 set Nim's verbosity level (1 is default)
--errorMax:N stop compilation after N errors; 0 means unlimited
--maxLoopIterationsVM:N set max iterations for all VM loops
--maxCallDepthVM:N set max call depth in the VM
--experimental:$1
enable experimental language feature
--legacy:$2
Expand Down
2 changes: 1 addition & 1 deletion tests/vm/tinfiniterecursion.nim
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ proc foo(x: int) =
echo "done"
else:
foo(x + 1) #[tt.Error
^ maximum call depth exceeded (2000)]#
^ maximum call depth for the VM exceeded; if you are sure this is not a bug in your code, compile with `--maxCallDepthVM:number` (current value: 2000)]#

static:
foo(1)

0 comments on commit 1e5bc46

Please sign in to comment.