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