Skip to content

Commit

Permalink
fix timotheecour#88 (#13865) [backport:1.2]
Browse files Browse the repository at this point in the history
  • Loading branch information
timotheecour authored Apr 5, 2020
1 parent 8784715 commit f1fd3ef
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 31 deletions.
53 changes: 23 additions & 30 deletions compiler/vm.nim
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,23 @@ const
"if you are sure this is not a bug in your code, compile with `--maxLoopIterationsVM:number` (current value: $1)"
errFieldXNotFound = "node lacks field: "


template maybeHandlePtr(node2: PNode, reg: TFullReg, isAssign2: bool): bool =
let node = node2 # prevent double evaluation
if node.kind == nkNilLit:
stackTrace(c, tos, pc, errNilAccess)
let typ = node.typ
if nfIsPtr in node.flags or (typ != nil and typ.kind == tyPtr):
assert node.kind == nkIntLit, $(node.kind)
assert typ != nil
let typ2 = if typ.kind == tyPtr: typ[0] else: typ
if not derefPtrToReg(node.intVal, typ2, reg, isAssign = isAssign2):
# tyObject not supported in this context
stackTrace(c, tos, pc, "deref unsupported ptr type: " & $(typeToString(typ), typ.kind))
true
else:
false

proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
var pc = start
var tos = tos
Expand Down Expand Up @@ -755,26 +772,12 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
ensureKind(regs[rb].regAddr.kind)
regs[ra] = regs[rb].regAddr[]
of rkNode:
if regs[rb].node.kind == nkNilLit:
stackTrace(c, tos, pc, errNilAccess)
if regs[rb].node.kind == nkRefTy:
regs[ra].node = regs[rb].node[0]
else:
let node = regs[rb].node
let typ = node.typ
# see also `nfIsPtr`
if node.kind == nkIntLit:
var typ2 = typ
doAssert typ != nil
if typ.kind == tyPtr:
typ2 = typ2[0]
if not derefPtrToReg(node.intVal, typ2, regs[ra], isAssign = false):
# tyObject not supported in this context
stackTrace(c, tos, pc, "opcLdDeref unsupported ptr type: " & $(typeToString(typ), typ.kind))
else:
## eg: typ.kind = tyObject
ensureKind(rkNode)
regs[ra].node = regs[rb].node
elif not maybeHandlePtr(regs[rb].node, regs[ra], false):
## eg: typ.kind = tyObject
ensureKind(rkNode)
regs[ra].node = regs[rb].node
else:
stackTrace(c, tos, pc, errNilAccess & " kind: " & $regs[rb].kind)
of opcWrDeref:
Expand All @@ -795,18 +798,8 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
regs[ra].nodeAddr[] = n
of rkRegisterAddr: regs[ra].regAddr[] = regs[rc]
of rkNode:
if regs[ra].node.kind == nkNilLit:
stackTrace(c, tos, pc, errNilAccess)
let node = regs[ra].node
let typ = node.typ
if nfIsPtr in node.flags or (typ != nil and typ.kind == tyPtr):
assert node.kind == nkIntLit, $(node.kind)
var typ2 = typ
if typ.kind == tyPtr:
typ2 = typ2[0]
if not derefPtrToReg(node.intVal, typ2, regs[rc], isAssign = true):
stackTrace(c, tos, pc, "opcWrDeref unsupported ptr type: " & $(typeToString(typ), typ.kind))
else:
# xxx: also check for nkRefTy as in opcLdDeref?
if not maybeHandlePtr(regs[ra].node, regs[rc], true):
regs[ra].node[] = regs[rc].regToNode[]
regs[ra].node.flags.incl nfIsRef
else: stackTrace(c, tos, pc, errNilAccess)
Expand Down
11 changes: 10 additions & 1 deletion tests/vm/tref.nim
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,13 @@ static:
static: # bug #8402
type R = ref object
var empty: R
let otherEmpty = empty
let otherEmpty = empty

block:
# fix https://github.com/timotheecour/Nim/issues/88
template fun() =
var s = @[10,11,12]
var a = s[0].addr
a[] += 100 # was giving SIGSEGV
doAssert a[] == 110
static: fun()

0 comments on commit f1fd3ef

Please sign in to comment.