Fix seq.setLen initialisation in VM (#6224)
This commit is contained in:
parent
6ce6883fad
commit
0861249de7
3 changed files with 90 additions and 8 deletions
|
|
@ -2315,6 +2315,15 @@ proc genConstExpr(p: BProc, n: PNode): Rope =
|
||||||
var t = skipTypes(n.typ, abstractInst)
|
var t = skipTypes(n.typ, abstractInst)
|
||||||
if t.kind == tySequence:
|
if t.kind == tySequence:
|
||||||
result = genConstSeq(p, n, n.typ)
|
result = genConstSeq(p, n, n.typ)
|
||||||
|
elif t.kind == tyProc and t.callConv == ccClosure and not n.sons.isNil and
|
||||||
|
n.sons[0].kind == nkNilLit and n.sons[1].kind == nkNilLit:
|
||||||
|
# this hack fixes issue that nkNilLit is expanded to {NIM_NIL,NIM_NIL}
|
||||||
|
# this behaviour is needed since closure_var = nil must be
|
||||||
|
# expanded to {NIM_NIL,NIM_NIL}
|
||||||
|
# in VM closures are initialized with nkPar(nkNilLit, nkNilLit)
|
||||||
|
# leading to duplicate code like this:
|
||||||
|
# "{NIM_NIL,NIM_NIL}, {NIM_NIL,NIM_NIL}"
|
||||||
|
result = ~"{NIM_NIL,NIM_NIL}"
|
||||||
else:
|
else:
|
||||||
result = genConstSimpleList(p, n)
|
result = genConstSimpleList(p, n)
|
||||||
of nkObjConstr:
|
of nkObjConstr:
|
||||||
|
|
|
||||||
|
|
@ -409,6 +409,28 @@ proc recSetFlagIsRef(arg: PNode) =
|
||||||
for i in 0 ..< arg.safeLen:
|
for i in 0 ..< arg.safeLen:
|
||||||
arg.sons[i].recSetFlagIsRef
|
arg.sons[i].recSetFlagIsRef
|
||||||
|
|
||||||
|
proc setLenSeq(c: PCtx; node: PNode; newLen: int; info: TLineInfo) =
|
||||||
|
# FIXME: this doesn't attempt to solve incomplete
|
||||||
|
# support of tyPtr, tyRef in VM.
|
||||||
|
let typ = node.typ.skipTypes(abstractInst+{tyRange}-{tyTypeDesc})
|
||||||
|
let typeEntry = typ.sons[0].skipTypes(abstractInst+{tyRange}-{tyTypeDesc})
|
||||||
|
let typeKind = case typeEntry.kind
|
||||||
|
of tyUInt..tyUInt64: nkUIntLit
|
||||||
|
of tyRange, tyEnum, tyBool, tyChar, tyInt..tyInt64: nkIntLit
|
||||||
|
of tyFloat..tyFloat128: nkFloatLit
|
||||||
|
of tyString: nkStrLit
|
||||||
|
of tyObject: nkObjConstr
|
||||||
|
of tySequence: nkNilLit
|
||||||
|
of tyProc, tyTuple: nkPar
|
||||||
|
else: nkEmpty
|
||||||
|
|
||||||
|
let oldLen = node.len
|
||||||
|
setLen(node.sons, newLen)
|
||||||
|
if oldLen < newLen:
|
||||||
|
# TODO: This is still not correct for tyPtr, tyRef default value
|
||||||
|
for i in oldLen .. <newLen:
|
||||||
|
node.sons[i] = newNodeI(typeKind, info)
|
||||||
|
|
||||||
proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
||||||
var pc = start
|
var pc = start
|
||||||
var tos = tos
|
var tos = tos
|
||||||
|
|
@ -1118,14 +1140,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
||||||
decodeB(rkNode)
|
decodeB(rkNode)
|
||||||
let newLen = regs[rb].intVal.int
|
let newLen = regs[rb].intVal.int
|
||||||
if regs[ra].node.isNil: stackTrace(c, tos, pc, errNilAccess)
|
if regs[ra].node.isNil: stackTrace(c, tos, pc, errNilAccess)
|
||||||
else:
|
else: c.setLenSeq(regs[ra].node, newLen, c.debug[pc])
|
||||||
let oldLen = regs[ra].node.len
|
|
||||||
setLen(regs[ra].node.sons, newLen)
|
|
||||||
if oldLen < newLen:
|
|
||||||
# XXX This is still not entirely correct
|
|
||||||
# set to default value:
|
|
||||||
for i in oldLen .. <newLen:
|
|
||||||
regs[ra].node.sons[i] = newNodeI(nkEmpty, c.debug[pc])
|
|
||||||
of opcReset:
|
of opcReset:
|
||||||
internalError(c.debug[pc], "too implement")
|
internalError(c.debug[pc], "too implement")
|
||||||
of opcNarrowS:
|
of opcNarrowS:
|
||||||
|
|
|
||||||
58
tests/vm/tseq_badinit.nim
Normal file
58
tests/vm/tseq_badinit.nim
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
|
||||||
|
type
|
||||||
|
AObj = object
|
||||||
|
i: int
|
||||||
|
d: float
|
||||||
|
ATup = tuple
|
||||||
|
i: int
|
||||||
|
d: float
|
||||||
|
MyEnum = enum
|
||||||
|
E01, E02, E03
|
||||||
|
Myrange = range[0..10]
|
||||||
|
|
||||||
|
MyProc = proc (x: int): bool
|
||||||
|
MyInt = distinct int
|
||||||
|
MyAlias = MyInt
|
||||||
|
MySet = set[char]
|
||||||
|
MyArray = array[4, char]
|
||||||
|
MySeq = seq[string]
|
||||||
|
|
||||||
|
template test(typename, default: untyped) =
|
||||||
|
proc `abc typename`(): seq[typename] =
|
||||||
|
result = newSeq[typename]()
|
||||||
|
result.add(default)
|
||||||
|
result.setLen(3)
|
||||||
|
for i in 0 .. <2:
|
||||||
|
result[i] = default
|
||||||
|
|
||||||
|
const constval = `abc typename`()
|
||||||
|
doAssert(constval == `abc typename`())
|
||||||
|
|
||||||
|
proc `arr typename`(): array[4, typename] =
|
||||||
|
for i in 0 .. <2:
|
||||||
|
result[i] = default
|
||||||
|
const constarr = `arr typename`()
|
||||||
|
doAssert(constarr == `arr typename`())
|
||||||
|
|
||||||
|
proc even(x: int): bool = x mod 2 == 0
|
||||||
|
proc `==`(x, y: MyInt): bool = ord(x) == ord(y)
|
||||||
|
proc `$`(x: MyInt): string = $ord(x)
|
||||||
|
proc `$`(x: proc): string =
|
||||||
|
if x.isNil: "(nil)" else: "funcptr"
|
||||||
|
|
||||||
|
test(int, 0)
|
||||||
|
test(uint, 0)
|
||||||
|
test(float, 0.1)
|
||||||
|
test(char, '0')
|
||||||
|
test(bool, false)
|
||||||
|
test(uint8, 2)
|
||||||
|
test(string, "data")
|
||||||
|
test(MyProc, even)
|
||||||
|
test(MyEnum, E02)
|
||||||
|
test(AObj, AObj())
|
||||||
|
test(ATup, (i:11, d:9.99))
|
||||||
|
test(Myrange, 4)
|
||||||
|
test(MyInt, MyInt(4))
|
||||||
|
test(MyAlias, MyAlias(4))
|
||||||
|
test(MyArray, ['0','1','2','3'])
|
||||||
|
test(MySeq, @["data"])
|
||||||
Loading…
Add table
Add a link
Reference in a new issue