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/3113
Tested-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <capn@google.com>
diff --git a/src/OpenGL/compiler/Intermediate.cpp b/src/OpenGL/compiler/Intermediate.cpp
index 7f056fb..fad11c6 100644
--- a/src/OpenGL/compiler/Intermediate.cpp
+++ b/src/OpenGL/compiler/Intermediate.cpp
@@ -177,12 +177,27 @@
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 @@
}
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 @@
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 @@
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 @@
//
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 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
}
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 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
- 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 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 @@
{// 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 @@
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;
}
diff --git a/src/OpenGL/compiler/glslang.y b/src/OpenGL/compiler/glslang.y
index 9fba3a7..0dff1c9 100644
--- a/src/OpenGL/compiler/glslang.y
+++ b/src/OpenGL/compiler/glslang.y
@@ -749,6 +749,7 @@
switch($1.op) {
case EOpNegative: errorOp = "-"; break;
case EOpLogicalNot: errorOp = "!"; break;
+ case EOpBitwiseNot: errorOp = "~"; break;
default: break;
}
context->unaryOpError($1.line, errorOp, $2->getCompleteString());
diff --git a/src/OpenGL/compiler/glslang_tab.cpp b/src/OpenGL/compiler/glslang_tab.cpp
index d73a1f4..a672362 100644
--- a/src/OpenGL/compiler/glslang_tab.cpp
+++ b/src/OpenGL/compiler/glslang_tab.cpp
@@ -733,29 +733,29 @@
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 @@
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());