Add ESSL 3.10 integer math built-ins

This adds built-ins found in ESSL 3.10 section 8.8 Integer functions.

This includes constant folding support for functions that may be
constant folded, and support for both GLSL and HLSL output. In HLSL
several of the functions need to be emulated.

The precision qualification for the return value of some of these
functions is determined by special rules, that are now part of type
promotion for TIntermUnary nodes and determining the type of
TIntermAggregate nodes.

BUG=angleproject:1730
TEST=angle_unittests
TEST=dEQP-GLES31.functional.shaders.builtin_functions.integer.*

Change-Id: Ib0056c17671c42b6496c2f0ef059b99f8f25c122
Reviewed-on: https://chromium-review.googlesource.com/431310
Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/compiler/translator/OutputHLSL.cpp b/src/compiler/translator/OutputHLSL.cpp
index 61ea424..5539a99 100644
--- a/src/compiler/translator/OutputHLSL.cpp
+++ b/src/compiler/translator/OutputHLSL.cpp
@@ -1473,6 +1473,22 @@
         case EOpLogicalNotComponentWise:
             outputTriplet(out, visit, "(!", "", ")");
             break;
+        case EOpBitfieldReverse:
+            outputTriplet(out, visit, "reversebits(", "", ")");
+            break;
+        case EOpBitCount:
+            outputTriplet(out, visit, "countbits(", "", ")");
+            break;
+        case EOpFindLSB:
+            // Note that it's unclear from the HLSL docs what this returns for 0, but this is tested
+            // in GLSLTest and results are consistent with GL.
+            outputTriplet(out, visit, "firstbitlow(", "", ")");
+            break;
+        case EOpFindMSB:
+            // Note that it's unclear from the HLSL docs what this returns for 0 or -1, but this is
+            // tested in GLSLTest and results are consistent with GL.
+            outputTriplet(out, visit, "firstbithigh(", "", ")");
+            break;
         default:
             UNREACHABLE();
     }
@@ -1997,6 +2013,15 @@
         case EOpMulMatrixComponentWise:
             outputTriplet(out, visit, "(", " * ", ")");
             break;
+        case EOpBitfieldExtract:
+        case EOpBitfieldInsert:
+        case EOpUaddCarry:
+        case EOpUsubBorrow:
+        case EOpUmulExtended:
+        case EOpImulExtended:
+            ASSERT(node->getUseEmulatedFunction());
+            writeEmulatedFunctionTriplet(out, visit, node->getOp());
+            break;
         default:
             UNREACHABLE();
     }