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());