fix #21045; getTime with vmopsDanger is broken; alternative to #21054 (#21056)

* fix #21045 getTime with vmopsDanger is broken; alternative to #21054

* typo
This commit is contained in:
ringabout 2022-12-11 01:57:19 +08:00 • committed by GitHub
commit 07be1791ba
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 51 additions and 22 deletions

View file

@ -3283,6 +3283,7 @@ proc getNullValueAux(p: BProc; t: PType; obj, constOrNil: PNode,
if constOrNil != nil: if constOrNil != nil:
for i in 1..<constOrNil.len: for i in 1..<constOrNil.len:
if constOrNil[i].kind == nkExprColonExpr: if constOrNil[i].kind == nkExprColonExpr:
assert constOrNil[i][0].kind == nkSym, "illformed object constr; the field is not a sym"
if constOrNil[i][0].sym.name.id == field.name.id: if constOrNil[i][0].sym.name.id == field.name.id:
genBracedInit(p, constOrNil[i][1], isConst, field.typ, result) genBracedInit(p, constOrNil[i][1], isConst, field.typ, result)
return return

View file

@ -1,4 +1,6 @@
import ast import ast, idents, lineinfos, astalgo
import vmdef
import std/times
template elementType*(T: typedesc): typedesc = template elementType*(T: typedesc): typedesc =
typeof(block: typeof(block:
@ -43,3 +45,12 @@ proc toLit*[T](a: T): PNode =
else: else:
static: doAssert false, "not yet supported: " & $T # add as needed static: doAssert false, "not yet supported: " & $T # add as needed
proc toTimeLit*(a: Time, c: PCtx, obj: PNode, info: TLineInfo): PNode =
# probably refactor it into `toLit` in the future
result = newTree(nkObjConstr)
result.add(newNode(nkEmpty)) # can be changed to a symbol according to PType
for k, ai in fieldPairs(a):
let reti = newNode(nkExprColonExpr)
reti.add newSymNode(lookupInRecord(obj, getIdent(c.cache, k)), info)
reti.add ai.toLit
result.add reti

View file

@ -328,8 +328,9 @@ proc registerAdditionalOps*(c: PCtx) =
registerCallback c, "stdlib.osproc.execCmdEx", proc (a: VmArgs) {.nimcall.} = registerCallback c, "stdlib.osproc.execCmdEx", proc (a: VmArgs) {.nimcall.} =
let options = getNode(a, 1).fromLit(set[osproc.ProcessOption]) let options = getNode(a, 1).fromLit(set[osproc.ProcessOption])
a.setResult osproc.execCmdEx(getString(a, 0), options).toLit a.setResult osproc.execCmdEx(getString(a, 0), options).toLit
registerCallback c, "stdlib.times.getTime", proc (a: VmArgs) {.nimcall.} = registerCallback c, "stdlib.times.getTimeImpl", proc (a: VmArgs) =
setResult(a, times.getTime().toLit) let obj = a.getNode(0).typ.n
setResult(a, times.getTime().toTimeLit(c, obj, a.currentLineInfo))
proc getEffectList(c: PCtx; a: VmArgs; effectIndex: int) = proc getEffectList(c: PCtx; a: VmArgs; effectIndex: int) =
let fn = getNode(a, 0) let fn = getNode(a, 0)

View file

@ -953,27 +953,33 @@ proc toWinTime*(t: Time): int64 =
## since `1601-01-01T00:00:00Z`). ## since `1601-01-01T00:00:00Z`).
result = t.seconds * rateDiff + epochDiff + t.nanosecond div 100 result = t.seconds * rateDiff + epochDiff + t.nanosecond div 100
proc getTimeImpl(typ: typedesc[Time]): Time =
discard "implemented in the vm"
proc getTime*(): Time {.tags: [TimeEffect], benign.} = proc getTime*(): Time {.tags: [TimeEffect], benign.} =
## Gets the current time as a `Time` with up to nanosecond resolution. ## Gets the current time as a `Time` with up to nanosecond resolution.
when defined(js): when nimvm:
let millis = newDate().getTime() result = getTimeImpl(Time)
let seconds = convert(Milliseconds, Seconds, millis) else:
let nanos = convert(Milliseconds, Nanoseconds, when defined(js):
millis mod convert(Seconds, Milliseconds, 1).int) let millis = newDate().getTime()
result = initTime(seconds, nanos) let seconds = convert(Milliseconds, Seconds, millis)
elif defined(macosx): let nanos = convert(Milliseconds, Nanoseconds,
var a {.noinit.}: Timeval millis mod convert(Seconds, Milliseconds, 1).int)
gettimeofday(a) result = initTime(seconds, nanos)
result = initTime(a.tv_sec.int64, elif defined(macosx):
convert(Microseconds, Nanoseconds, a.tv_usec.int)) var a {.noinit.}: Timeval
elif defined(posix): gettimeofday(a)
var ts {.noinit.}: Timespec result = initTime(a.tv_sec.int64,
discard clock_gettime(CLOCK_REALTIME, ts) convert(Microseconds, Nanoseconds, a.tv_usec.int))
result = initTime(ts.tv_sec.int64, ts.tv_nsec.int) elif defined(posix):
elif defined(windows): var ts {.noinit.}: Timespec
var f {.noinit.}: FILETIME discard clock_gettime(CLOCK_REALTIME, ts)
getSystemTimeAsFileTime(f) result = initTime(ts.tv_sec.int64, ts.tv_nsec.int)
result = fromWinTime(rdFileTime(f)) elif defined(windows):
var f {.noinit.}: FILETIME
getSystemTimeAsFileTime(f)
result = fromWinTime(rdFileTime(f))
proc `-`*(a, b: Time): Duration {.operator, extern: "ntDiffTime".} = proc `-`*(a, b: Time): Duration {.operator, extern: "ntDiffTime".} =
## Computes the duration between two points in time. ## Computes the duration between two points in time.

10
tests/vm/tvmopsDanger.nim Normal file
View file

@ -0,0 +1,10 @@
discard """
cmd: "nim c --experimental:vmopsDanger -r $file"
"""
when defined(nimPreviewSlimSystem):
import std/assertions
import std/times
const foo = getTime()
let bar = foo
doAssert bar > low(Time)