Commit d061e42b by Alexis Hetu Committed by Alexis Hétu

Added type checking for Mod and bitwise ops

Added type checking and bitwise logic in a few cases for Mod and bitwise operators for TIntermediate, TIntermBinary and TIntermConstantUnion. Change-Id: Ic6ac624fd8d6d9f407f1b8fac40ae31f54a6c7da Reviewed-on: https://swiftshader-review.googlesource.com/3113Tested-by: 's avatarAlexis Hétu <sugoi@google.com> Reviewed-by: 's avatarNicolas Capens <capn@google.com>
parent 4ffc8188
......@@ -177,12 +177,27 @@ TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIn
return 0;
}
break;
case EOpBitwiseOr:
case EOpBitwiseXor:
case EOpBitwiseAnd:
if ((left->getBasicType() != EbtInt && left->getBasicType() != EbtUInt) || left->isMatrix() || left->isArray()) {
return 0;
}
break;
case EOpAdd:
case EOpSub:
case EOpDiv:
case EOpMul:
if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool)
if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool) {
return 0;
}
break;
case EOpIMod:
// Note that this is only for the % operator, not for mod()
if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool || left->getBasicType() == EbtFloat) {
return 0;
}
break;
default: break;
}
......@@ -285,6 +300,12 @@ TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode,
}
switch (op) {
case EOpBitwiseNot:
if ((child->getType().getBasicType() != EbtInt && child->getType().getBasicType() != EbtUInt) || child->getType().isMatrix() || child->getType().isArray()) {
return 0;
}
break;
case EOpLogicalNot:
if (child->getType().getBasicType() != EbtBool || child->getType().isMatrix() || child->getType().isArray() || child->getType().isVector()) {
return 0;
......@@ -659,6 +680,10 @@ bool TIntermUnary::promote(TInfoSink&)
if (operand->getBasicType() != EbtBool)
return false;
break;
case EOpBitwiseNot:
if(operand->getBasicType() != EbtInt && operand->getBasicType() != EbtUInt)
return false;
break;
case EOpNegative:
case EOpPostIncrement:
case EOpPostDecrement:
......@@ -726,13 +751,13 @@ bool TIntermBinary::promote(TInfoSink& infoSink)
getTypePointer()->setQualifier(EvqTemporary);
}
int size = std::max(left->getNominalSize(), right->getNominalSize());
int matrixSize = std::max(left->getSecondarySize(), right->getSecondarySize()); // FIXME: This will have to change for NxM matrices
int primarySize = std::max(left->getNominalSize(), right->getNominalSize());
int secondarySize = std::max(left->getSecondarySize(), right->getSecondarySize());
//
// All scalars. Code after this test assumes this case is removed!
//
if (size == 1) {
if (primarySize == 1) {
switch (op) {
//
// Promote to conditional
......@@ -751,6 +776,7 @@ bool TIntermBinary::promote(TInfoSink& infoSink)
//
case EOpLogicalAnd:
case EOpLogicalOr:
case EOpLogicalXor:
// Both operands must be of type bool.
if (left->getBasicType() != EbtBool || right->getBasicType() != EbtBool)
return false;
......@@ -794,12 +820,12 @@ bool TIntermBinary::promote(TInfoSink& infoSink)
op = EOpVectorTimesMatrix;
else {
op = EOpMatrixTimesScalar;
setType(TType(basicType, higherPrecision, EvqTemporary, size, matrixSize));
setType(TType(basicType, higherPrecision, EvqTemporary, primarySize, secondarySize));
}
} else if (left->isMatrix() && !right->isMatrix()) {
if (right->isVector()) {
op = EOpMatrixTimesVector;
setType(TType(basicType, higherPrecision, EvqTemporary, size, 1));
setType(TType(basicType, higherPrecision, EvqTemporary, primarySize, 1));
} else {
op = EOpMatrixTimesScalar;
}
......@@ -810,7 +836,7 @@ bool TIntermBinary::promote(TInfoSink& infoSink)
// leave as component product
} else if (left->isVector() || right->isVector()) {
op = EOpVectorTimesScalar;
setType(TType(basicType, higherPrecision, EvqTemporary, size, 1));
setType(TType(basicType, higherPrecision, EvqTemporary, primarySize, 1));
}
} else {
infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
......@@ -839,7 +865,7 @@ bool TIntermBinary::promote(TInfoSink& infoSink)
if (! left->isVector())
return false;
op = EOpVectorTimesScalarAssign;
setType(TType(basicType, higherPrecision, EvqTemporary, size, 1));
setType(TType(basicType, higherPrecision, EvqTemporary, primarySize, 1));
}
} else {
infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
......@@ -852,6 +878,12 @@ bool TIntermBinary::promote(TInfoSink& infoSink)
case EOpAdd:
case EOpSub:
case EOpDiv:
case EOpIMod:
case EOpBitShiftLeft:
case EOpBitShiftRight:
case EOpBitwiseAnd:
case EOpBitwiseXor:
case EOpBitwiseOr:
case EOpAddAssign:
case EOpSubAssign:
case EOpDivAssign:
......@@ -864,7 +896,35 @@ bool TIntermBinary::promote(TInfoSink& infoSink)
if ((left->isMatrix() && right->isVector()) ||
(left->isVector() && right->isMatrix()))
return false;
setType(TType(basicType, higherPrecision, EvqTemporary, size, matrixSize));
// Are the sizes compatible?
if(left->getNominalSize() != right->getNominalSize() ||
left->getSecondarySize() != right->getSecondarySize())
{
// If the nominal sizes of operands do not match:
// One of them must be a scalar.
if(!left->isScalar() && !right->isScalar())
return false;
// In the case of compound assignment other than multiply-assign,
// the right side needs to be a scalar. Otherwise a vector/matrix
// would be assigned to a scalar. A scalar can't be shifted by a
// vector either.
if(!right->isScalar() && (modifiesState() || op == EOpBitShiftLeft || op == EOpBitShiftRight))
return false;
}
{
setType(TType(basicType, higherPrecision, EvqTemporary,
static_cast<unsigned char>(primarySize), static_cast<unsigned char>(secondarySize)));
if(left->isArray())
{
ASSERT(left->getArraySize() == right->getArraySize());
type.setArraySize(left->getArraySize());
}
}
setType(TType(basicType, higherPrecision, EvqTemporary, primarySize, secondarySize));
break;
case EOpEqual:
......@@ -1009,35 +1069,50 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
}
break;
case EOpDiv:
case EOpIMod:
tempConstArray = new ConstantUnion[objectSize];
{// support MSVC++6.0
for (int i = 0; i < objectSize; i++) {
switch (getType().getBasicType()) {
case EbtFloat:
if (rightUnionArray[i] == 0.0f) {
infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
tempConstArray[i].setFConst(FLT_MAX);
} else
tempConstArray[i].setFConst(unionArray[i].getFConst() / rightUnionArray[i].getFConst());
break;
case EbtInt:
if (rightUnionArray[i] == 0) {
infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
tempConstArray[i].setIConst(INT_MAX);
} else
tempConstArray[i].setIConst(unionArray[i].getIConst() / rightUnionArray[i].getIConst());
break;
case EbtUInt:
if (rightUnionArray[i] == 0) {
infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
tempConstArray[i].setUConst(UINT_MAX);
} else
tempConstArray[i].setUConst(unionArray[i].getUConst() / rightUnionArray[i].getUConst());
break;
default:
infoSink.info.message(EPrefixInternalError, "Constant folding cannot be done for \"/\"", getLine());
return 0;
case EbtFloat:
if (rightUnionArray[i] == 0.0f) {
infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
tempConstArray[i].setFConst(FLT_MAX);
} else {
ASSERT(op == EOpDiv);
tempConstArray[i].setFConst(unionArray[i].getFConst() / rightUnionArray[i].getFConst());
}
break;
case EbtInt:
if (rightUnionArray[i] == 0) {
infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
tempConstArray[i].setIConst(INT_MAX);
} else {
if(op == EOpDiv) {
tempConstArray[i].setIConst(unionArray[i].getIConst() / rightUnionArray[i].getIConst());
} else {
ASSERT(op == EOpIMod);
tempConstArray[i].setIConst(unionArray[i].getIConst() % rightUnionArray[i].getIConst());
}
}
break;
case EbtUInt:
if (rightUnionArray[i] == 0) {
infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
tempConstArray[i].setUConst(UINT_MAX);
} else {
if(op == EOpDiv) {
tempConstArray[i].setUConst(unionArray[i].getUConst() / rightUnionArray[i].getUConst());
} else {
ASSERT(op == EOpIMod);
tempConstArray[i].setUConst(unionArray[i].getUConst() % rightUnionArray[i].getUConst());
}
}
break;
default:
infoSink.info.message(EPrefixInternalError, "Constant folding cannot be done for \"/\"", getLine());
return 0;
}
}
}
......@@ -1102,12 +1177,38 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
{// support MSVC++6.0
for (int i = 0; i < objectSize; i++)
switch (getType().getBasicType()) {
case EbtBool: tempConstArray[i].setBConst((unionArray[i] == rightUnionArray[i]) ? false : true); break;
default: assert(false && "Default missing");
case EbtBool: tempConstArray[i].setBConst((unionArray[i] == rightUnionArray[i]) ? false : true); break;
default: assert(false && "Default missing");
}
}
break;
case EOpBitwiseAnd:
tempConstArray = new ConstantUnion[objectSize];
for(int i = 0; i < objectSize; i++)
tempConstArray[i] = unionArray[i] & rightUnionArray[i];
break;
case EOpBitwiseXor:
tempConstArray = new ConstantUnion[objectSize];
for(int i = 0; i < objectSize; i++)
tempConstArray[i] = unionArray[i] ^ rightUnionArray[i];
break;
case EOpBitwiseOr:
tempConstArray = new ConstantUnion[objectSize];
for(int i = 0; i < objectSize; i++)
tempConstArray[i] = unionArray[i] | rightUnionArray[i];
break;
case EOpBitShiftLeft:
tempConstArray = new ConstantUnion[objectSize];
for(int i = 0; i < objectSize; i++)
tempConstArray[i] = unionArray[i] << rightUnionArray[i];
break;
case EOpBitShiftRight:
tempConstArray = new ConstantUnion[objectSize];
for(int i = 0; i < objectSize; i++)
tempConstArray[i] = unionArray[i] >> rightUnionArray[i];
break;
case EOpLessThan:
assert(objectSize == 1);
tempConstArray = new ConstantUnion[1];
......@@ -1226,6 +1327,15 @@ TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNod
return 0;
}
break;
case EOpBitwiseNot:
switch(getType().getBasicType()) {
case EbtInt: tempConstArray[i].setIConst(~unionArray[i].getIConst()); break;
case EbtUInt: tempConstArray[i].setUConst(~unionArray[i].getUConst()); break;
default:
infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
return 0;
}
break;
default:
return 0;
}
......
......@@ -749,6 +749,7 @@ unary_expression
switch($1.op) {
case EOpNegative: errorOp = "-"; break;
case EOpLogicalNot: errorOp = "!"; break;
case EOpBitwiseNot: errorOp = "~"; break;
default: break;
}
context->unaryOpError($1.line, errorOp, $2->getCompleteString());
......
......@@ -733,29 +733,29 @@ static const yytype_uint16 yyrline[] =
0, 190, 190, 225, 228, 233, 238, 243, 248, 254,
257, 336, 339, 440, 450, 463, 471, 571, 574, 582,
586, 593, 597, 604, 610, 619, 627, 704, 711, 721,
724, 734, 744, 765, 766, 767, 768, 776, 777, 786,
795, 808, 809, 817, 828, 829, 838, 850, 851, 861,
871, 881, 894, 895, 905, 918, 919, 933, 934, 948,
949, 963, 964, 977, 978, 991, 992, 1005, 1006, 1023,
1024, 1037, 1038, 1039, 1040, 1042, 1043, 1044, 1046, 1048,
1050, 1052, 1057, 1060, 1071, 1079, 1106, 1111, 1121, 1159,
1162, 1169, 1177, 1198, 1219, 1230, 1259, 1264, 1274, 1279,
1289, 1292, 1295, 1298, 1304, 1311, 1314, 1336, 1354, 1378,
1401, 1405, 1423, 1431, 1463, 1483, 1571, 1580, 1603, 1606,
1612, 1618, 1625, 1634, 1643, 1646, 1649, 1656, 1660, 1667,
1671, 1676, 1681, 1687, 1693, 1702, 1712, 1719, 1722, 1725,
1731, 1738, 1741, 1747, 1750, 1753, 1759, 1762, 1777, 1781,
1785, 1789, 1793, 1797, 1802, 1807, 1812, 1817, 1822, 1827,
1832, 1837, 1842, 1847, 1852, 1857, 1863, 1869, 1875, 1881,
1887, 1893, 1899, 1905, 1911, 1916, 1921, 1930, 1935, 1940,
1945, 1950, 1955, 1960, 1965, 1970, 1975, 1980, 1985, 1990,
1995, 2000, 2013, 2013, 2027, 2027, 2036, 2039, 2054, 2086,
2090, 2096, 2104, 2120, 2124, 2128, 2129, 2135, 2136, 2137,
2138, 2139, 2143, 2144, 2144, 2144, 2154, 2155, 2159, 2159,
2160, 2160, 2165, 2168, 2178, 2181, 2187, 2188, 2192, 2200,
2204, 2214, 2219, 2236, 2236, 2241, 2241, 2248, 2248, 2256,
2259, 2265, 2268, 2274, 2278, 2285, 2292, 2299, 2306, 2317,
2326, 2330, 2337, 2340, 2346, 2346
724, 734, 744, 766, 767, 768, 769, 777, 778, 787,
796, 809, 810, 818, 829, 830, 839, 851, 852, 862,
872, 882, 895, 896, 906, 919, 920, 934, 935, 949,
950, 964, 965, 978, 979, 992, 993, 1006, 1007, 1024,
1025, 1038, 1039, 1040, 1041, 1043, 1044, 1045, 1047, 1049,
1051, 1053, 1058, 1061, 1072, 1080, 1107, 1112, 1122, 1160,
1163, 1170, 1178, 1199, 1220, 1231, 1260, 1265, 1275, 1280,
1290, 1293, 1296, 1299, 1305, 1312, 1315, 1337, 1355, 1379,
1402, 1406, 1424, 1432, 1464, 1484, 1572, 1581, 1604, 1607,
1613, 1619, 1626, 1635, 1644, 1647, 1650, 1657, 1661, 1668,
1672, 1677, 1682, 1688, 1694, 1703, 1713, 1720, 1723, 1726,
1732, 1739, 1742, 1748, 1751, 1754, 1760, 1763, 1778, 1782,
1786, 1790, 1794, 1798, 1803, 1808, 1813, 1818, 1823, 1828,
1833, 1838, 1843, 1848, 1853, 1858, 1864, 1870, 1876, 1882,
1888, 1894, 1900, 1906, 1912, 1917, 1922, 1931, 1936, 1941,
1946, 1951, 1956, 1961, 1966, 1971, 1976, 1981, 1986, 1991,
1996, 2001, 2014, 2014, 2028, 2028, 2037, 2040, 2055, 2087,
2091, 2097, 2105, 2121, 2125, 2129, 2130, 2136, 2137, 2138,
2139, 2140, 2144, 2145, 2145, 2145, 2155, 2156, 2160, 2160,
2161, 2161, 2166, 2169, 2179, 2182, 2188, 2189, 2193, 2201,
2205, 2215, 2220, 2237, 2237, 2242, 2242, 2249, 2249, 2257,
2260, 2266, 2269, 2275, 2279, 2286, 2293, 2300, 2307, 2318,
2327, 2331, 2338, 2341, 2347, 2347
};
#endif
......@@ -2950,6 +2950,7 @@ yyreduce:
switch((yyvsp[(1) - (2)].interm).op) {
case EOpNegative: errorOp = "-"; break;
case EOpLogicalNot: errorOp = "!"; break;
case EOpBitwiseNot: errorOp = "~"; break;
default: break;
}
context->unaryOpError((yyvsp[(1) - (2)].interm).line, errorOp, (yyvsp[(2) - (2)].interm.intermTypedNode)->getCompleteString());
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment