Skip to content

Commit

Permalink
add --experimental:vmopsDanger; add generic conversion for vmops (#…
Browse files Browse the repository at this point in the history
…13813)

* add --experimental:vmopsDanger; vmops cleanups
  • Loading branch information
timotheecour authored Apr 20, 2020
1 parent 77834f0 commit b272031
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 9 deletions.
1 change: 1 addition & 0 deletions compiler/options.nim
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ type
## This requires building nim with `-d:nimHasLibFFI`
## which itself requires `nimble install libffi`, see #10150
## Note: this feature can't be localized with {.push.}
vmopsDanger,

LegacyFeature* = enum
allowSemcheckedAstModification,
Expand Down
41 changes: 41 additions & 0 deletions compiler/vmconv.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import ast

template elementType*(T: typedesc): typedesc =
typeof(block:
var a: T
for ai in a: ai)

proc fromLit*(a: PNode, T: typedesc): auto =
## generic PNode => type
## see also reverse operation `toLit`
when T is set:
result = default(T)
type Ti = elementType(T)
for ai in a:
result.incl Ti(ai.intVal)
else:
static: doAssert false, "not yet supported: " & $T # add as needed

proc toLit*[T](a: T): PNode =
## generic type => PNode
## see also reverse operation `fromLit`
when T is string: newStrNode(nkStrLit, a)
elif T is Ordinal: newIntNode(nkIntLit, a.ord)
elif T is (proc): newNode(nkNilLit)
elif T is ref:
if a == nil: newNode(nkNilLit)
else: toLit(a[])
elif T is tuple:
result = newTree(nkTupleConstr)
for ai in fields(a): result.add toLit(ai)
elif T is object:
result = newTree(nkObjConstr)
result.add(newNode(nkEmpty))
for k, ai in fieldPairs(a):
let reti = newNode(nkExprColonExpr)
reti.add k.toLit
reti.add ai.toLit
result.add reti
else:
static: doAssert false, "not yet supported: " & $T # add as needed

33 changes: 24 additions & 9 deletions compiler/vmops.nim
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ from sighashes import symBodyDigest
from times import cpuTime

from hashes import hash
from osproc import nil

import vmconv

template mathop(op) {.dirty.} =
registerCallback(c, "stdlib.math." & astToStr(op), `op Wrapper`)
Expand Down Expand Up @@ -99,13 +102,12 @@ proc getCurrentExceptionWrapper(a: VmArgs) {.nimcall.} =
proc staticWalkDirImpl(path: string, relative: bool): PNode =
result = newNode(nkBracket)
for k, f in walkDir(path, relative):
result.add newTree(nkTupleConstr, newIntNode(nkIntLit, k.ord),
newStrNode(nkStrLit, f))
result.add toLit((k, f))

when defined(nimHasInvariant):
from std / compilesettings import SingleValueSetting, MultipleValueSetting

proc querySettingImpl(a: VmArgs, conf: ConfigRef, switch: BiggestInt): string =
proc querySettingImpl(conf: ConfigRef, switch: BiggestInt): string =
case SingleValueSetting(switch)
of arguments: result = conf.arguments
of outFile: result = conf.outFile.string
Expand All @@ -120,7 +122,7 @@ when defined(nimHasInvariant):
of compileOptions: result = conf.compileOptions
of ccompilerPath: result = conf.cCompilerPath

proc querySettingSeqImpl(a: VmArgs, conf: ConfigRef, switch: BiggestInt): seq[string] =
proc querySettingSeqImpl(conf: ConfigRef, switch: BiggestInt): seq[string] =
template copySeq(field: untyped): untyped =
for i in field: result.add i.string

Expand All @@ -134,9 +136,9 @@ when defined(nimHasInvariant):

proc registerAdditionalOps*(c: PCtx) =
proc gorgeExWrapper(a: VmArgs) =
let (s, e) = opGorge(getString(a, 0), getString(a, 1), getString(a, 2),
let ret = opGorge(getString(a, 0), getString(a, 1), getString(a, 2),
a.currentLineInfo, c.config)
setResult a, newTree(nkTupleConstr, newStrNode(nkStrLit, s), newIntNode(nkIntLit, e))
setResult a, ret.toLit

proc getProjectPathWrapper(a: VmArgs) =
setResult a, c.config.projectPath.string
Expand Down Expand Up @@ -184,9 +186,9 @@ proc registerAdditionalOps*(c: PCtx) =
setResult(a, staticWalkDirImpl(getString(a, 0), getBool(a, 1)))
when defined(nimHasInvariant):
registerCallback c, "stdlib.compilesettings.querySetting", proc (a: VmArgs) {.nimcall.} =
setResult(a, querySettingImpl(a, c.config, getInt(a, 0)))
setResult(a, querySettingImpl(c.config, getInt(a, 0)))
registerCallback c, "stdlib.compilesettings.querySettingSeq", proc (a: VmArgs) {.nimcall.} =
setResult(a, querySettingSeqImpl(a, c.config, getInt(a, 0)))
setResult(a, querySettingSeqImpl(c.config, getInt(a, 0)))

if defined(nimsuggest) or c.config.cmd == cmdCheck:
discard "don't run staticExec for 'nim suggest'"
Expand Down Expand Up @@ -238,8 +240,21 @@ proc registerAdditionalOps*(c: PCtx) =
registerCallback c, "stdlib.hashes.hashVmImplByte", hashVmImplByte
registerCallback c, "stdlib.hashes.hashVmImplChar", hashVmImplByte

if optBenchmarkVM in c.config.globalOptions:
if optBenchmarkVM in c.config.globalOptions or vmopsDanger in c.config.features:
wrap0(cpuTime, timesop)
else:
proc cpuTime(): float = 5.391245e-44 # Randomly chosen
wrap0(cpuTime, timesop)

if vmopsDanger in c.config.features:
## useful procs but these should be opt-in because they may impact
## reproducible builds and users need to understand that this runs at CT.
## Note that `staticExec` can already do equal amount of damage so it's more
## of a semantic issue than a security issue.
registerCallback c, "stdlib.os.getCurrentDir", proc (a: VmArgs) {.nimcall.} =
setResult(a, os.getCurrentDir())
registerCallback c, "stdlib.osproc.execCmdEx", proc (a: VmArgs) {.nimcall.} =
let options = getNode(a, 1).fromLit(set[osproc.ProcessOption])
a.setResult osproc.execCmdEx(getString(a, 0), options).toLit
registerCallback c, "stdlib.times.getTime", proc (a: VmArgs) {.nimcall.} =
setResult(a, times.getTime().toLit)

0 comments on commit b272031

Please sign in to comment.