fix getNullValue for cstring in VM, make other VM code aware of nil cstring (#22527)

* fix getNullValue for cstring in VM

fixes #22524

* very ugly fixes, but fix #15730

* nil cstring len works, more test lines

* fix high

(cherry picked from commit 942f846f04)
This commit is contained in:
metagn
2023-08-21 21:08:00 +03:00
committed by narimiran
parent 562fb0d14b
commit 5fa48e97b6
4 changed files with 53 additions and 6 deletions

View File

@@ -1015,7 +1015,10 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
of opcLenCstring:
decodeBImm(rkInt)
assert regs[rb].kind == rkNode
regs[ra].intVal = regs[rb].node.strVal.cstring.len - imm
if regs[rb].node.kind == nkNilLit:
regs[ra].intVal = -imm
else:
regs[ra].intVal = regs[rb].node.strVal.cstring.len - imm
of opcIncl:
decodeB(rkNode)
let b = regs[rb].regToNode
@@ -1213,6 +1216,12 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
of opcEqStr:
decodeBC(rkInt)
regs[ra].intVal = ord(regs[rb].node.strVal == regs[rc].node.strVal)
of opcEqCString:
decodeBC(rkInt)
let bNil = regs[rb].node.kind == nkNilLit
let cNil = regs[rc].node.kind == nkNilLit
regs[ra].intVal = ord((bNil and cNil) or
(not bNil and not cNil and regs[rb].node.strVal == regs[rc].node.strVal))
of opcLeStr:
decodeBC(rkInt)
regs[ra].intVal = ord(regs[rb].node.strVal <= regs[rc].node.strVal)
@@ -1496,7 +1505,13 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
regs[ra].node
c.currentExceptionA = raised
# Set the `name` field of the exception
c.currentExceptionA[2].skipColon.strVal = c.currentExceptionA.typ.sym.name.s
var exceptionNameNode = newStrNode(nkStrLit, c.currentExceptionA.typ.sym.name.s)
if c.currentExceptionA[2].kind == nkExprColonExpr:
exceptionNameNode.typ = c.currentExceptionA[2][1].typ
c.currentExceptionA[2][1] = exceptionNameNode
else:
exceptionNameNode.typ = c.currentExceptionA[2].typ
c.currentExceptionA[2] = exceptionNameNode
c.exceptionInstr = pc
var frame = tos

View File

@@ -99,7 +99,7 @@ type
opcLeFloat, opcLtFloat, opcLeu, opcLtu,
opcEqRef, opcEqNimNode, opcSameNodeType,
opcXor, opcNot, opcUnaryMinusInt, opcUnaryMinusFloat, opcBitnotInt,
opcEqStr, opcLeStr, opcLtStr, opcEqSet, opcLeSet, opcLtSet,
opcEqStr, opcEqCString, opcLeStr, opcLtStr, opcEqSet, opcLeSet, opcLtSet,
opcMulSet, opcPlusSet, opcMinusSet, opcConcatStr,
opcContainsSet, opcRepr, opcSetLenStr, opcSetLenSeq,
opcIsNil, opcOf, opcIs,

View File

@@ -1151,7 +1151,8 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
c.gABC(n, opcNarrowU, dest, TRegister(size*8))
of mCharToStr, mBoolToStr, mIntToStr, mInt64ToStr, mFloatToStr, mCStrToStr, mStrToStr, mEnumToStr:
genConv(c, n, n[1], dest)
of mEqStr, mEqCString: genBinaryABC(c, n, dest, opcEqStr)
of mEqStr: genBinaryABC(c, n, dest, opcEqStr)
of mEqCString: genBinaryABC(c, n, dest, opcEqCString)
of mLeStr: genBinaryABC(c, n, dest, opcLeStr)
of mLtStr: genBinaryABC(c, n, dest, opcLtStr)
of mEqSet: genBinarySet(c, n, dest, opcEqSet)
@@ -1864,10 +1865,10 @@ proc getNullValue(typ: PType, info: TLineInfo; conf: ConfigRef): PNode =
result = newNodeIT(nkUIntLit, info, t)
of tyFloat..tyFloat128:
result = newNodeIT(nkFloatLit, info, t)
of tyCstring, tyString:
of tyString:
result = newNodeIT(nkStrLit, info, t)
result.strVal = ""
of tyVar, tyLent, tyPointer, tyPtr, tyUntyped,
of tyCstring, tyVar, tyLent, tyPointer, tyPtr, tyUntyped,
tyTyped, tyTypeDesc, tyRef, tyNil:
result = newNodeIT(nkNilLit, info, t)
of tyProc:

View File

@@ -733,3 +733,34 @@ block: # bug #22190
tab = mkOpTable(Berlin)
doAssert not tab
block: # issue #22524
const cnst = cstring(nil)
doAssert cnst.isNil
doAssert cnst == nil
let b = cnst
doAssert b.isNil
doAssert b == nil
let a = static: cstring(nil)
doAssert a.isNil
static:
var x: cstring
doAssert x.isNil
doAssert x == nil
doAssert x != ""
block: # issue #15730
const s: cstring = ""
doAssert s != nil
static:
let s: cstring = ""
doAssert not s.isNil
doAssert s != nil
doAssert s == ""
static: # more nil cstring issues
let x = cstring(nil)
doAssert x.len == 0