Implement deterministic int64 wrapping arithmetic

This commit is contained in:
2026-10-27 16:20:48 +01:00
parent 0e26fc4125
commit 62f81aea89
5 changed files with 813 additions and 314 deletions
+38 -22
View File
@@ -3775,7 +3775,7 @@ Resume:
if(pObj->nType & MEMOBJ_REAL) {
pObj->x.rVal++;
} else {
pObj->x.iVal++;
pObj->x.iVal = PH7_Int64Add(pObj->x.iVal, 1);
}
if(pInstr->iP1) {
/* Pre-increment */
@@ -3788,7 +3788,7 @@ Resume:
if(pTos->nType & MEMOBJ_REAL) {
pTos->x.rVal++;
} else {
pTos->x.iVal++;
pTos->x.iVal = PH7_Int64Add(pTos->x.iVal, 1);
MemObjSetType(pTos, MEMOBJ_INT);
}
}
@@ -3816,7 +3816,7 @@ Resume:
if(pObj->nType & MEMOBJ_REAL) {
pObj->x.rVal--;
} else {
pObj->x.iVal--;
pObj->x.iVal = PH7_Int64Sub(pObj->x.iVal, 1);
}
if(pInstr->iP1) {
/* Pre-decrement */
@@ -3829,7 +3829,7 @@ Resume:
if(pTos->nType & MEMOBJ_REAL) {
pTos->x.rVal--;
} else {
pTos->x.iVal--;
pTos->x.iVal = PH7_Int64Sub(pTos->x.iVal, 1);
MemObjSetType(pTos, MEMOBJ_INT);
}
}
@@ -3854,7 +3854,7 @@ Resume:
pTos->x.rVal = -pTos->x.rVal;
}
if(pTos->nType & MEMOBJ_INT) {
pTos->x.iVal = -pTos->x.iVal;
pTos->x.iVal = PH7_Int64Neg(pTos->x.iVal);
}
break;
/*
@@ -3905,7 +3905,7 @@ Resume:
if((pTos->nType & MEMOBJ_INT) == 0) {
PH7_MemObjToInteger(pTos);
}
pTos->x.iVal = ~pTos->x.iVal;
pTos->x.iVal = PH7_Int64FromUnsigned(~(sxu64)pTos->x.iVal);
break;
/* OP_MUL * * *
* OP_MUL_STORE * * *
@@ -3944,7 +3944,7 @@ Resume:
sxi64 a, b, r;
a = pNos->x.iVal;
b = pTos->x.iVal;
r = a * b;
r = PH7_Int64Mul(a, b);
/* Push the result */
pNos->x.iVal = r;
MemObjSetType(pNos, MEMOBJ_INT);
@@ -4000,7 +4000,23 @@ Resume:
sxi64 a, b, r;
a = pNos->x.iVal;
b = pTos->x.iVal;
r = (sxi64)pow((double)b, (double)a);
/* The parser emits the exponent before the base. */
if(a < 0) {
if(b == 0) {
PH7_VmThrowError(&(*pVm), PH7_CTX_ERR, "Division by zero");
}
r = b == 1 ? 1 : b == -1 ? ((sxu64)a & 1 ? -1 : 1) : 0;
} else {
sxu64 base = (sxu64)b, exponent = (sxu64)a, result = 1;
while(exponent != 0) {
if(exponent & 1) {
result *= base;
}
base *= base;
exponent >>= 1;
}
r = PH7_Int64FromUnsigned(result);
}
/* Push the result */
pNos->x.iVal = r;
MemObjSetType(pNos, MEMOBJ_INT);
@@ -4131,7 +4147,7 @@ Resume:
sxi64 a, b, r;
a = pNos->x.iVal;
b = pTos->x.iVal;
r = a - b;
r = PH7_Int64Sub(a, b);
/* Push the result */
pNos->x.iVal = r;
MemObjSetType(pNos, MEMOBJ_INT);
@@ -4172,7 +4188,7 @@ Resume:
sxi64 a, b, r;
a = pTos->x.iVal;
b = pNos->x.iVal;
r = a - b;
r = PH7_Int64Sub(a, b);
/* Push the result */
pNos->x.iVal = r;
MemObjSetType(pNos, MEMOBJ_INT);
@@ -4217,7 +4233,7 @@ Resume:
if(b == 0) {
PH7_VmThrowError(&(*pVm), PH7_CTX_ERR, "Division by zero %qd%%0", a);
} else {
r = a % b;
r = b == -1 ? 0 : a % b;
}
/* Push the result */
pNos->x.iVal = r;
@@ -4256,7 +4272,7 @@ Resume:
if(b == 0) {
PH7_VmThrowError(&(*pVm), PH7_CTX_ERR, "Division by zero %qd%%0", a);
} else {
r = a % b;
r = b == -1 ? 0 : a % b;
}
/* Push the result */
pNos->x.iVal = r;
@@ -4392,16 +4408,16 @@ Resume:
switch(pInstr->iOp) {
case PH7_OP_BOR_STORE:
case PH7_OP_BOR:
r = a | b;
r = PH7_Int64FromUnsigned((sxu64)a | (sxu64)b);
break;
case PH7_OP_BXOR_STORE:
case PH7_OP_BXOR:
r = a ^ b;
r = PH7_Int64FromUnsigned((sxu64)a ^ (sxu64)b);
break;
case PH7_OP_BAND_STORE:
case PH7_OP_BAND:
default:
r = a & b;
r = PH7_Int64FromUnsigned((sxu64)a & (sxu64)b);
break;
}
/* Push the result */
@@ -4450,16 +4466,16 @@ Resume:
switch(pInstr->iOp) {
case PH7_OP_BOR_STORE:
case PH7_OP_BOR:
r = a | b;
r = PH7_Int64FromUnsigned((sxu64)a | (sxu64)b);
break;
case PH7_OP_BXOR_STORE:
case PH7_OP_BXOR:
r = a ^ b;
r = PH7_Int64FromUnsigned((sxu64)a ^ (sxu64)b);
break;
case PH7_OP_BAND_STORE:
case PH7_OP_BAND:
default:
r = a & b;
r = PH7_Int64FromUnsigned((sxu64)a & (sxu64)b);
break;
}
/* Push the result */
@@ -4506,9 +4522,9 @@ Resume:
a = pNos->x.iVal;
b = (sxi32)pTos->x.iVal;
if(pInstr->iOp == PH7_OP_SHL) {
r = a << b;
r = PH7_Int64FromUnsigned((sxu64)a << b);
} else {
r = a >> b;
r = PH7_Int64ShiftRight(a, b);
}
/* Push the result */
pNos->x.iVal = r;
@@ -4550,9 +4566,9 @@ Resume:
a = pTos->x.iVal;
b = (sxi32)pNos->x.iVal;
if(pInstr->iOp == PH7_OP_SHL_STORE) {
r = a << b;
r = PH7_Int64FromUnsigned((sxu64)a << b);
} else {
r = a >> b;
r = PH7_Int64ShiftRight(a, b);
}
/* Push the result */
pNos->x.iVal = r;