diff options
author | Timothee Cour <timothee.cour2@gmail.com> | 2020-04-20 03:00:00 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-04-20 12:00:00 +0200 |
commit | b2720317fa3b31aed298398696124b439fcfa907 (patch) | |
tree | 75808f47b701c00355ca187971890aaadc88a0b2 | |
parent | 77834f0fdabc9d39cf111c4c94e717bd2c4f00d2 (diff) | |
download | Nim-b2720317fa3b31aed298398696124b439fcfa907.tar.gz |
add `--experimental:vmopsDanger`; add generic conversion for vmops (#13813)
* add --experimental:vmopsDanger; vmops cleanups
-rw-r--r-- | compiler/options.nim | 1 | ||||
-rw-r--r-- | compiler/vmconv.nim | 41 | ||||
-rw-r--r-- | compiler/vmops.nim | 33 |
3 files changed, 66 insertions, 9 deletions
diff --git a/compiler/options.nim b/compiler/options.nim index 813d2d6e5..b9aca23a1 100644 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -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, diff --git a/compiler/vmconv.nim b/compiler/vmconv.nim new file mode 100644 index 000000000..7db3906c2 --- /dev/null +++ b/compiler/vmconv.nim @@ -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 + diff --git a/compiler/vmops.nim b/compiler/vmops.nim index 0ee137178..ef36419a7 100644 --- a/compiler/vmops.nim +++ b/compiler/vmops.nim @@ -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`) @@ -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 @@ -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 @@ -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 @@ -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'" @@ -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) |