Implemented mSlice on the VM allowing toOpenArray to work at compile time. (#20586)

* Implemented opcSlice to make 'toOpenArray' work on the VM

* Added nkOpenArray for VM to reduce bodgeness

* Fixed range issues and erraneous comments

* Range check correctly for openArrays in opcLdArr

* Inverted logic for ldArr checking

* vm now supports slicing strings

* Added string tests

* Removed usage of 'nkOpenArray' and redundant operations

* Refactored vmSlice implementation, removing redundant and incorrect code

* Made tuples go throw opcWrObj for field assignment

* All strkinds should be considered for openarrays
This commit is contained in:
Jason Beetham 2022-10-20 15:59:57 -06:00 • committed by GitHub
commit 4aa67ad7fd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 204 additions and 30 deletions

View file

@ -640,9 +640,19 @@ proc genCheckedObjAccessAux(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags
proc genAsgnPatch(c: PCtx; le: PNode, value: TRegister) =
case le.kind
of nkBracketExpr:
let dest = c.genx(le[0], {gfNode})
let idx = c.genIndex(le[1], le[0].typ)
c.gABC(le, opcWrArr, dest, idx, value)
let
dest = c.genx(le[0], {gfNode})
idx = c.genIndex(le[1], le[0].typ)
collTyp = le[0].typ.skipTypes(abstractVarRange-{tyTypeDesc})
case collTyp.kind
of tyString, tyCstring:
c.gABC(le, opcWrStrIdx, dest, idx, value)
of tyTuple:
c.gABC(le, opcWrObj, dest, int le[1].intVal, value)
else:
c.gABC(le, opcWrArr, dest, idx, value)
c.freeTemp(dest)
c.freeTemp(idx)
of nkCheckedFieldExpr:
@ -1054,6 +1064,18 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
of tyString: genUnaryABI(c, n, dest, opcLenStr)
of tyCstring: genUnaryABI(c, n, dest, opcLenCstring)
else: doAssert false, $n[1].typ.kind
of mSlice:
var
d = c.genx(n[1])
left = c.genIndex(n[2], n[1].typ)
right = c.genIndex(n[3], n[1].typ)
if dest < 0: dest = c.getTemp(n.typ)
c.gABC(n, opcNodeToReg, dest, d)
c.gABC(n, opcSlice, dest, left, right)
c.freeTemp(left)
c.freeTemp(right)
c.freeTemp(d)
of mIncl, mExcl:
unused(c, n, dest)
var d = c.genx(n[1])
@ -1179,7 +1201,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
var d = c.genx(n[1])
# XXX use ldNullOpcode() here?
c.gABx(n, opcLdNull, d, c.genType(n[1].typ))
c.gABx(n, opcNodeToReg, d, d)
c.gABC(n, opcNodeToReg, d, d)
c.genAsgnPatch(n[1], d)
of mDefault, mZeroDefault:
if dest < 0: dest = c.getTemp(n.typ)
@ -1507,12 +1529,16 @@ proc preventFalseAlias(c: PCtx; n: PNode; opc: TOpcode;
proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) =
case le.kind
of nkBracketExpr:
let dest = c.genx(le[0], {gfNode})
let idx = c.genIndex(le[1], le[0].typ)
let tmp = c.genx(ri)
if le[0].typ.skipTypes(abstractVarRange-{tyTypeDesc}).kind in {
tyString, tyCstring}:
let
dest = c.genx(le[0], {gfNode})
idx = c.genIndex(le[1], le[0].typ)
tmp = c.genx(ri)
collTyp = le[0].typ.skipTypes(abstractVarRange-{tyTypeDesc})
case collTyp.kind
of tyString, tyCstring:
c.preventFalseAlias(le, opcWrStrIdx, dest, idx, tmp)
of tyTuple:
c.preventFalseAlias(le, opcWrObj, dest, int le[1].intVal, tmp)
else:
c.preventFalseAlias(le, opcWrArr, dest, idx, tmp)
c.freeTemp(tmp)
@ -1676,9 +1702,7 @@ proc genArrAccessOpcode(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode;
c.freeTemp(a)
c.freeTemp(b)
proc genObjAccess(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
let a = c.genx(n[0], flags)
let b = genField(c, n[1])
proc genObjAccessAux(c: PCtx; n: PNode; a, b: int, dest: var TDest; flags: TGenFlags) =
if dest < 0: dest = c.getTemp(n.typ)
if {gfNodeAddr} * flags != {}:
c.gABC(n, opcLdObjAddr, dest, a, b)
@ -1691,6 +1715,11 @@ proc genObjAccess(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
c.gABC(n, opcLdObj, dest, a, b)
c.freeTemp(a)
proc genObjAccess(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
genObjAccessAux(c, n, c.genx(n[0], flags), genField(c, n[1]), dest, flags)
proc genCheckedObjAccessAux(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
internalAssert c.config, n.kind == nkCheckedFieldExpr
# nkDotExpr to access the requested field
@ -1758,10 +1787,13 @@ proc genCheckedObjAccess(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
proc genArrAccess(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
let arrayType = n[0].typ.skipTypes(abstractVarRange-{tyTypeDesc}).kind
if arrayType in {tyString, tyCstring}:
case arrayType
of tyString, tyCstring:
let opc = if gfNodeAddr in flags: opcLdStrIdxAddr else: opcLdStrIdx
genArrAccessOpcode(c, n, dest, opc, flags)
elif arrayType == tyTypeDesc:
of tyTuple:
c.genObjAccessAux(n, c.genx(n[0], flags), int n[1].intVal, dest, flags)
of tyTypeDesc:
c.genTypeLit(n.typ, dest)
else:
let opc = if gfNodeAddr in flags: opcLdArrAddr else: opcLdArr