Merge mozilla-central to autoland. a=merge CLOSED TREE
authorBogdan Tara <btara@mozilla.com>
Tue, 05 Jun 2018 12:33:18 +0300
changeset 475562 752465b44c793318cef36df46ca5ff00c3d8854a
parent 475561 b8a579ca9dd2a0f865710c4d8c27b0f9c61f029f (current diff)
parent 475493 a358755643e92f8fc55a23e3ab1fbf88695b8bf3 (diff)
child 475563 7910d46af606344992f232d710794e5a7c686daa
push id9374
push userjlund@mozilla.com
push dateMon, 18 Jun 2018 21:43:20 +0000
treeherdermozilla-beta@160e085dfb0b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone62.0a1
first release with
nightly linux32
752465b44c79 / 62.0a1 / 20180605141053 / files
nightly linux64
752465b44c79 / 62.0a1 / 20180605141053 / files
nightly mac
752465b44c79 / 62.0a1 / 20180605141053 / files
nightly win32
752465b44c79 / 62.0a1 / 20180605141053 / files
nightly win64
752465b44c79 / 62.0a1 / 20180605141053 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge mozilla-central to autoland. a=merge CLOSED TREE
devtools/shared/css/generated/properties-db.js
dom/interfaces/geolocation/nsIDOMGeoGeolocation.idl
gfx/angle/checkout/src/compiler/translator/AddAndTrueToLoopCondition.cpp
gfx/angle/checkout/src/compiler/translator/AddAndTrueToLoopCondition.h
gfx/angle/checkout/src/compiler/translator/AddDefaultReturnStatements.cpp
gfx/angle/checkout/src/compiler/translator/AddDefaultReturnStatements.h
gfx/angle/checkout/src/compiler/translator/ArrayReturnValueToOutParameter.cpp
gfx/angle/checkout/src/compiler/translator/ArrayReturnValueToOutParameter.h
gfx/angle/checkout/src/compiler/translator/BreakVariableAliasingInInnerLoops.cpp
gfx/angle/checkout/src/compiler/translator/BreakVariableAliasingInInnerLoops.h
gfx/angle/checkout/src/compiler/translator/ClampFragDepth.cpp
gfx/angle/checkout/src/compiler/translator/ClampFragDepth.h
gfx/angle/checkout/src/compiler/translator/ClampPointSize.cpp
gfx/angle/checkout/src/compiler/translator/ClampPointSize.h
gfx/angle/checkout/src/compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.cpp
gfx/angle/checkout/src/compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.h
gfx/angle/checkout/src/compiler/translator/DeferGlobalInitializers.cpp
gfx/angle/checkout/src/compiler/translator/DeferGlobalInitializers.h
gfx/angle/checkout/src/compiler/translator/EmulateGLFragColorBroadcast.cpp
gfx/angle/checkout/src/compiler/translator/EmulateGLFragColorBroadcast.h
gfx/angle/checkout/src/compiler/translator/EmulatePrecision.cpp
gfx/angle/checkout/src/compiler/translator/EmulatePrecision.h
gfx/angle/checkout/src/compiler/translator/ExpandIntegerPowExpressions.cpp
gfx/angle/checkout/src/compiler/translator/ExpandIntegerPowExpressions.h
gfx/angle/checkout/src/compiler/translator/FindMain.cpp
gfx/angle/checkout/src/compiler/translator/FindMain.h
gfx/angle/checkout/src/compiler/translator/FindSymbolNode.cpp
gfx/angle/checkout/src/compiler/translator/FindSymbolNode.h
gfx/angle/checkout/src/compiler/translator/FoldExpressions.cpp
gfx/angle/checkout/src/compiler/translator/FoldExpressions.h
gfx/angle/checkout/src/compiler/translator/InitializeVariables.cpp
gfx/angle/checkout/src/compiler/translator/InitializeVariables.h
gfx/angle/checkout/src/compiler/translator/IntermNodePatternMatcher.cpp
gfx/angle/checkout/src/compiler/translator/IntermNodePatternMatcher.h
gfx/angle/checkout/src/compiler/translator/IntermNode_util.cpp
gfx/angle/checkout/src/compiler/translator/IntermNode_util.h
gfx/angle/checkout/src/compiler/translator/IntermTraverse.cpp
gfx/angle/checkout/src/compiler/translator/IntermTraverse.h
gfx/angle/checkout/src/compiler/translator/NodeSearch.h
gfx/angle/checkout/src/compiler/translator/ParamType.h
gfx/angle/checkout/src/compiler/translator/PruneNoOps.cpp
gfx/angle/checkout/src/compiler/translator/PruneNoOps.h
gfx/angle/checkout/src/compiler/translator/RecordConstantPrecision.cpp
gfx/angle/checkout/src/compiler/translator/RecordConstantPrecision.h
gfx/angle/checkout/src/compiler/translator/RegenerateStructNames.cpp
gfx/angle/checkout/src/compiler/translator/RegenerateStructNames.h
gfx/angle/checkout/src/compiler/translator/RemoveArrayLengthMethod.cpp
gfx/angle/checkout/src/compiler/translator/RemoveArrayLengthMethod.h
gfx/angle/checkout/src/compiler/translator/RemoveDynamicIndexing.cpp
gfx/angle/checkout/src/compiler/translator/RemoveDynamicIndexing.h
gfx/angle/checkout/src/compiler/translator/RemoveEmptySwitchStatements.cpp
gfx/angle/checkout/src/compiler/translator/RemoveEmptySwitchStatements.h
gfx/angle/checkout/src/compiler/translator/RemoveInvariantDeclaration.cpp
gfx/angle/checkout/src/compiler/translator/RemoveInvariantDeclaration.h
gfx/angle/checkout/src/compiler/translator/RemoveNoOpCasesFromEndOfSwitchStatements.cpp
gfx/angle/checkout/src/compiler/translator/RemoveNoOpCasesFromEndOfSwitchStatements.h
gfx/angle/checkout/src/compiler/translator/RemovePow.cpp
gfx/angle/checkout/src/compiler/translator/RemovePow.h
gfx/angle/checkout/src/compiler/translator/RemoveSwitchFallThrough.cpp
gfx/angle/checkout/src/compiler/translator/RemoveSwitchFallThrough.h
gfx/angle/checkout/src/compiler/translator/RemoveUnreferencedVariables.cpp
gfx/angle/checkout/src/compiler/translator/RemoveUnreferencedVariables.h
gfx/angle/checkout/src/compiler/translator/ReplaceVariable.cpp
gfx/angle/checkout/src/compiler/translator/ReplaceVariable.h
gfx/angle/checkout/src/compiler/translator/RewriteDoWhile.cpp
gfx/angle/checkout/src/compiler/translator/RewriteDoWhile.h
gfx/angle/checkout/src/compiler/translator/RewriteElseBlocks.cpp
gfx/angle/checkout/src/compiler/translator/RewriteElseBlocks.h
gfx/angle/checkout/src/compiler/translator/RewriteTexelFetchOffset.cpp
gfx/angle/checkout/src/compiler/translator/RewriteTexelFetchOffset.h
gfx/angle/checkout/src/compiler/translator/RewriteUnaryMinusOperatorFloat.cpp
gfx/angle/checkout/src/compiler/translator/RewriteUnaryMinusOperatorFloat.h
gfx/angle/checkout/src/compiler/translator/RewriteUnaryMinusOperatorInt.cpp
gfx/angle/checkout/src/compiler/translator/RewriteUnaryMinusOperatorInt.h
gfx/angle/checkout/src/compiler/translator/RunAtTheEndOfShader.cpp
gfx/angle/checkout/src/compiler/translator/RunAtTheEndOfShader.h
gfx/angle/checkout/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp
gfx/angle/checkout/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h
gfx/angle/checkout/src/compiler/translator/SeparateArrayConstructorStatements.cpp
gfx/angle/checkout/src/compiler/translator/SeparateArrayConstructorStatements.h
gfx/angle/checkout/src/compiler/translator/SeparateArrayInitialization.cpp
gfx/angle/checkout/src/compiler/translator/SeparateArrayInitialization.h
gfx/angle/checkout/src/compiler/translator/SeparateDeclarations.cpp
gfx/angle/checkout/src/compiler/translator/SeparateDeclarations.h
gfx/angle/checkout/src/compiler/translator/SeparateExpressionsReturningArrays.cpp
gfx/angle/checkout/src/compiler/translator/SeparateExpressionsReturningArrays.h
gfx/angle/checkout/src/compiler/translator/SimplifyLoopConditions.cpp
gfx/angle/checkout/src/compiler/translator/SimplifyLoopConditions.h
gfx/angle/checkout/src/compiler/translator/SplitSequenceOperator.cpp
gfx/angle/checkout/src/compiler/translator/SplitSequenceOperator.h
gfx/angle/checkout/src/compiler/translator/StaticType.cpp
gfx/angle/checkout/src/compiler/translator/UnfoldShortCircuitAST.cpp
gfx/angle/checkout/src/compiler/translator/UnfoldShortCircuitAST.h
gfx/angle/checkout/src/compiler/translator/UnfoldShortCircuitToIf.cpp
gfx/angle/checkout/src/compiler/translator/UnfoldShortCircuitToIf.h
gfx/angle/checkout/src/compiler/translator/UseInterfaceBlockFields.cpp
gfx/angle/checkout/src/compiler/translator/UseInterfaceBlockFields.h
gfx/angle/checkout/src/compiler/translator/VectorizeVectorScalarArithmetic.cpp
gfx/angle/checkout/src/compiler/translator/VectorizeVectorScalarArithmetic.h
gfx/angle/checkout/src/compiler/translator/WrapSwitchStatementsInBlocks.cpp
gfx/angle/checkout/src/compiler/translator/WrapSwitchStatementsInBlocks.h
gfx/angle/checkout/src/libANGLE/signal_utils.cpp
gfx/angle/checkout/src/libANGLE/signal_utils.h
gfx/angle/cherries.log
gfx/layers/ipc/CompositorBridgeParent.cpp
modules/brotli/dec/context.h
modules/brotli/dec/port.h
modules/brotli/dec/transform.h
modules/brotli/enc/context.h
modules/brotli/enc/port.h
testing/mozharness/scripts/mobile_partner_repack.py
testing/web-platform/meta/FileAPI/file/send-file-form-iso-2022-jp.tentative.html.ini
testing/web-platform/meta/FileAPI/file/send-file-form-utf-8.html.ini
testing/web-platform/meta/FileAPI/file/send-file-form-windows-1252.tentative.html.ini
testing/web-platform/meta/FileAPI/file/send-file-form-x-user-defined.tentative.html.ini
testing/web-platform/meta/FileAPI/file/send-file-form.html.ini
testing/web-platform/meta/MANIFEST.json
testing/web-platform/meta/css/css-fonts/font-display/font-display-failure-fallback.html.ini
testing/web-platform/meta/css/css-fonts/variations/font-weight-matching.html.ini
testing/web-platform/meta/html/editing/dnd/datastore/datatransfer-constructor-001.html.ini
testing/web-platform/meta/html/editing/dnd/datastore/datatransfer-types.html.ini
testing/web-platform/meta/html/semantics/forms/form-submission-0/submit-file.sub.html.ini
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1134,17 +1134,17 @@ name = "malloc_size_of"
 version = "0.0.1"
 dependencies = [
  "app_units 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "cssparser 0.23.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "euclid 0.17.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "hashglobe 0.1.0",
  "selectors 0.19.0",
  "servo_arc 0.1.1",
- "smallbitvec 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "smallbitvec 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "malloc_size_of_derive"
 version = "0.0.1"
 dependencies = [
@@ -1844,17 +1844,17 @@ version = "0.0.1"
 
 [[package]]
 name = "slab"
 version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "smallbitvec"
-version = "2.1.0"
+version = "2.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
 name = "smallvec"
 version = "0.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
@@ -1929,17 +1929,17 @@ dependencies = [
  "ordered-float 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "precomputed-hash 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "rayon 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
  "selectors 0.19.0",
  "servo_arc 0.1.1",
- "smallbitvec 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "smallbitvec 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "style_derive 0.0.1",
  "style_traits 0.0.1",
  "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)",
  "toml 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
  "uluru 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2673,17 +2673,17 @@ dependencies = [
 "checksum semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3186ec9e65071a2095434b1f5bb24838d4e8e130f584c790f6033c79943537"
 "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
 "checksum serde 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)" = "34e9df8efbe7a2c12ceec1fc8744d56ae3374d8ae325f4a0028949d16433d554"
 "checksum serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)" = "adb6e51a6b3696b301bc221d785f898b4457c619b51d7ce195a6d20baecb37b3"
 "checksum serde_derive 1.0.58 (git+https://github.com/servo/serde?branch=deserialize_from_enums7)" = "<none>"
 "checksum simd 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3dd0805c7363ab51a829a1511ad24b6ed0349feaa756c4bc2f977f9f496e6673"
 "checksum siphasher 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2ffc669b726f2bc9a3bcff66e5e23b56ba6bf70e22a34c3d7b6d0b3450b65b84"
 "checksum slab 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "17b4fcaed89ab08ef143da37bc52adbcc04d4a69014f4c1208d6b51f0c47bc23"
-"checksum smallbitvec 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "665fbc8384f961eb55c548daa2a4b1efff1f9d03b7a10f162ac6ad6a781ca966"
+"checksum smallbitvec 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c63726029f0069f88467873e47f392575f28f9f16b72ac65465263db4b3a13c"
 "checksum smallvec 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44db0ecb22921ef790d17ae13a3f6d15784183ff5f2a01aa32098c7498d2b4b9"
 "checksum stable_deref_trait 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "15132e0e364248108c5e2c02e3ab539be8d6f5d52a01ca9bbf27ed657316f02b"
 "checksum string_cache 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39cb4173bcbd1319da31faa5468a7e3870683d7a237150b0b0aaafd546f6ad12"
 "checksum string_cache_codegen 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "479cde50c3539481f33906a387f2bd17c8e87cb848c35b6021d41fb81ff9b4d7"
 "checksum string_cache_shared 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b1884d1bc09741d466d9b14e6d37ac89d6909cbcac41dd9ae982d4d063bbedfc"
 "checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694"
 "checksum syn 0.12.12 (registry+https://github.com/rust-lang/crates.io-index)" = "9e1c669ed757c0ebd04337f6a5bb972d05e0c08fe2540dd3ee3dd9e4daf1604c"
 "checksum syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "91b52877572087400e83d24b9178488541e3d535259e04ff17a63df1e5ceff59"
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -74,16 +74,17 @@
   <binding id="tabbrowser-tabs"
            extends="chrome://global/content/bindings/tabbox.xml#tabs">
     <content>
       <xul:hbox class="tab-drop-indicator-box">
         <xul:image class="tab-drop-indicator" anonid="tab-drop-indicator" collapsed="true"/>
       </xul:hbox>
       <xul:arrowscrollbox anonid="arrowscrollbox" orient="horizontal" flex="1"
                           style="min-width: 1px;"
+                          clicktoscroll="true"
                           class="tabbrowser-arrowscrollbox">
 <!--
  This is a hack to circumvent bug 472020, otherwise the tabs show up on the
  right of the newtab button.
 -->
         <children includes="tab"/>
 <!--
   This is to ensure anything extensions put here will go before the newtab
--- a/devtools/shared/css/generated/properties-db.js
+++ b/devtools/shared/css/generated/properties-db.js
@@ -1383,81 +1383,16 @@ exports.CSS_PROPERTIES = {
       "default",
       "drag",
       "inherit",
       "initial",
       "no-drag",
       "unset"
     ]
   },
-  "-moz-window-opacity": {
-    "isInherited": false,
-    "subproperties": [
-      "-moz-window-opacity"
-    ],
-    "supports": [],
-    "values": [
-      "inherit",
-      "initial",
-      "unset"
-    ]
-  },
-  "-moz-window-transform": {
-    "isInherited": false,
-    "subproperties": [
-      "-moz-window-transform"
-    ],
-    "supports": [],
-    "values": [
-      "accumulatematrix",
-      "inherit",
-      "initial",
-      "interpolatematrix",
-      "matrix",
-      "matrix3d",
-      "none",
-      "perspective",
-      "rotate",
-      "rotate3d",
-      "rotateX",
-      "rotateY",
-      "rotateZ",
-      "scale",
-      "scale3d",
-      "scaleX",
-      "scaleY",
-      "scaleZ",
-      "skew",
-      "skewX",
-      "skewY",
-      "translate",
-      "translate3d",
-      "translateX",
-      "translateY",
-      "translateZ",
-      "unset"
-    ]
-  },
-  "-moz-window-transform-origin": {
-    "isInherited": false,
-    "subproperties": [
-      "-moz-window-transform-origin"
-    ],
-    "supports": [],
-    "values": [
-      "bottom",
-      "center",
-      "inherit",
-      "initial",
-      "left",
-      "right",
-      "top",
-      "unset"
-    ]
-  },
   "-webkit-align-content": {
     "isInherited": false,
     "subproperties": [
       "align-content"
     ],
     "supports": [],
     "values": [
       "baseline",
@@ -3039,19 +2974,16 @@ exports.CSS_PROPERTIES = {
       "text-overflow",
       "text-decoration-line",
       "text-decoration-style",
       "text-decoration-color",
       "initial-letter",
       "ime-mode",
       "-moz-user-select",
       "-moz-window-dragging",
-      "-moz-window-opacity",
-      "-moz-window-transform",
-      "-moz-window-transform-origin",
       "-moz-force-broken-image-icon",
       "text-anchor",
       "color-interpolation",
       "color-interpolation-filters",
       "fill",
       "fill-opacity",
       "fill-rule",
       "shape-rendering",
--- a/dom/base/nsDeprecatedOperationList.h
+++ b/dom/base/nsDeprecatedOperationList.h
@@ -42,8 +42,9 @@ DEPRECATED_OPERATION(WindowContentUntrus
 DEPRECATED_OPERATION(RegisterProtocolHandlerInsecure)
 DEPRECATED_OPERATION(MixedDisplayObjectSubrequest)
 DEPRECATED_OPERATION(MotionEvent)
 DEPRECATED_OPERATION(OrientationEvent)
 DEPRECATED_OPERATION(ProximityEvent)
 DEPRECATED_OPERATION(AmbientLightEvent)
 DEPRECATED_OPERATION(IDBOpenDBOptions_StorageType)
 DEPRECATED_OPERATION(DOMAttrModifiedEvent)
+DEPRECATED_OPERATION(MozBoxOrInlineBoxDisplay)
--- a/dom/bindings/test/test_dom_xrays.html
+++ b/dom/bindings/test/test_dom_xrays.html
@@ -166,17 +166,17 @@ function test()
   ok(Object.isFrozen(languages2.wrappedJSObject),
      ".languages should still be a frozen array underneath");
   isnot(languages1, languages2, "Must have distinct arrays");
   isnot(languages1, languages2.wrappedJSObject,
         "Must have distinct arrays no matter how we slice it");
 
   // Check that DataTransfer's .types has the hack to alias contains()
   // to includes().
-  var dataTransfer = new win.DataTransfer("foo", true);
+  var dataTransfer = new win.DataTransfer();
   is(dataTransfer.types.contains, dataTransfer.types.includes,
      "Should have contains() set up as an alias to includes()");
   // Waive Xrays on the dataTransfer itself, since the .types we get is
   // different over Xrays vs not.
   is(dataTransfer.wrappedJSObject.types.contains, undefined,
      "Underlying object should not have contains() set up as an alias to " +
      "includes()");
 
--- a/dom/canvas/WebGLShader.cpp
+++ b/dom/canvas/WebGLShader.cpp
@@ -14,16 +14,37 @@
 #include "prenv.h"
 #include "WebGLContext.h"
 #include "WebGLObjectModel.h"
 #include "WebGLShaderValidator.h"
 #include "WebGLValidateStrings.h"
 
 namespace mozilla {
 
+static void
+PrintLongString(const char* const begin, const size_t len)
+{
+    // Wow - Roll Your Own Foreach-Lines because printf_stderr has a hard-coded
+    // internal size, so long strings are truncated.
+
+    const size_t chunkSize = 1000;
+    const UniqueBuffer buf(moz_xmalloc(chunkSize+1)); // +1 for null-term
+    const auto bufBegin = (char*)buf.get();
+    bufBegin[chunkSize] = '\0';
+
+    auto chunkBegin = begin;
+    const auto end = begin + len;
+    while (chunkBegin + chunkSize < end) {
+        memcpy(bufBegin, chunkBegin, chunkSize);
+        printf_stderr("%s", bufBegin);
+        chunkBegin += chunkSize;
+    }
+    printf_stderr("%s", chunkBegin);
+}
+
 // On success, writes to out_validator and out_translatedSource.
 // On failure, writes to out_translationLog.
 static bool
 Translate(const nsACString& source, webgl::ShaderValidator* validator,
           nsACString* const out_translationLog, nsACString* const out_translatedSource)
 {
     if (!validator->ValidateAndTranslate(source.BeginReading())) {
         validator->GetInfoLog(out_translationLog);
@@ -161,67 +182,56 @@ WebGLShader::ShaderSource(const nsAStrin
 
     if (!ValidateGLSLPreprocString(mContext, funcName, sourceWithoutComments))
         return;
 
     // We checked that the source stripped of comments is in the
     // 7-bit ASCII range, so we can skip the NS_IsAscii() check.
     const NS_LossyConvertUTF16toASCII cleanSource(sourceWithoutComments);
 
-    if (PR_GetEnv("MOZ_WEBGL_DUMP_SHADERS")) {
-        printf_stderr("////////////////////////////////////////\n");
-        printf_stderr("// MOZ_WEBGL_DUMP_SHADERS:\n");
-
-        // Wow - Roll Your Own Foreach-Lines because printf_stderr has a hard-coded
-        // internal size, so long strings are truncated.
-
-        const size_t maxChunkSize = 1024-1; // -1 for null-term.
-        const UniqueBuffer buf(moz_xmalloc(maxChunkSize+1)); // +1 for null-term
-        const auto bufBegin = (char*)buf.get();
-
-        size_t chunkStart = 0;
-        while (chunkStart != cleanSource.Length()) {
-            const auto chunkEnd = std::min(chunkStart + maxChunkSize,
-                                           size_t(cleanSource.Length()));
-            const auto chunkSize = chunkEnd - chunkStart;
-
-            memcpy(bufBegin, cleanSource.BeginReading() + chunkStart, chunkSize);
-            bufBegin[chunkSize + 1] = '\0';
-
-            printf_stderr("%s", bufBegin);
-            chunkStart += chunkSize;
-        }
-
-        printf_stderr("////////////////////////////////////////\n");
-    }
-
     mSource = source;
     mCleanSource = cleanSource;
 }
 
 void
 WebGLShader::CompileShader()
 {
     mValidator = nullptr;
     mTranslationSuccessful = false;
     mCompilationSuccessful = false;
 
     gl::GLContext* gl = mContext->gl;
 
     mValidator.reset(mContext->CreateShaderValidator(mType));
 
+    static const bool kDumpShaders = PR_GetEnv("MOZ_WEBGL_DUMP_SHADERS");
+    if (MOZ_UNLIKELY(kDumpShaders)) {
+        printf_stderr("==== begin MOZ_WEBGL_DUMP_SHADERS ====\n");
+        PrintLongString(mCleanSource.BeginReading(), mCleanSource.Length());
+    }
+
     bool success;
     if (mValidator) {
         success = Translate(mCleanSource, mValidator.get(), &mValidationLog,
                             &mTranslatedSource);
     } else {
         success = TranslateWithoutValidation(mCleanSource, mContext->IsWebGL2(),
                                              &mValidationLog, &mTranslatedSource);
     }
 
+    if (MOZ_UNLIKELY(kDumpShaders)) {
+        printf_stderr("\n==== \\/ \\/ \\/ ====\n");
+        if (success) {
+            PrintLongString(mTranslatedSource.BeginReading(), mTranslatedSource.Length());
+        } else {
+            printf_stderr("Validation failed:\n%s", mValidationLog.BeginReading());
+        }
+        printf_stderr("\n==== end ====\n");
+    }
+
     if (!success)
         return;
 
     mTranslationSuccessful = true;
 
     const char* const parts[] = {
         mTranslatedSource.BeginReading()
     };
--- a/dom/canvas/test/webgl-conf/generated-mochitest.ini
+++ b/dom/canvas/test/webgl-conf/generated-mochitest.ini
@@ -4952,17 +4952,17 @@ support-files = always-fail.html
                 checkout/test-guidelines.md
                 checkout/webgl-conformance-tests.html
                 iframe-passthrough.css
                 mochi-single.html
 
 [generated/test_..__always-fail.html]
 fail-if = 1
 [generated/test_2_conformance2__attribs__gl-bindAttribLocation-aliasing-inactive.html]
-fail-if = 1
+fail-if = (os != 'win')
 skip-if = (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__attribs__gl-vertex-attrib-i-render.html]
 skip-if = (os == 'win') || (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__attribs__gl-vertex-attrib-normalized-int.html]
 skip-if = (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__attribs__gl-vertex-attrib.html]
 skip-if = (os == 'win') || (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__attribs__gl-vertexattribipointer-offsets.html]
@@ -5090,20 +5090,18 @@ skip-if = (os == 'android' || os == 'lin
 skip-if = (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__glsl3__shader-with-invalid-characters.html]
 skip-if = (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__glsl3__shader-with-mis-matching-uniform-block.html]
 skip-if = (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__glsl3__short-circuiting-in-loop-condition.html]
 skip-if = (os == 'win' && os_version == '6.1') || (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__glsl3__switch-case.html]
-fail-if = (os == 'win')
 skip-if = (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__glsl3__texture-offset-non-constant-offset.html]
-fail-if = (os == 'win')
 skip-if = (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__glsl3__texture-offset-out-of-range.html]
 skip-if = (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__glsl3__texture-offset-uniform-texture-coordinate.html]
 skip-if = (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__glsl3__tricky-loop-conditions.html]
 fail-if = (os == 'win')
 skip-if = (os == 'android' || os == 'linux')
@@ -7274,18 +7272,17 @@ skip-if = (os == 'android' || os == 'lin
 skip-if = (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__transform_feedback__non-existent-varying.html]
 skip-if = (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__transform_feedback__simultaneous_binding.html]
 skip-if = (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__transform_feedback__switching-objects.html]
 skip-if = (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__transform_feedback__too-small-buffers.html]
-fail-if = 1
-skip-if = (os == 'android' || os == 'linux')
+skip-if = 1 || (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__transform_feedback__transform_feedback.html]
 skip-if = (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__transform_feedback__two-unreferenced-varyings.html]
 skip-if = (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__transform_feedback__unwritten-output-defaults-to-zero.html]
 skip-if = (os == 'android' || os == 'linux')
 [generated/test_2_conformance2__uniforms__dependent-buffer-change.html]
 skip-if = (os == 'android' || os == 'linux')
--- a/dom/canvas/test/webgl-conf/mochitest-errata.ini
+++ b/dom/canvas/test/webgl-conf/mochitest-errata.ini
@@ -84,21 +84,22 @@ skip-if = (os == 'win')
 skip-if = 1
 [generated/test_2_conformance2__rendering__depth-stencil-feedback-loop.html]
 fail-if = 1
 [generated/test_2_conformance2__rendering__instanced-arrays.html]
 fail-if = 1
 [generated/test_2_conformance2__rendering__read-draw-when-missing-image.html]
 fail-if = 1
 [generated/test_2_conformance2__transform_feedback__too-small-buffers.html]
-fail-if = 1
+# ABORT_ON_ERROR
+skip-if = 1
 [generated/test_2_conformance2__uniforms__incompatible-texture-type-for-sampler.html]
 fail-if = 1
 [generated/test_2_conformance2__attribs__gl-bindAttribLocation-aliasing-inactive.html]
-fail-if = 1
+fail-if = (os != 'win')
 
 [generated/test_conformance__rendering__texture-switch-performance.html]
 # Frequent orange on linux+asan, but likely intermittant:
 # Texture switching significantly hurt performance - achieved 77 frames in 2.016 seconds (0.79 times baseline performance)
 skip-if = 1
 [generated/test_2_conformance__rendering__texture-switch-performance.html]
 # Orange on win10+debug
 # Texture switching significantly hurt performance - achieved 3 frames in 2.164
@@ -1164,20 +1165,16 @@ fail-if = (os == 'win')
 [generated/test_2_conformance__rendering__preservedrawingbuffer-leak.html]
 skip-if = (os == 'win')
 [generated/test_conformance__context__context-size-change.html]
 skip-if = (os == 'win')
 [generated/test_conformance__rendering__preservedrawingbuffer-leak.html]
 skip-if = (os == 'win')
 [generated/test_2_conformance2__glsl3__array-initialize-with-same-name-array.html]
 fail-if = (os == 'win')
-[generated/test_2_conformance2__glsl3__switch-case.html]
-fail-if = (os == 'win')
-[generated/test_2_conformance2__glsl3__texture-offset-non-constant-offset.html]
-fail-if = (os == 'win')
 [generated/test_2_conformance__misc__webgl-specific-stencil-settings.html]
 # [gl:0D6DE000] mozilla::gl::GLContext::raw_fDrawArrays: Generated unexpected GL_INVALID_OPERATION error. (0x0502)
 # ERR: gl::ValidateDrawBase(2519): This ANGLE implementation does not support separate front/back stencil writemasks, reference values, or stencil mask values.
 # Hit MOZ_CRASH(Unexpected error with MOZ_GL_DEBUG_ABORT_ON_ERROR. (Run with MOZ_GL_DEBUG_ABORT_ON_ERROR=0 to disable)) at z:/build/build/src/gfx/gl/GLContext.cpp:3030
 skip-if = (os == 'win')
 [generated/test_conformance__misc__webgl-specific-stencil-settings.html]
 skip-if = (os == 'win')
 [generated/test_conformance__textures__misc__tex-video-using-tex-unit-non-zero.html]
--- a/dom/clients/manager/ClientInfo.cpp
+++ b/dom/clients/manager/ClientInfo.cpp
@@ -55,16 +55,22 @@ ClientInfo::operator=(ClientInfo&& aRigh
   mData = std::move(aRight.mData);
   return *this;
 }
 
 ClientInfo::~ClientInfo()
 {
 }
 
+bool
+ClientInfo::operator==(const ClientInfo& aRight) const
+{
+  return *mData == *aRight.mData;
+}
+
 const nsID&
 ClientInfo::Id() const
 {
   return mData->id();
 }
 
 ClientType
 ClientInfo::Type() const
--- a/dom/clients/manager/ClientInfo.h
+++ b/dom/clients/manager/ClientInfo.h
@@ -42,16 +42,19 @@ public:
 
   ClientInfo&
   operator=(ClientInfo&& aRight);
 
   explicit ClientInfo(const IPCClientInfo& aData);
 
   ~ClientInfo();
 
+  bool
+  operator==(const ClientInfo& aRight) const;
+
   // Get the unique identifier chosen at the time of the global's creation.
   const nsID&
   Id() const;
 
   // Determine what kind of global this is; e.g. Window, Worker, SharedWorker,
   // etc.
   ClientType
   Type() const;
--- a/dom/clients/manager/ClientManagerService.cpp
+++ b/dom/clients/manager/ClientManagerService.cpp
@@ -8,16 +8,18 @@
 
 #include "ClientManagerParent.h"
 #include "ClientNavigateOpParent.h"
 #include "ClientOpenWindowOpParent.h"
 #include "ClientOpenWindowUtils.h"
 #include "ClientPrincipalUtils.h"
 #include "ClientSourceParent.h"
 #include "mozilla/dom/ContentParent.h"
+#include "mozilla/dom/ServiceWorkerManager.h"
+#include "mozilla/dom/ServiceWorkerUtils.h"
 #include "mozilla/ipc/BackgroundParent.h"
 #include "mozilla/ipc/PBackgroundSharedTypes.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/SystemGroup.h"
 #include "nsIAsyncShutdown.h"
 #include "nsIXULRuntime.h"
 #include "nsProxyRelease.h"
 
@@ -443,16 +445,50 @@ ClientManagerService::MatchAll(const Cli
   }
 
   // Maybe finish the promise now in case we didn't find any matching clients.
   promiseList->MaybeFinish();
 
   return promiseList->GetResultPromise();
 }
 
+namespace {
+
+RefPtr<ClientOpPromise>
+ClaimOnMainThread(const ClientInfo& aClientInfo,
+                  const ServiceWorkerDescriptor& aDescriptor)
+{
+  RefPtr<ClientOpPromise::Private> promise =
+    new ClientOpPromise::Private(__func__);
+
+  nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction(__func__,
+    [promise, clientInfo = std::move(aClientInfo), desc = std::move(aDescriptor)] () {
+      auto scopeExit = MakeScopeExit([&] {
+        promise->Reject(NS_ERROR_DOM_INVALID_STATE_ERR, __func__);
+      });
+
+      RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
+      NS_ENSURE_TRUE_VOID(swm);
+
+      RefPtr<GenericPromise> inner = swm->MaybeClaimClient(clientInfo, desc);
+      inner->Then(SystemGroup::EventTargetFor(TaskCategory::Other), __func__,
+        [promise] (bool aResult) {
+          promise->Resolve(NS_OK, __func__);
+        }, [promise] (nsresult aRv) {
+          promise->Reject(aRv, __func__);
+        });
+    });
+
+  MOZ_ALWAYS_SUCCEEDS(SystemGroup::Dispatch(TaskCategory::Other, r.forget()));
+
+  return promise.forget();
+}
+
+} // anonymous namespace
+
 RefPtr<ClientOpPromise>
 ClientManagerService::Claim(const ClientClaimArgs& aArgs)
 {
   AssertIsOnBackgroundThread();
 
   const IPCServiceWorkerDescriptor& serviceWorker = aArgs.serviceWorker();
   const PrincipalInfo& principalInfo = serviceWorker.principalInfo();
 
@@ -482,17 +518,23 @@ ClientManagerService::Claim(const Client
     //       This can't happen until the SWM is moved to the parent process,
     //       though.
     if (!source->ExecutionReady() ||
         source->Info().Type() == ClientType::Serviceworker ||
         source->Info().URL().Find(serviceWorker.scope()) != 0) {
       continue;
     }
 
-    promiseList->AddPromise(source->StartOp(aArgs));
+    if (ServiceWorkerParentInterceptEnabled()) {
+      promiseList->AddPromise(
+        ClaimOnMainThread(source->Info(),
+                          ServiceWorkerDescriptor(serviceWorker)));
+    } else {
+      promiseList->AddPromise(source->StartOp(aArgs));
+    }
   }
 
   // Maybe finish the promise now in case we didn't find any matching clients.
   promiseList->MaybeFinish();
 
   return promiseList->GetResultPromise();
 }
 
--- a/dom/clients/manager/ClientSource.cpp
+++ b/dom/clients/manager/ClientSource.cpp
@@ -635,17 +635,17 @@ ClientSource::Claim(const ClientClaimArg
   }
 
   RefPtr<ClientOpPromise::Private> outerPromise =
     new ClientOpPromise::Private(__func__);
 
   auto holder =
     MakeRefPtr<DOMMozPromiseRequestHolder<GenericPromise>>(innerWindow->AsGlobal());
 
-  RefPtr<GenericPromise> p = swm->MaybeClaimClient(doc, swd);
+  RefPtr<GenericPromise> p = swm->MaybeClaimClient(mClientInfo, swd);
   p->Then(mEventTarget, __func__,
     [outerPromise, holder] (bool aResult) {
       holder->Complete();
       outerPromise->Resolve(NS_OK, __func__);
     }, [outerPromise, holder] (nsresult aResult) {
       holder->Complete();
       outerPromise->Reject(aResult, __func__);
     })->Track(*holder);
--- a/dom/events/DataTransfer.cpp
+++ b/dom/events/DataTransfer.cpp
@@ -192,32 +192,22 @@ DataTransfer::DataTransfer(nsISupports* 
                "invalid event type for DataTransfer constructor");
 }
 
 DataTransfer::~DataTransfer()
 {}
 
 // static
 already_AddRefed<DataTransfer>
-DataTransfer::Constructor(const GlobalObject& aGlobal,
-                          const nsAString& aEventType, bool aIsExternal,
-                          ErrorResult& aRv)
+DataTransfer::Constructor(const GlobalObject& aGlobal, ErrorResult& aRv)
 {
-  nsAutoCString onEventType("on");
-  AppendUTF16toUTF8(aEventType, onEventType);
-  RefPtr<nsAtom> eventTypeAtom = NS_Atomize(onEventType);
-  if (!eventTypeAtom) {
-    aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
-    return nullptr;
-  }
 
-  EventMessage eventMessage = nsContentUtils::GetEventMessage(eventTypeAtom);
   RefPtr<DataTransfer> transfer = new DataTransfer(aGlobal.GetAsSupports(),
-                                                     eventMessage, aIsExternal,
-                                                     -1);
+                                                   eCopy, /* is external */ false, /* clipboard type */ -1);
+  transfer->mEffectAllowed = nsIDragService::DRAGDROP_ACTION_NONE;
   return transfer.forget();
 }
 
 JSObject*
 DataTransfer::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
 {
   return DataTransferBinding::Wrap(aCx, this, aGivenProto);
 }
--- a/dom/events/DataTransfer.h
+++ b/dom/events/DataTransfer.h
@@ -114,18 +114,17 @@ public:
     MOZ_ASSERT(aNewParent);
     // Setting the parent after we've been wrapped is pointless, so
     // make sure we aren't wrapped yet.
     MOZ_ASSERT(!GetWrapperPreserveColor());
     mParent = aNewParent;
   }
 
   static already_AddRefed<DataTransfer>
-  Constructor(const GlobalObject& aGlobal, const nsAString& aEventType,
-              bool aIsExternal, ErrorResult& aRv);
+  Constructor(const GlobalObject& aGlobal, ErrorResult& aRv);
 
   /**
    * The actual effect that will be used, and should always be one of the
    * possible values of effectAllowed.
    *
    * For dragstart, drag and dragleave events, the dropEffect is initialized
    * to none. Any value assigned to the dropEffect will be set, but the value
    * isn't used for anything.
--- a/dom/geolocation/nsGeolocation.cpp
+++ b/dom/geolocation/nsGeolocation.cpp
@@ -911,18 +911,17 @@ nsGeolocationService::RemoveLocator(Geol
 }
 
 ////////////////////////////////////////////////////
 // Geolocation
 ////////////////////////////////////////////////////
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Geolocation)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
-  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMGeoGeolocation)
-  NS_INTERFACE_MAP_ENTRY(nsIDOMGeoGeolocation)
+  NS_INTERFACE_MAP_ENTRY(nsISupports)
   NS_INTERFACE_MAP_ENTRY(nsIGeolocationUpdate)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(Geolocation)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(Geolocation)
 
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Geolocation,
                                       mPendingCallbacks,
@@ -937,16 +936,34 @@ Geolocation::Geolocation()
 
 Geolocation::~Geolocation()
 {
   if (mService) {
     Shutdown();
   }
 }
 
+StaticRefPtr<Geolocation> Geolocation::sNonWindowSingleton;
+
+already_AddRefed<Geolocation>
+Geolocation::NonWindowSingleton()
+{
+  if (sNonWindowSingleton) {
+    return do_AddRef(sNonWindowSingleton);
+  }
+
+  RefPtr<Geolocation> result = new Geolocation();
+  DebugOnly<nsresult> rv = result->Init();
+  MOZ_ASSERT(NS_SUCCEEDED(rv), "How can this fail?");
+
+  ClearOnShutdown(&sNonWindowSingleton);
+  sNonWindowSingleton = result;
+  return result.forget();
+}
+
 nsresult
 Geolocation::Init(nsPIDOMWindowInner* aContentDom)
 {
   // Remember the window
   if (aContentDom) {
     mOwner = do_GetWeakReference(aContentDom);
     if (!mOwner) {
       return NS_ERROR_FAILURE;
@@ -1234,101 +1251,99 @@ Geolocation::GetCurrentPosition(GeoPosit
 
 int32_t
 Geolocation::WatchPosition(PositionCallback& aCallback,
                            PositionErrorCallback* aErrorCallback,
                            const PositionOptions& aOptions,
                            CallerType aCallerType,
                            ErrorResult& aRv)
 {
-  int32_t ret = 0;
-  nsresult rv = WatchPosition(GeoPositionCallback(&aCallback),
-                              GeoPositionErrorCallback(aErrorCallback),
-                              CreatePositionOptionsCopy(aOptions),
-                              aCallerType,
-                              &ret);
-
-  if (NS_FAILED(rv)) {
-    aRv.Throw(rv);
-  }
-
-  return ret;
+  return WatchPosition(GeoPositionCallback(&aCallback),
+                       GeoPositionErrorCallback(aErrorCallback),
+                       CreatePositionOptionsCopy(aOptions),
+                       aCallerType,
+                       aRv);
 }
 
-NS_IMETHODIMP
+int32_t
 Geolocation::WatchPosition(nsIDOMGeoPositionCallback *aCallback,
                            nsIDOMGeoPositionErrorCallback *aErrorCallback,
-                           UniquePtr<PositionOptions>&& aOptions,
-                           int32_t* aRv)
+                           UniquePtr<PositionOptions>&& aOptions)
 {
-  NS_ENSURE_ARG_POINTER(aCallback);
+  MOZ_ASSERT(aCallback);
 
   return WatchPosition(GeoPositionCallback(aCallback),
                        GeoPositionErrorCallback(aErrorCallback),
                        std::move(aOptions), CallerType::System,
-                       aRv);
+                       IgnoreErrors());
 }
 
-nsresult
+// On errors we return -1 because that's not a valid watch id and will
+// get ignored in clearWatch.
+int32_t
 Geolocation::WatchPosition(GeoPositionCallback aCallback,
                            GeoPositionErrorCallback aErrorCallback,
                            UniquePtr<PositionOptions>&& aOptions,
                            CallerType aCallerType,
-                           int32_t* aRv)
+                           ErrorResult& aRv)
 {
   if (mWatchingCallbacks.Length() > MAX_GEO_REQUESTS_PER_WINDOW) {
-    return NS_ERROR_NOT_AVAILABLE;
+    aRv.Throw(NS_ERROR_NOT_AVAILABLE);
+    return -1;
   }
 
   // Count the number of requests per protocol/scheme.
   Telemetry::Accumulate(Telemetry::GEOLOCATION_WATCHPOSITION_SECURE_ORIGIN,
                         static_cast<uint8_t>(mProtocolType));
 
   // The watch ID:
-  *aRv = mLastWatchId++;
+  int32_t watchId = mLastWatchId++;
 
   nsIEventTarget* target = MainThreadTarget(this);
   RefPtr<nsGeolocationRequest> request =
     new nsGeolocationRequest(this, std::move(aCallback), std::move(aErrorCallback),
                              std::move(aOptions),
                              static_cast<uint8_t>(mProtocolType), target, true,
-                             EventStateManager::IsHandlingUserInput(), *aRv);
+                             EventStateManager::IsHandlingUserInput(), watchId);
 
   if (!sGeoEnabled || ShouldBlockInsecureRequests() ||
       nsContentUtils::ResistFingerprinting(aCallerType)) {
     nsCOMPtr<nsIRunnable> ev = new RequestAllowEvent(false, request);
     target->Dispatch(ev.forget());
-    return NS_OK;
+    return watchId;
   }
 
   if (!mOwner && aCallerType != CallerType::System) {
-    return NS_ERROR_FAILURE;
+    aRv.Throw(NS_ERROR_FAILURE);
+    return -1;
   }
 
   if (mOwner) {
-    if (!RegisterRequestWithPrompt(request))
-      return NS_ERROR_NOT_AVAILABLE;
+    if (!RegisterRequestWithPrompt(request)) {
+      aRv.Throw(NS_ERROR_NOT_AVAILABLE);
+      return -1;
+    }
 
-    return NS_OK;
+    return watchId;
   }
 
   if (aCallerType != CallerType::System) {
-    return NS_ERROR_FAILURE;
+    aRv.Throw(NS_ERROR_FAILURE);
+    return -1;
   }
 
   request->Allow(JS::UndefinedHandleValue);
-
-  return NS_OK;
+  return watchId;
 }
 
-NS_IMETHODIMP
+void
 Geolocation::ClearWatch(int32_t aWatchId)
 {
   if (aWatchId < 0) {
-    return NS_OK;
+    return;
   }
 
   if (!mClearedWatchIDs.Contains(aWatchId)) {
     mClearedWatchIDs.AppendElement(aWatchId);
   }
 
   for (uint32_t i = 0, length = mWatchingCallbacks.Length(); i < length; ++i) {
     if (mWatchingCallbacks[i]->WatchId() == aWatchId) {
@@ -1344,18 +1359,16 @@ Geolocation::ClearWatch(int32_t aWatchId
   for (uint32_t i = 0, length = mPendingRequests.Length(); i < length; ++i) {
     if (mPendingRequests[i]->IsWatch() &&
         (mPendingRequests[i]->WatchId() == aWatchId)) {
       mPendingRequests[i]->Shutdown();
       mPendingRequests.RemoveElementAt(i);
       break;
     }
   }
-
-  return NS_OK;
 }
 
 bool
 Geolocation::WindowOwnerStillExists()
 {
   // an owner was never set when Geolocation
   // was created, which means that this object
   // is being used without a window.
--- a/dom/geolocation/nsGeolocation.h
+++ b/dom/geolocation/nsGeolocation.h
@@ -16,17 +16,16 @@
 #include "nsITimer.h"
 #include "nsIObserver.h"
 #include "nsWrapperCache.h"
 
 #include "nsWeakPtr.h"
 #include "nsCycleCollectionParticipant.h"
 
 #include "nsGeoPosition.h"
-#include "nsIDOMGeoGeolocation.h"
 #include "nsIDOMGeoPosition.h"
 #include "nsIDOMGeoPositionCallback.h"
 #include "nsIDOMGeoPositionErrorCallback.h"
 #include "mozilla/dom/BindingDeclarations.h"
 #include "mozilla/dom/GeolocationBinding.h"
 #include "mozilla/dom/CallbackObject.h"
 
 #include "nsIGeolocationProvider.h"
@@ -115,27 +114,25 @@ private:
 };
 
 namespace mozilla {
 namespace dom {
 
 /**
  * Can return a geolocation info
  */
-class Geolocation final : public nsIDOMGeoGeolocation,
-                          public nsIGeolocationUpdate,
+class Geolocation final : public nsIGeolocationUpdate,
                           public nsWrapperCache
 {
 public:
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(Geolocation, nsIDOMGeoGeolocation)
+  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Geolocation)
 
   NS_DECL_NSIGEOLOCATIONUPDATE
-  NS_DECL_NSIDOMGEOGEOLOCATION
 
   Geolocation();
 
   nsresult Init(nsPIDOMWindowInner* aContentDom = nullptr);
 
   nsPIDOMWindowInner* GetParentObject() const;
   virtual JSObject* WrapObject(JSContext *aCtx, JS::Handle<JSObject*> aGivenProto) override;
 
@@ -144,16 +141,22 @@ public:
                         const PositionOptions& aOptions,
                         CallerType aCallerType,
                         ErrorResult& aRv);
   void GetCurrentPosition(PositionCallback& aCallback,
                           PositionErrorCallback* aErrorCallback,
                           const PositionOptions& aOptions,
                           CallerType aCallerType,
                           ErrorResult& aRv);
+  void ClearWatch(int32_t aWatchId);
+
+  // A WatchPosition for C++ use.  Returns -1 if we failed to actually watch.
+  int32_t WatchPosition(nsIDOMGeoPositionCallback* aCallback,
+                        nsIDOMGeoPositionErrorCallback* aErrorCallback,
+                        UniquePtr<PositionOptions>&& aOptions);
 
   // Returns true if any of the callbacks are repeating
   bool HasActiveCallbacks();
 
   // Register an allowed request
   void NotifyAllowedRequest(nsGeolocationRequest* aRequest);
 
   // Remove request from all callbacks arrays
@@ -173,29 +176,32 @@ public:
   nsIWeakReference* GetOwner() { return mOwner; }
 
   // Check to see if the window still exists
   bool WindowOwnerStillExists();
 
   // Check to see if any active request requires high accuracy
   bool HighAccuracyRequested();
 
+  // Get the singleton non-window Geolocation instance.  This never returns null.
+  static already_AddRefed<Geolocation> NonWindowSingleton();
+
 private:
 
   ~Geolocation();
 
   nsresult GetCurrentPosition(GeoPositionCallback aCallback,
                               GeoPositionErrorCallback aErrorCallback,
                               UniquePtr<PositionOptions>&& aOptions,
                               CallerType aCallerType);
-  nsresult WatchPosition(GeoPositionCallback aCallback,
-                         GeoPositionErrorCallback aErrorCallback,
-                         UniquePtr<PositionOptions>&& aOptions,
-                         CallerType aCallerType,
-                         int32_t* aRv);
+  int32_t WatchPosition(GeoPositionCallback aCallback,
+                        GeoPositionErrorCallback aErrorCallback,
+                        UniquePtr<PositionOptions>&& aOptions,
+                        CallerType aCallerType,
+                        ErrorResult& aRv);
 
   bool RegisterRequestWithPrompt(nsGeolocationRequest* request);
 
   // Check if clearWatch is already called
   bool IsAlreadyCleared(nsGeolocationRequest* aRequest);
 
   // Returns whether the Geolocation object should block requests
   // within a context that is not secure.
@@ -228,21 +234,17 @@ private:
   // Watch ID
   uint32_t mLastWatchId;
 
   // Pending requests are used when the service is not ready
   nsTArray<RefPtr<nsGeolocationRequest> > mPendingRequests;
 
   // Array containing already cleared watch IDs
   nsTArray<int32_t> mClearedWatchIDs;
+
+  // Our cached non-window singleton.
+  static mozilla::StaticRefPtr<Geolocation> sNonWindowSingleton;
 };
 
 } // namespace dom
-
-inline nsISupports*
-ToSupports(dom::Geolocation* aGeolocation)
-{
-  return ToSupports(static_cast<nsIDOMGeoGeolocation*>(aGeolocation));
-}
-
 } // namespace mozilla
 
 #endif /* nsGeoLocation_h */
--- a/dom/interfaces/geolocation/moz.build
+++ b/dom/interfaces/geolocation/moz.build
@@ -3,17 +3,16 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 with Files("**"):
     BUG_COMPONENT = ("Core", "Geolocation")
 
 XPIDL_SOURCES += [
-    'nsIDOMGeoGeolocation.idl',
     'nsIDOMGeoPosition.idl',
     'nsIDOMGeoPositionCallback.idl',
     'nsIDOMGeoPositionCoords.idl',
     'nsIDOMGeoPositionErrorCallback.idl',
 ]
 
 XPIDL_MODULE = 'dom_geolocation'
 
deleted file mode 100644
--- a/dom/interfaces/geolocation/nsIDOMGeoGeolocation.idl
+++ /dev/null
@@ -1,29 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "domstubs.idl"
-
-interface nsIDOMGeoPositionCallback;
-interface nsIDOMGeoPositionErrorCallback;
-
-%{C++
-namespace mozilla {
-namespace dom {
-struct PositionOptions;
-} // namespace dom
-} // namespace mozilla
-
-#include "mozilla/UniquePtr.h"
-%}
-
-native PositionOptionsRef(mozilla::UniquePtr<mozilla::dom::PositionOptions>&&);
-
-[builtinclass, uuid(9142ab45-0ab5-418c-9bab-338a6d271d4f)]
-interface nsIDOMGeoGeolocation : nsISupports
-{
-  int32_t watchPosition(in nsIDOMGeoPositionCallback callback,
-                        in nsIDOMGeoPositionErrorCallback errorCallback,
-                        in PositionOptionsRef options);
-  void clearWatch(in long watchId);
-};
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -118,17 +118,17 @@
 #include "nsIAlertsService.h"
 #include "nsIClipboard.h"
 #include "nsICookie.h"
 #include "nsContentPermissionHelper.h"
 #include "nsIContentProcess.h"
 #include "nsICycleCollectorListener.h"
 #include "nsIDocShellTreeOwner.h"
 #include "nsIDocument.h"
-#include "nsIDOMGeoGeolocation.h"
+#include "nsGeolocation.h"
 #include "nsIDragService.h"
 #include "mozilla/dom/WakeLock.h"
 #include "nsIDOMWindow.h"
 #include "nsIExternalProtocolService.h"
 #include "nsIFormProcessor.h"
 #include "nsIGfxInfo.h"
 #include "nsIIdleService.h"
 #include "nsIInterfaceRequestorUtils.h"
@@ -3831,28 +3831,23 @@ ContentParent::RecvAsyncMessage(const ns
                                             aData);
 }
 
 static int32_t
 AddGeolocationListener(nsIDOMGeoPositionCallback* watcher,
                        nsIDOMGeoPositionErrorCallback* errorCallBack,
                        bool highAccuracy)
 {
-  nsCOMPtr<nsIDOMGeoGeolocation> geo = do_GetService("@mozilla.org/geolocation;1");
-  if (!geo) {
-    return -1;
-  }
+  RefPtr<Geolocation> geo = Geolocation::NonWindowSingleton();
 
   UniquePtr<PositionOptions> options = MakeUnique<PositionOptions>();
   options->mTimeout = 0;
   options->mMaximumAge = 0;
   options->mEnableHighAccuracy = highAccuracy;
-  int32_t retval = 1;
-  geo->WatchPosition(watcher, errorCallBack, std::move(options), &retval);
-  return retval;
+  return geo->WatchPosition(watcher, errorCallBack, std::move(options));
 }
 
 mozilla::ipc::IPCResult
 ContentParent::RecvAddGeolocationListener(const IPC::Principal& aPrincipal,
                                           const bool& aHighAccuracy)
 {
   // To ensure no geolocation updates are skipped, we always force the
   // creation of a new listener.
@@ -3860,20 +3855,17 @@ ContentParent::RecvAddGeolocationListene
   mGeolocationWatchID = AddGeolocationListener(this, this, aHighAccuracy);
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 ContentParent::RecvRemoveGeolocationListener()
 {
   if (mGeolocationWatchID != -1) {
-    nsCOMPtr<nsIDOMGeoGeolocation> geo = do_GetService("@mozilla.org/geolocation;1");
-    if (!geo) {
-      return IPC_OK();
-    }
+    RefPtr<Geolocation> geo = Geolocation::NonWindowSingleton();
     geo->ClearWatch(mGeolocationWatchID);
     mGeolocationWatchID = -1;
   }
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 ContentParent::RecvSetGeolocationHigherAccuracy(const bool& aEnable)
--- a/dom/plugins/ipc/FunctionBroker.cpp
+++ b/dom/plugins/ipc/FunctionBroker.cpp
@@ -902,16 +902,39 @@ const LPINTERNET_BUFFERSA HSRExAReqInfo:
 // passes other values.
 // template<> template<>
 // struct HSRExAReqInfo::FixedValue<3> { static const DWORD value = 0; };
 
 template<> template<>
 struct HSRExAReqInfo::FixedValue<4> { static const DWORD_PTR value; };
 const DWORD_PTR HSRExAReqInfo::FixedValue<4>::value = 0;
 
+/* HttpEndRequestA */
+
+typedef SslFunctionBroker<ID_HttpEndRequestA,
+  decltype(HttpEndRequestA)> HttpEndRequestAFB;
+
+template<>
+ShouldHookFunc* const
+HttpEndRequestAFB::BaseType::mShouldHook = &CheckQuirks<QUIRK_FLASH_HOOK_SSL>;
+
+typedef RequestInfo<ID_HttpEndRequestA> HERAReqInfo;
+
+template<> template<>
+struct HERAReqInfo::FixedValue<1> { static const LPINTERNET_BUFFERSA value; };
+const LPINTERNET_BUFFERSA HERAReqInfo::FixedValue<1>::value = nullptr;
+
+template<> template<>
+struct HERAReqInfo::FixedValue<2> { static const DWORD value; };
+const DWORD HERAReqInfo::FixedValue<2>::value = 0;
+
+template<> template<>
+struct HERAReqInfo::FixedValue<3> { static const DWORD_PTR value; };
+const DWORD_PTR HERAReqInfo::FixedValue<3>::value = 0;
+
 /* InternetQueryOptionA */
 
 typedef SslFunctionBroker<ID_InternetQueryOptionA,
                           decltype(InternetQueryOptionA)> InternetQueryOptionAFB;
 
 template<>
 ShouldHookFunc* const
 InternetQueryOptionAFB::BaseType::mShouldHook = &CheckQuirks<QUIRK_FLASH_HOOK_SSL>;
@@ -1305,16 +1328,19 @@ AddBrokeredFunctionHooks(FunctionHookArr
     FUN_HOOK(new HttpQueryInfoAFB("wininet.dll", "HttpQueryInfoA",
                                   &HttpQueryInfoA));
   aHooks[ID_HttpSendRequestA] =
     FUN_HOOK(new HttpSendRequestAFB("wininet.dll", "HttpSendRequestA",
                                     &HttpSendRequestA));
   aHooks[ID_HttpSendRequestExA] =
     FUN_HOOK(new HttpSendRequestExAFB("wininet.dll", "HttpSendRequestExA",
                                       &HttpSendRequestExA));
+  aHooks[ID_HttpEndRequestA] =
+    FUN_HOOK(new HttpEndRequestAFB("wininet.dll", "HttpEndRequestA",
+      &HttpEndRequestA));
   aHooks[ID_InternetQueryOptionA] =
     FUN_HOOK(new InternetQueryOptionAFB("wininet.dll", "InternetQueryOptionA",
                                         &InternetQueryOptionA));
   aHooks[ID_InternetErrorDlg] =
     FUN_HOOK(new InternetErrorDlgFB("wininet.dll", "InternetErrorDlg",
                                     InternetErrorDlg));
   aHooks[ID_AcquireCredentialsHandleA] =
     FUN_HOOK(new AcquireCredentialsHandleAFB("sspicli.dll",
--- a/dom/plugins/ipc/FunctionBrokerIPCUtils.h
+++ b/dom/plugins/ipc/FunctionBrokerIPCUtils.h
@@ -35,16 +35,17 @@ enum FunctionHookId
   , ID_InternetReadFile
   , ID_InternetWriteFile
   , ID_InternetSetOptionA
   , ID_HttpAddRequestHeadersA
   , ID_HttpOpenRequestA
   , ID_HttpQueryInfoA
   , ID_HttpSendRequestA
   , ID_HttpSendRequestExA
+  , ID_HttpEndRequestA
   , ID_InternetQueryOptionA
   , ID_InternetErrorDlg
   , ID_AcquireCredentialsHandleA
   , ID_QueryCredentialsAttributesA
   , ID_FreeCredentialsHandle
   , ID_PrintDlgW
   , ID_CreateMutexW
   , ID_FunctionHookCount
@@ -282,17 +283,17 @@ struct ParamTraits<OpenFileNameIPC>
         ReadParam(aMsg, aIter, &aResult->mFlagsEx)) {
       return true;
     }
     return false;
   }
 
   static void Log(const paramType& aParam, std::wstring* aLog)
   {
-    aLog->append(StringPrintf(L"[%S, %S, %S, %S]", aParam.mFilter.c_str(),
+    aLog->append(StringPrintf(L"[%ls, %ls, %ls, %ls]", aParam.mFilter.c_str(),
                               aParam.mCustomFilterIn.c_str(), aParam.mFile.c_str(),
                               aParam.mTitle.c_str()));
   }
 };
 
 template <>
 struct ParamTraits<OpenFileNameRetIPC>
 {
@@ -316,17 +317,17 @@ struct ParamTraits<OpenFileNameRetIPC>
         ReadParam(aMsg, aIter, &aResult->mFileExtension)) {
       return true;
     }
     return false;
   }
 
   static void Log(const paramType& aParam, std::wstring* aLog)
   {
-    aLog->append(StringPrintf(L"[%S, %S, %S, %d, %d]", aParam.mCustomFilterOut.c_str(),
+    aLog->append(StringPrintf(L"[%ls, %ls, %ls, %d, %d]", aParam.mCustomFilterOut.c_str(),
                               aParam.mFile.c_str(), aParam.mFileTitle.c_str(),
                               aParam.mFileOffset, aParam.mFileExtension));
   }
 };
 
 template <>
 struct ParamTraits<mozilla::plugins::GetFileNameFunc> :
   public ContiguousEnumSerializerInclusive<mozilla::plugins::GetFileNameFunc,
--- a/dom/serviceworkers/ServiceWorkerManager.cpp
+++ b/dom/serviceworkers/ServiceWorkerManager.cpp
@@ -2549,69 +2549,61 @@ ServiceWorkerManager::UpdateInternal(nsI
 
   RefPtr<UpdateJobCallback> cb = new UpdateJobCallback(aCallback);
   job->AppendResultCallback(cb);
 
   queue->ScheduleJob(job);
 }
 
 already_AddRefed<GenericPromise>
-ServiceWorkerManager::MaybeClaimClient(nsIDocument* aDocument,
+ServiceWorkerManager::MaybeClaimClient(const ClientInfo& aClientInfo,
                                        ServiceWorkerRegistrationInfo* aWorkerRegistration)
 {
   MOZ_DIAGNOSTIC_ASSERT(aWorkerRegistration);
 
   RefPtr<GenericPromise> ref;
 
   if (!aWorkerRegistration->GetActive()) {
     ref = GenericPromise::CreateAndReject(NS_ERROR_DOM_INVALID_STATE_ERR,
                                           __func__);
     return ref.forget();
   }
 
   // Same origin check
-  if (!aWorkerRegistration->Principal()->Equals(aDocument->NodePrincipal())) {
+  nsCOMPtr<nsIPrincipal> principal(aClientInfo.GetPrincipal());
+  if (!aWorkerRegistration->Principal()->Equals(principal)) {
     ref = GenericPromise::CreateAndReject(NS_ERROR_DOM_SECURITY_ERR, __func__);
     return ref.forget();
   }
 
-  Maybe<ClientInfo> clientInfo(aDocument->GetClientInfo());
-  if (NS_WARN_IF(clientInfo.isNothing())) {
-    ref = GenericPromise::CreateAndReject(NS_ERROR_DOM_INVALID_STATE_ERR,
-                                          __func__);
-    return ref.forget();
-  }
-
   // The registration that should be controlling the client
   RefPtr<ServiceWorkerRegistrationInfo> matchingRegistration =
-    GetServiceWorkerRegistrationInfo(aDocument);
+    GetServiceWorkerRegistrationInfo(aClientInfo);
 
   // The registration currently controlling the client
   RefPtr<ServiceWorkerRegistrationInfo> controllingRegistration;
-  GetClientRegistration(clientInfo.ref(),
-                        getter_AddRefs(controllingRegistration));
+  GetClientRegistration(aClientInfo, getter_AddRefs(controllingRegistration));
 
   if (aWorkerRegistration != matchingRegistration ||
       aWorkerRegistration == controllingRegistration) {
     ref = GenericPromise::CreateAndResolve(true, __func__);
     return ref.forget();
   }
 
-  ref = StartControllingClient(clientInfo.ref(), aWorkerRegistration);
+  ref = StartControllingClient(aClientInfo, aWorkerRegistration);
   return ref.forget();
 }
 
 already_AddRefed<GenericPromise>
-ServiceWorkerManager::MaybeClaimClient(nsIDocument* aDoc,
+ServiceWorkerManager::MaybeClaimClient(const ClientInfo& aClientInfo,
                                        const ServiceWorkerDescriptor& aServiceWorker)
 {
   RefPtr<GenericPromise> ref;
 
-  nsCOMPtr<nsIPrincipal> principal =
-    PrincipalInfoToPrincipal(aServiceWorker.PrincipalInfo());
+  nsCOMPtr<nsIPrincipal> principal = aServiceWorker.GetPrincipal();
   if (!principal) {
     ref = GenericPromise::CreateAndResolve(false, __func__);
     return ref.forget();
   }
 
   RefPtr<ServiceWorkerRegistrationInfo> registration =
     GetRegistration(principal, aServiceWorker.Scope());
 
@@ -2620,17 +2612,17 @@ ServiceWorkerManager::MaybeClaimClient(n
   // not propagated to this process yet.  For now, simply note that we
   // are done.  The fix for this is to move the SWM to the parent process
   // so there are no consistency errors.
   if (NS_WARN_IF(!registration) || NS_WARN_IF(!registration->GetActive())) {
     ref = GenericPromise::CreateAndResolve(false, __func__);
     return ref.forget();
   }
 
-  ref = MaybeClaimClient(aDoc, registration);
+  ref = MaybeClaimClient(aClientInfo, registration);
   return ref.forget();
 }
 
 void
 ServiceWorkerManager::SetSkipWaitingFlag(nsIPrincipal* aPrincipal,
                                          const nsCString& aScope,
                                          uint64_t aServiceWorkerID)
 {
--- a/dom/serviceworkers/ServiceWorkerManager.h
+++ b/dom/serviceworkers/ServiceWorkerManager.h
@@ -280,21 +280,21 @@ public:
               const nsString& aFilename,
               const nsString& aLine,
               uint32_t aLineNumber,
               uint32_t aColumnNumber,
               uint32_t aFlags,
               JSExnType aExnType);
 
   already_AddRefed<GenericPromise>
-  MaybeClaimClient(nsIDocument* aDocument,
+  MaybeClaimClient(const ClientInfo& aClientInfo,
                    ServiceWorkerRegistrationInfo* aWorkerRegistration);
 
   already_AddRefed<GenericPromise>
-  MaybeClaimClient(nsIDocument* aDoc,
+  MaybeClaimClient(const ClientInfo& aClientInfo,
                    const ServiceWorkerDescriptor& aServiceWorker);
 
   void
   SetSkipWaitingFlag(nsIPrincipal* aPrincipal, const nsCString& aScope,
                      uint64_t aServiceWorkerID);
 
   static already_AddRefed<ServiceWorkerManager>
   GetInstance();
--- a/dom/serviceworkers/ServiceWorkerUtils.cpp
+++ b/dom/serviceworkers/ServiceWorkerUtils.cpp
@@ -9,28 +9,24 @@
 #include "mozilla/Preferences.h"
 
 namespace mozilla {
 namespace dom {
 
 bool
 ServiceWorkerParentInterceptEnabled()
 {
-  // For right now we only support main thread.  In the future we could make
-  // this use an atomic bool if we need to support worker threads.
-  MOZ_ASSERT(NS_IsMainThread());
-
   static bool sInit = false;
-  static bool sEnabled;
+  static Atomic<bool> sEnabled;
 
   if (!sInit) {
     MOZ_ASSERT(NS_IsMainThread());
-    Preferences::AddBoolVarCache(&sEnabled,
-                                 "dom.serviceWorkers.parent_intercept",
-                                 false);
+    Preferences::AddAtomicBoolVarCache(&sEnabled,
+                                       "dom.serviceWorkers.parent_intercept",
+                                       false);
     sInit = true;
   }
 
   return sEnabled;
 }
 
 bool
 ServiceWorkerRegistrationDataIsValid(const ServiceWorkerRegistrationData& aData)
--- a/dom/webidl/DataTransfer.webidl
+++ b/dom/webidl/DataTransfer.webidl
@@ -2,17 +2,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/.
  *
  * The origin of this IDL file is:
  * http://www.whatwg.org/specs/web-apps/current-work/#the-datatransfer-interface
  */
 
-[ChromeConstructor(DOMString eventType, boolean isExternal)]
+[Constructor]
 interface DataTransfer {
            attribute DOMString dropEffect;
            attribute DOMString effectAllowed;
 
   readonly attribute DataTransferItemList items;
 
   void setDragImage(Element image, long x, long y);
 
--- a/gfx/angle/checkout/include/EGL/eglext_angle.h
+++ b/gfx/angle/checkout/include/EGL/eglext_angle.h
@@ -170,11 +170,16 @@ EGLAPI EGLint EGLAPIENTRY eglProgramCach
 #define EGL_ANGLE_iosurface_client_buffer 1
 #define EGL_IOSURFACE_ANGLE 0x3454
 #define EGL_IOSURFACE_PLANE_ANGLE 0x345A
 #define EGL_TEXTURE_RECTANGLE_ANGLE 0x345B
 #define EGL_TEXTURE_TYPE_ANGLE 0x345C
 #define EGL_TEXTURE_INTERNAL_FORMAT_ANGLE 0x345D
 #endif /* EGL_ANGLE_iosurface_client_buffer */
 
+#ifndef EGL_ANGLE_create_context_extensions_enabled
+#define EGL_ANGLE_create_context_extensions_enabled 1
+#define EGL_EXTENSIONS_ENABLED_ANGLE 0x345F
+#endif /* EGL_ANGLE_create_context_extensions_enabled */
+
 // clang-format on
 
 #endif  // INCLUDE_EGL_EGLEXT_ANGLE_
--- a/gfx/angle/checkout/include/GLSLANG/ShaderLang.h
+++ b/gfx/angle/checkout/include/GLSLANG/ShaderLang.h
@@ -20,17 +20,17 @@
 // and the shading language compiler.
 //
 
 // Note: make sure to increment ANGLE_SH_VERSION when changing ShaderVars.h
 #include "ShaderVars.h"
 
 // Version number for shader translation API.
 // It is incremented every time the API changes.
-#define ANGLE_SH_VERSION 196
+#define ANGLE_SH_VERSION 197
 
 enum ShShaderSpec
 {
     SH_GLES2_SPEC,
     SH_WEBGL_SPEC,
 
     SH_GLES3_SPEC,
     SH_WEBGL2_SPEC,
--- a/gfx/angle/checkout/include/GLSLANG/ShaderVars.h
+++ b/gfx/angle/checkout/include/GLSLANG/ShaderVars.h
@@ -121,17 +121,22 @@ struct ShaderVariable
     // Offset of this variable in parent arrays. In case the parent is an array of arrays, the
     // offset is outerArrayElement * innerArraySize + innerArrayElement.
     // For example, if there's a variable declared as size 3 array of size 4 array of int:
     //   int a[3][4];
     // then the flattenedOffsetInParentArrays of a[2] would be 2.
     // and flattenedOffsetInParentArrays of a[2][1] would be 2*4 + 1 = 9.
     unsigned int flattenedOffsetInParentArrays;
 
+    // Static use means that the variable is accessed somewhere in the shader source.
     bool staticUse;
+    // A variable is active unless the compiler determined that it is not accessed by the shader.
+    // All active variables are statically used, but not all statically used variables are
+    // necessarily active. GLES 3.0.5 section 2.12.6. GLES 3.1 section 7.3.1.
+    bool active;
     std::vector<ShaderVariable> fields;
     std::string structName;
 
   protected:
     bool isSameVariableAtLinkTime(const ShaderVariable &other,
                                   bool matchPrecision,
                                   bool matchName) const;
 
@@ -274,16 +279,17 @@ struct InterfaceBlock
     BlockLayoutType layout;
 
     // Deprecated. Matrix packing should only be queried from individual fields of the block.
     // TODO(oetuaho): Remove this once it is no longer used in Chromium.
     bool isRowMajorLayout;
 
     int binding;
     bool staticUse;
+    bool active;
     BlockType blockType;
     std::vector<InterfaceBlockField> fields;
 };
 
 struct WorkGroupSize
 {
     // Must have a trivial default constructor since it is used in YYSTYPE.
     WorkGroupSize() = default;
--- a/gfx/angle/checkout/include/KHR/khrplatform.h
+++ b/gfx/angle/checkout/include/KHR/khrplatform.h
@@ -1,13 +1,13 @@
 #ifndef __khrplatform_h_
 #define __khrplatform_h_
 
 /*
-** Copyright (c) 2008-2009 The Khronos Group Inc.
+** Copyright (c) 2008-2018 The Khronos Group Inc.
 **
 ** Permission is hereby granted, free of charge, to any person obtaining a
 ** copy of this software and/or associated documentation files (the
 ** "Materials"), to deal in the Materials without restriction, including
 ** without limitation the rights to use, copy, modify, merge, publish,
 ** distribute, sublicense, and/or sell copies of the Materials, and to
 ** permit persons to whom the Materials are furnished to do so, subject to
 ** the following conditions:
@@ -21,28 +21,26 @@
 ** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 ** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 ** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
 */
 
 /* Khronos platform-specific types and definitions.
  *
- * $Revision: 32517 $ on $Date: 2016-03-11 02:41:19 -0800 (Fri, 11 Mar 2016) $
+ * The master copy of khrplatform.h is maintained in the Khronos EGL
+ * Registry repository at https://github.com/KhronosGroup/EGL-Registry
+ * The last semantic modification to khrplatform.h was at commit ID:
+ *      67a3e0864c2d75ea5287b9f3d2eb74a745936692
  *
  * Adopters may modify this file to suit their platform. Adopters are
  * encouraged to submit platform specific modifications to the Khronos
  * group so that they can be included in future versions of this file.
- * Please submit changes by sending them to the public Khronos Bugzilla
- * (http://khronos.org/bugzilla) by filing a bug against product
- * "Khronos (general)" component "Registry".
- *
- * A predefined template which fills in some of the bug fields can be
- * reached using http://tinyurl.com/khrplatform-h-bugreport, but you
- * must create a Bugzilla login first.
+ * Please submit changes by filing pull requests or issues on
+ * the EGL Registry repository linked above.
  *
  *
  * See the Implementer's Guidelines for information about where this file
  * should be located on your system and for more details of its use:
  *    http://www.khronos.org/registry/implementers_guide.pdf
  *
  * This file should be included as
  *        #include <KHR/khrplatform.h>
@@ -97,18 +95,17 @@
  *-------------------------------------------------------------------------
  * This precedes the return type of the function in the function prototype.
  */
 #if defined(_WIN32) && !defined(__SCITECH_SNAP__)
 #   define KHRONOS_APICALL __declspec(dllimport)
 #elif defined (__SYMBIAN32__)
 #   define KHRONOS_APICALL IMPORT_C
 #elif defined(__ANDROID__)
-#   include <sys/cdefs.h>
-#   define KHRONOS_APICALL __attribute__((visibility("default"))) __NDK_FPABI__
+#   define KHRONOS_APICALL __attribute__((visibility("default")))
 #else
 #   define KHRONOS_APICALL
 #endif
 
 /*-------------------------------------------------------------------------
  * Definition of KHRONOS_APIENTRY
  *-------------------------------------------------------------------------
  * This follows the return type of the function  and precedes the function
@@ -277,9 +274,9 @@ typedef khronos_int64_t        khronos_s
  * comparisons should not be made against KHRONOS_TRUE.
  */
 typedef enum {
     KHRONOS_FALSE = 0,
     KHRONOS_TRUE  = 1,
     KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM
 } khronos_boolean_enum_t;
 
-#endif /* __khrplatform_h_ */
\ No newline at end of file
+#endif /* __khrplatform_h_ */
--- a/gfx/angle/checkout/out/gen/angle/id/commit.h
+++ b/gfx/angle/checkout/out/gen/angle/id/commit.h
@@ -1,3 +1,3 @@
-#define ANGLE_COMMIT_HASH "fcbca0e873c3"
+#define ANGLE_COMMIT_HASH "595ccab4acc3"
 #define ANGLE_COMMIT_HASH_SIZE 12
-#define ANGLE_COMMIT_DATE "2018-04-20 16:07:35 -0700"
+#define ANGLE_COMMIT_DATE "2018-06-01 17:26:22 -0700"
--- a/gfx/angle/checkout/src/common/Color.h
+++ b/gfx/angle/checkout/src/common/Color.h
@@ -10,23 +10,26 @@
 #define COMMON_COLOR_H_
 
 namespace angle
 {
 
 template <typename T>
 struct Color
 {
+    Color();
+    Color(T r, T g, T b, T a);
+
+    const T *data() const { return &red; }
+    T *ptr() { return &red; }
+
     T red;
     T green;
     T blue;
     T alpha;
-
-    Color();
-    Color(T r, T g, T b, T a);
 };
 
 template <typename T>
 bool operator==(const Color<T> &a, const Color<T> &b);
 
 template <typename T>
 bool operator!=(const Color<T> &a, const Color<T> &b);
 
new file mode 100644
--- /dev/null
+++ b/gfx/angle/checkout/src/common/FixedVector.h
@@ -0,0 +1,331 @@
+//
+// Copyright 2018 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// FixedVector.h:
+//   A vector class with a maximum size and fixed storage.
+//
+
+#ifndef COMMON_FIXEDVECTOR_H_
+#define COMMON_FIXEDVECTOR_H_
+
+#include "common/debug.h"
+
+#include <algorithm>
+#include <array>
+#include <initializer_list>
+
+namespace angle
+{
+template <class T, size_t N, class Storage = std::array<T, N>>
+class FixedVector final
+{
+  public:
+    using value_type             = typename Storage::value_type;
+    using size_type              = typename Storage::size_type;
+    using reference              = typename Storage::reference;
+    using const_reference        = typename Storage::const_reference;
+    using pointer                = typename Storage::pointer;
+    using const_pointer          = typename Storage::const_pointer;
+    using iterator               = typename Storage::iterator;
+    using const_iterator         = typename Storage::const_iterator;
+    using reverse_iterator       = typename Storage::reverse_iterator;
+    using const_reverse_iterator = typename Storage::const_reverse_iterator;
+
+    FixedVector();
+    FixedVector(size_type count, const value_type &value);
+    FixedVector(size_type count);
+
+    FixedVector(const FixedVector<T, N, Storage> &other);
+    FixedVector(FixedVector<T, N, Storage> &&other);
+    FixedVector(std::initializer_list<value_type> init);
+
+    FixedVector<T, N, Storage> &operator=(const FixedVector<T, N, Storage> &other);
+    FixedVector<T, N, Storage> &operator=(FixedVector<T, N, Storage> &&other);
+    FixedVector<T, N, Storage> &operator=(std::initializer_list<value_type> init);
+
+    ~FixedVector();
+
+    reference at(size_type pos);
+    const_reference at(size_type pos) const;
+
+    reference operator[](size_type pos);
+    const_reference operator[](size_type pos) const;
+
+    pointer data();
+    const_pointer data() const;
+
+    iterator begin();
+    const_iterator begin() const;
+
+    iterator end();
+    const_iterator end() const;
+
+    bool empty() const;
+    size_type size() const;
+    size_type max_size() const;
+
+    void clear();
+
+    void push_back(const value_type &value);
+    void push_back(value_type &&value);
+
+    void pop_back();
+    reference back();
+    const_reference back() const;
+
+    void swap(FixedVector<T, N, Storage> &other);
+
+    void resize(size_type count);
+    void resize(size_type count, const value_type &value);
+
+    bool full() const;
+
+  private:
+    void assign_from_initializer_list(std::initializer_list<value_type> init);
+
+    Storage mStorage;
+    size_type mSize = 0;
+};
+
+template <class T, size_t N, class Storage>
+bool operator==(const FixedVector<T, N, Storage> &a, const FixedVector<T, N, Storage> &b)
+{
+    return a.size() == b.size() && std::equal(a.begin(), a.end(), b.begin());
+}
+
+template <class T, size_t N, class Storage>
+bool operator!=(const FixedVector<T, N, Storage> &a, const FixedVector<T, N, Storage> &b)
+{
+    return !(a == b);
+}
+
+template <class T, size_t N, class Storage>
+FixedVector<T, N, Storage>::FixedVector() = default;
+
+template <class T, size_t N, class Storage>
+FixedVector<T, N, Storage>::FixedVector(size_type count, const value_type &value) : mSize(count)
+{
+    ASSERT(count <= N);
+    std::fill(mStorage.begin(), mStorage.begin() + count, value);
+}
+
+template <class T, size_t N, class Storage>
+FixedVector<T, N, Storage>::FixedVector(size_type count) : mSize(count)
+{
+    ASSERT(count <= N);
+}
+
+template <class T, size_t N, class Storage>
+FixedVector<T, N, Storage>::FixedVector(const FixedVector<T, N, Storage> &other) = default;
+
+template <class T, size_t N, class Storage>
+FixedVector<T, N, Storage>::FixedVector(FixedVector<T, N, Storage> &&other) = default;
+
+template <class T, size_t N, class Storage>
+FixedVector<T, N, Storage>::FixedVector(std::initializer_list<value_type> init)
+{
+    ASSERT(init.size() <= N);
+    assign_from_initializer_list(init);
+}
+
+template <class T, size_t N, class Storage>
+FixedVector<T, N, Storage> &FixedVector<T, N, Storage>::operator=(
+    const FixedVector<T, N, Storage> &other) = default;
+
+template <class T, size_t N, class Storage>
+FixedVector<T, N, Storage> &FixedVector<T, N, Storage>::operator=(
+    FixedVector<T, N, Storage> &&other) = default;
+
+template <class T, size_t N, class Storage>
+FixedVector<T, N, Storage> &FixedVector<T, N, Storage>::operator=(
+    std::initializer_list<value_type> init)
+{
+    clear();
+    ASSERT(init.size() <= N);
+    assign_from_initializer_list(init);
+    return this;
+}
+
+template <class T, size_t N, class Storage>
+FixedVector<T, N, Storage>::~FixedVector()
+{
+    clear();
+}
+
+template <class T, size_t N, class Storage>
+typename FixedVector<T, N, Storage>::reference FixedVector<T, N, Storage>::at(size_type pos)
+{
+    ASSERT(pos < N);
+    return mStorage.at(pos);
+}
+
+template <class T, size_t N, class Storage>
+typename FixedVector<T, N, Storage>::const_reference FixedVector<T, N, Storage>::at(
+    size_type pos) const
+{
+    ASSERT(pos < N);
+    return mStorage.at(pos);
+}
+
+template <class T, size_t N, class Storage>
+typename FixedVector<T, N, Storage>::reference FixedVector<T, N, Storage>::operator[](size_type pos)
+{
+    ASSERT(pos < N);
+    return mStorage[pos];
+}
+
+template <class T, size_t N, class Storage>
+typename FixedVector<T, N, Storage>::const_reference FixedVector<T, N, Storage>::operator[](
+    size_type pos) const
+{
+    ASSERT(pos < N);
+    return mStorage[pos];
+}
+
+template <class T, size_t N, class Storage>
+typename FixedVector<T, N, Storage>::const_pointer angle::FixedVector<T, N, Storage>::data() const
+{
+    return mStorage.data();
+}
+
+template <class T, size_t N, class Storage>
+typename FixedVector<T, N, Storage>::pointer angle::FixedVector<T, N, Storage>::data()
+{
+    return mStorage.data();
+}
+
+template <class T, size_t N, class Storage>
+typename FixedVector<T, N, Storage>::iterator FixedVector<T, N, Storage>::begin()
+{
+    return mStorage.begin();
+}
+
+template <class T, size_t N, class Storage>
+typename FixedVector<T, N, Storage>::const_iterator FixedVector<T, N, Storage>::begin() const
+{
+    return mStorage.begin();
+}
+
+template <class T, size_t N, class Storage>
+typename FixedVector<T, N, Storage>::iterator FixedVector<T, N, Storage>::end()
+{
+    return mStorage.begin() + mSize;
+}
+
+template <class T, size_t N, class Storage>
+typename FixedVector<T, N, Storage>::const_iterator FixedVector<T, N, Storage>::end() const
+{
+    return mStorage.begin() + mSize;
+}
+
+template <class T, size_t N, class Storage>
+bool FixedVector<T, N, Storage>::empty() const
+{
+    return mSize == 0;
+}
+
+template <class T, size_t N, class Storage>
+typename FixedVector<T, N, Storage>::size_type FixedVector<T, N, Storage>::size() const
+{
+    return mSize;
+}
+
+template <class T, size_t N, class Storage>
+typename FixedVector<T, N, Storage>::size_type FixedVector<T, N, Storage>::max_size() const
+{
+    return N;
+}
+
+template <class T, size_t N, class Storage>
+void FixedVector<T, N, Storage>::clear()
+{
+    resize(0);
+}
+
+template <class T, size_t N, class Storage>
+void FixedVector<T, N, Storage>::push_back(const value_type &value)
+{
+    ASSERT(mSize < N);
+    mStorage[mSize] = value;
+    mSize++;
+}
+
+template <class T, size_t N, class Storage>
+void FixedVector<T, N, Storage>::push_back(value_type &&value)
+{
+    ASSERT(mSize < N);
+    mStorage[mSize] = std::move(value);
+    mSize++;
+}
+
+template <class T, size_t N, class Storage>
+void FixedVector<T, N, Storage>::pop_back()
+{
+    ASSERT(mSize > 0);
+    mSize--;
+}
+
+template <class T, size_t N, class Storage>
+typename FixedVector<T, N, Storage>::reference FixedVector<T, N, Storage>::back()
+{
+    ASSERT(mSize > 0);
+    return mStorage[mSize - 1];
+}
+
+template <class T, size_t N, class Storage>
+typename FixedVector<T, N, Storage>::const_reference FixedVector<T, N, Storage>::back() const
+{
+    ASSERT(mSize > 0);
+    return mStorage[mSize - 1];
+}
+
+template <class T, size_t N, class Storage>
+void FixedVector<T, N, Storage>::swap(FixedVector<T, N, Storage> &other)
+{
+    std::swap(mSize, other.mSize);
+    std::swap(mStorage, other.mStorage);
+}
+
+template <class T, size_t N, class Storage>
+void FixedVector<T, N, Storage>::resize(size_type count)
+{
+    resize(count, value_type());
+}
+
+template <class T, size_t N, class Storage>
+void FixedVector<T, N, Storage>::resize(size_type count, const value_type &value)
+{
+    ASSERT(count <= N);
+    while (mSize > count)
+    {
+        mSize--;
+        mStorage[mSize] = T();
+    }
+    while (mSize < count)
+    {
+        mStorage[mSize] = value;
+        mSize++;
+    }
+}
+
+template <class T, size_t N, class Storage>
+void FixedVector<T, N, Storage>::assign_from_initializer_list(
+    std::initializer_list<value_type> init)
+{
+    for (auto element : init)
+    {
+        mStorage[mSize] = std::move(element);
+        mSize++;
+    }
+}
+
+template <class T, size_t N, class Storage>
+bool FixedVector<T, N, Storage>::full() const
+{
+    return (mSize == N);
+}
+}  // namespace angle
+
+#endif  // COMMON_FIXEDVECTOR_H_
--- a/gfx/angle/checkout/src/common/angleutils.h
+++ b/gfx/angle/checkout/src/common/angleutils.h
@@ -186,16 +186,17 @@ std::string ToString(const T &value)
     return o.str();
 }
 
 // snprintf is not defined with MSVC prior to to msvc14
 #if defined(_MSC_VER) && _MSC_VER < 1900
 #define snprintf _snprintf
 #endif
 
+#define GL_A1RGB5_ANGLEX 0x6AC5
 #define GL_BGRX8_ANGLEX 0x6ABA
 #define GL_BGR565_ANGLEX 0x6ABB
 #define GL_BGRA4_ANGLEX 0x6ABC
 #define GL_BGR5_A1_ANGLEX 0x6ABD
 #define GL_INT_64_ANGLEX 0x6ABE
 #define GL_UINT_64_ANGLEX 0x6ABF
 #define GL_BGRA8_SRGB_ANGLEX 0x6AC0
 
--- a/gfx/angle/checkout/src/common/bitset_utils.h
+++ b/gfx/angle/checkout/src/common/bitset_utils.h
@@ -35,20 +35,20 @@ class BitSetT final
             mParent->set(mBit, x);
             return *this;
         }
         explicit operator bool() const { return mParent->test(mBit); }
 
       private:
         friend class BitSetT;
 
-        Reference(BitSetT *parent, std::size_t bit) : mParent(parent), mBit(bit) {}
+        Reference(BitSetT *parent, ParamT bit) : mParent(parent), mBit(bit) {}
 
         BitSetT *mParent;
-        std::size_t mBit;
+        ParamT mBit;
     };
 
     class Iterator final
     {
       public:
         Iterator(const BitSetT &bits);
         Iterator &operator++();
 
@@ -59,18 +59,17 @@ class BitSetT final
       private:
         std::size_t getNextBit();
 
         BitSetT mBitsCopy;
         std::size_t mCurrentBit;
     };
 
     BitSetT();
-    BitSetT(BitsT value);
-    ~BitSetT();
+    constexpr explicit BitSetT(BitsT value);
 
     BitSetT(const BitSetT &other);
     BitSetT &operator=(const BitSetT &other);
 
     bool operator==(const BitSetT &other) const;
     bool operator!=(const BitSetT &other) const;
 
     constexpr bool operator[](ParamT pos) const;
@@ -85,16 +84,20 @@ class BitSetT final
 
     constexpr std::size_t size() const { return N; }
 
     BitSetT &operator&=(const BitSetT &other);
     BitSetT &operator|=(const BitSetT &other);
     BitSetT &operator^=(const BitSetT &other);
     BitSetT operator~() const;
 
+    BitSetT &operator&=(BitsT value);
+    BitSetT &operator|=(BitsT value);
+    BitSetT &operator^=(BitsT value);
+
     BitSetT operator<<(std::size_t pos) const;
     BitSetT &operator<<=(std::size_t pos);
     BitSetT operator>>(std::size_t pos) const;
     BitSetT &operator>>=(std::size_t pos);
 
     BitSetT &set();
     BitSetT &set(ParamT pos, bool value = true);
 
@@ -110,17 +113,21 @@ class BitSetT final
     Iterator begin() const { return Iterator(*this); }
     Iterator end() const { return Iterator(BitSetT()); }
 
   private:
     constexpr static BitsT Bit(ParamT x)
     {
         return (static_cast<BitsT>(1) << static_cast<size_t>(x));
     }
-    constexpr static BitsT Mask(std::size_t x) { return ((Bit(x - 1) - 1) << 1) + 1; }
+    // Produces a mask of ones up to the "x"th bit.
+    constexpr static BitsT Mask(std::size_t x)
+    {
+        return ((Bit(static_cast<ParamT>(x - 1)) - 1) << 1) + 1;
+    }
 
     BitsT mBits;
 };
 
 template <size_t N>
 class IterableBitSet : public std::bitset<N>
 {
   public:
@@ -208,22 +215,17 @@ unsigned long IterableBitSet<N>::Iterato
 template <size_t N, typename BitsT, typename ParamT>
 BitSetT<N, BitsT, ParamT>::BitSetT() : mBits(0)
 {
     static_assert(N > 0, "Bitset type cannot support zero bits.");
     static_assert(N <= sizeof(BitsT) * 8, "Bitset type cannot support a size this large.");
 }
 
 template <size_t N, typename BitsT, typename ParamT>
-BitSetT<N, BitsT, ParamT>::BitSetT(BitsT value) : mBits(value & Mask(N))
-{
-}
-
-template <size_t N, typename BitsT, typename ParamT>
-BitSetT<N, BitsT, ParamT>::~BitSetT()
+constexpr BitSetT<N, BitsT, ParamT>::BitSetT(BitsT value) : mBits(value & Mask(N))
 {
 }
 
 template <size_t N, typename BitsT, typename ParamT>
 BitSetT<N, BitsT, ParamT>::BitSetT(const BitSetT &other) : mBits(other.mBits)
 {
 }
 
@@ -308,16 +310,37 @@ BitSetT<N, BitsT, ParamT> &BitSetT<N, Bi
 
 template <size_t N, typename BitsT, typename ParamT>
 BitSetT<N, BitsT, ParamT> BitSetT<N, BitsT, ParamT>::operator~() const
 {
     return BitSetT<N, BitsT, ParamT>(~mBits & Mask(N));
 }
 
 template <size_t N, typename BitsT, typename ParamT>
+BitSetT<N, BitsT, ParamT> &BitSetT<N, BitsT, ParamT>::operator&=(BitsT value)
+{
+    mBits &= value;
+    return *this;
+}
+
+template <size_t N, typename BitsT, typename ParamT>
+BitSetT<N, BitsT, ParamT> &BitSetT<N, BitsT, ParamT>::operator|=(BitsT value)
+{
+    mBits |= value;
+    return *this;
+}
+
+template <size_t N, typename BitsT, typename ParamT>
+BitSetT<N, BitsT, ParamT> &BitSetT<N, BitsT, ParamT>::operator^=(BitsT value)
+{
+    mBits ^= value;
+    return *this;
+}
+
+template <size_t N, typename BitsT, typename ParamT>
 BitSetT<N, BitsT, ParamT> BitSetT<N, BitsT, ParamT>::operator<<(std::size_t pos) const
 {
     return BitSetT<N, BitsT, ParamT>((mBits << pos) & Mask(N));
 }
 
 template <size_t N, typename BitsT, typename ParamT>
 BitSetT<N, BitsT, ParamT> &BitSetT<N, BitsT, ParamT>::operator<<=(std::size_t pos)
 {
--- a/gfx/angle/checkout/src/common/mathutil.h
+++ b/gfx/angle/checkout/src/common/mathutil.h
@@ -4,57 +4,59 @@
 // found in the LICENSE file.
 //
 
 // mathutil.h: Math and bit manipulation functions.
 
 #ifndef COMMON_MATHUTIL_H_
 #define COMMON_MATHUTIL_H_
 
-#include <limits>
-#include <algorithm>
 #include <math.h>
-#include <string.h>
 #include <stdint.h>
 #include <stdlib.h>
+#include <string.h>
+#include <algorithm>
+#include <limits>
 
 #include <anglebase/numerics/safe_math.h>
 
 #include "common/debug.h"
 #include "common/platform.h"
 
 namespace angle
 {
 using base::CheckedNumeric;
 using base::IsValueInRangeForNumericType;
 }
 
 namespace gl
 {
 
-const unsigned int Float32One = 0x3F800000;
+const unsigned int Float32One   = 0x3F800000;
 const unsigned short Float16One = 0x3C00;
 
-template<typename T>
+template <typename T>
 inline bool isPow2(T x)
 {
     static_assert(std::is_integral<T>::value, "isPow2 must be called on an integer type.");
     return (x & (x - 1)) == 0 && (x != 0);
 }
 
 inline int log2(int x)
 {
     int r = 0;
-    while ((x >> r) > 1) r++;
+    while ((x >> r) > 1)
+        r++;
     return r;
 }
 
 inline unsigned int ceilPow2(unsigned int x)
 {
-    if (x != 0) x--;
+    if (x != 0)
+        x--;
     x |= x >> 1;
     x |= x >> 2;
     x |= x >> 4;
     x |= x >> 8;
     x |= x >> 16;
     x++;
 
     return x;
@@ -103,29 +105,29 @@ inline unsigned int clampCast(bool value
 }
 
 template <>
 inline int clampCast(bool value)
 {
     return static_cast<int>(value);
 }
 
-template<typename T, typename MIN, typename MAX>
+template <typename T, typename MIN, typename MAX>
 inline T clamp(T x, MIN min, MAX max)
 {
     // Since NaNs fail all comparison tests, a NaN value will default to min
     return x > min ? (x > max ? max : x) : min;
 }
 
 inline float clamp01(float x)
 {
     return clamp(x, 0.0f, 1.0f);
 }
 
-template<const int n>
+template <const int n>
 inline unsigned int unorm(float x)
 {
     const unsigned int max = 0xFFFFFFFF >> (32 - n);
 
     if (x > 1)
     {
         return max;
     }
@@ -137,17 +139,17 @@ inline unsigned int unorm(float x)
     {
         return (unsigned int)(max * x + 0.5f);
     }
 }
 
 inline bool supportsSSE2()
 {
 #if defined(ANGLE_USE_SSE)
-    static bool checked = false;
+    static bool checked  = false;
     static bool supports = false;
 
     if (checked)
     {
         return supports;
     }
 
 #if defined(ANGLE_PLATFORM_WINDOWS) && !defined(_M_ARM)
@@ -177,79 +179,82 @@ destType bitCast(const sourceType &sourc
     destType output;
     memcpy(&output, &source, copySize);
     return output;
 }
 
 inline unsigned short float32ToFloat16(float fp32)
 {
     unsigned int fp32i = bitCast<unsigned int>(fp32);
-    unsigned int sign = (fp32i & 0x80000000) >> 16;
-    unsigned int abs = fp32i & 0x7FFFFFFF;
+    unsigned int sign  = (fp32i & 0x80000000) >> 16;
+    unsigned int abs   = fp32i & 0x7FFFFFFF;
 
-    if(abs > 0x47FFEFFF)   // Infinity
+    if (abs > 0x47FFEFFF)  // Infinity
     {
         return static_cast<unsigned short>(sign | 0x7FFF);
     }
-    else if(abs < 0x38800000)   // Denormal
+    else if (abs < 0x38800000)  // Denormal
     {
         unsigned int mantissa = (abs & 0x007FFFFF) | 0x00800000;
-        int e = 113 - (abs >> 23);
+        int e                 = 113 - (abs >> 23);
 
-        if(e < 24)
+        if (e < 24)
         {
             abs = mantissa >> e;
         }
         else
         {
             abs = 0;
         }
 
         return static_cast<unsigned short>(sign | (abs + 0x00000FFF + ((abs >> 13) & 1)) >> 13);
     }
     else
     {
-        return static_cast<unsigned short>(sign | (abs + 0xC8000000 + 0x00000FFF + ((abs >> 13) & 1)) >> 13);
+        return static_cast<unsigned short>(
+            sign | (abs + 0xC8000000 + 0x00000FFF + ((abs >> 13) & 1)) >> 13);
     }
 }
 
 float float16ToFloat32(unsigned short h);
 
 unsigned int convertRGBFloatsTo999E5(float red, float green, float blue);
 void convert999E5toRGBFloats(unsigned int input, float *red, float *green, float *blue);
 
 inline unsigned short float32ToFloat11(float fp32)
 {
-    const unsigned int float32MantissaMask = 0x7FFFFF;
-    const unsigned int float32ExponentMask = 0x7F800000;
-    const unsigned int float32SignMask = 0x80000000;
-    const unsigned int float32ValueMask = ~float32SignMask;
+    const unsigned int float32MantissaMask     = 0x7FFFFF;
+    const unsigned int float32ExponentMask     = 0x7F800000;
+    const unsigned int float32SignMask         = 0x80000000;
+    const unsigned int float32ValueMask        = ~float32SignMask;
     const unsigned int float32ExponentFirstBit = 23;
-    const unsigned int float32ExponentBias = 127;
+    const unsigned int float32ExponentBias     = 127;
 
-    const unsigned short float11Max = 0x7BF;
+    const unsigned short float11Max          = 0x7BF;
     const unsigned short float11MantissaMask = 0x3F;
     const unsigned short float11ExponentMask = 0x7C0;
-    const unsigned short float11BitMask = 0x7FF;
-    const unsigned int float11ExponentBias = 14;
+    const unsigned short float11BitMask      = 0x7FF;
+    const unsigned int float11ExponentBias   = 14;
 
     const unsigned int float32Maxfloat11 = 0x477E0000;
     const unsigned int float32Minfloat11 = 0x38800000;
 
     const unsigned int float32Bits = bitCast<unsigned int>(fp32);
-    const bool float32Sign = (float32Bits & float32SignMask) == float32SignMask;
+    const bool float32Sign         = (float32Bits & float32SignMask) == float32SignMask;
 
     unsigned int float32Val = float32Bits & float32ValueMask;
 
     if ((float32Val & float32ExponentMask) == float32ExponentMask)
     {
         // INF or NAN
         if ((float32Val & float32MantissaMask) != 0)
         {
-            return float11ExponentMask | (((float32Val >> 17) | (float32Val >> 11) | (float32Val >> 6) | (float32Val)) & float11MantissaMask);
+            return float11ExponentMask |
+                   (((float32Val >> 17) | (float32Val >> 11) | (float32Val >> 6) | (float32Val)) &
+                    float11MantissaMask);
         }
         else if (float32Sign)
         {
             // -INF is clamped to 0 since float11 is positive only
             return 0;
         }
         else
         {
@@ -267,58 +272,62 @@ inline unsigned short float32ToFloat11(f
         return float11Max;
     }
     else
     {
         if (float32Val < float32Minfloat11)
         {
             // The number is too small to be represented as a normalized float11
             // Convert it to a denormalized value.
-            const unsigned int shift = (float32ExponentBias - float11ExponentBias) - (float32Val >> float32ExponentFirstBit);
-            float32Val = ((1 << float32ExponentFirstBit) | (float32Val & float32MantissaMask)) >> shift;
+            const unsigned int shift = (float32ExponentBias - float11ExponentBias) -
+                                       (float32Val >> float32ExponentFirstBit);
+            float32Val =
+                ((1 << float32ExponentFirstBit) | (float32Val & float32MantissaMask)) >> shift;
         }
         else
         {
             // Rebias the exponent to represent the value as a normalized float11
             float32Val += 0xC8000000;
         }
 
         return ((float32Val + 0xFFFF + ((float32Val >> 17) & 1)) >> 17) & float11BitMask;
     }
 }
 
 inline unsigned short float32ToFloat10(float fp32)
 {
-    const unsigned int float32MantissaMask = 0x7FFFFF;
-    const unsigned int float32ExponentMask = 0x7F800000;
-    const unsigned int float32SignMask = 0x80000000;
-    const unsigned int float32ValueMask = ~float32SignMask;
+    const unsigned int float32MantissaMask     = 0x7FFFFF;
+    const unsigned int float32ExponentMask     = 0x7F800000;
+    const unsigned int float32SignMask         = 0x80000000;
+    const unsigned int float32ValueMask        = ~float32SignMask;
     const unsigned int float32ExponentFirstBit = 23;
-    const unsigned int float32ExponentBias = 127;
+    const unsigned int float32ExponentBias     = 127;
 
-    const unsigned short float10Max = 0x3DF;
+    const unsigned short float10Max          = 0x3DF;
     const unsigned short float10MantissaMask = 0x1F;
     const unsigned short float10ExponentMask = 0x3E0;
-    const unsigned short float10BitMask = 0x3FF;
-    const unsigned int float10ExponentBias = 14;
+    const unsigned short float10BitMask      = 0x3FF;
+    const unsigned int float10ExponentBias   = 14;
 
     const unsigned int float32Maxfloat10 = 0x477C0000;
     const unsigned int float32Minfloat10 = 0x38800000;
 
     const unsigned int float32Bits = bitCast<unsigned int>(fp32);
-    const bool float32Sign = (float32Bits & float32SignMask) == float32SignMask;
+    const bool float32Sign         = (float32Bits & float32SignMask) == float32SignMask;
 
     unsigned int float32Val = float32Bits & float32ValueMask;
 
     if ((float32Val & float32ExponentMask) == float32ExponentMask)
     {
         // INF or NAN
         if ((float32Val & float32MantissaMask) != 0)
         {
-            return float10ExponentMask | (((float32Val >> 18) | (float32Val >> 13) | (float32Val >> 3) | (float32Val)) & float10MantissaMask);
+            return float10ExponentMask |
+                   (((float32Val >> 18) | (float32Val >> 13) | (float32Val >> 3) | (float32Val)) &
+                    float10MantissaMask);
         }
         else if (float32Sign)
         {
             // -INF is clamped to 0 since float11 is positive only
             return 0;
         }
         else
         {
@@ -336,18 +345,20 @@ inline unsigned short float32ToFloat10(f
         return float10Max;
     }
     else
     {
         if (float32Val < float32Minfloat10)
         {
             // The number is too small to be represented as a normalized float11
             // Convert it to a denormalized value.
-            const unsigned int shift = (float32ExponentBias - float10ExponentBias) - (float32Val >> float32ExponentFirstBit);
-            float32Val = ((1 << float32ExponentFirstBit) | (float32Val & float32MantissaMask)) >> shift;
+            const unsigned int shift = (float32ExponentBias - float10ExponentBias) -
+                                       (float32Val >> float32ExponentFirstBit);
+            float32Val =
+                ((1 << float32ExponentFirstBit) | (float32Val & float32MantissaMask)) >> shift;
         }
         else
         {
             // Rebias the exponent to represent the value as a normalized float11
             float32Val += 0xC8000000;
         }
 
         return ((float32Val + 0x1FFFF + ((float32Val >> 18) & 1)) >> 18) & float10BitMask;
@@ -374,22 +385,21 @@ inline float float11ToFloat32(unsigned s
         {
             // The value is denormalized
             exponent = 1;
 
             do
             {
                 exponent--;
                 mantissa <<= 1;
-            }
-            while ((mantissa & 0x40) == 0);
+            } while ((mantissa & 0x40) == 0);
 
             mantissa = mantissa & 0x3F;
         }
-        else // The value is zero
+        else  // The value is zero
         {
             exponent = static_cast<unsigned short>(-112);
         }
 
         return bitCast<float>(((exponent + 112) << 23) | (mantissa << 17));
     }
 }
 
@@ -413,30 +423,55 @@ inline float float10ToFloat32(unsigned s
         {
             // The value is denormalized
             exponent = 1;
 
             do
             {
                 exponent--;
                 mantissa <<= 1;
-            }
-            while ((mantissa & 0x20) == 0);
+            } while ((mantissa & 0x20) == 0);
 
             mantissa = mantissa & 0x1F;
         }
-        else // The value is zero
+        else  // The value is zero
         {
             exponent = static_cast<unsigned short>(-112);
         }
 
         return bitCast<float>(((exponent + 112) << 23) | (mantissa << 18));
     }
 }
 
+// Convers to and from float and 16.16 fixed point format.
+
+inline float FixedToFloat(uint32_t fixedInput)
+{
+    return static_cast<float>(fixedInput) / 65536.0f;
+}
+
+inline uint32_t FloatToFixed(float floatInput)
+{
+    static constexpr uint32_t kHighest = 32767 * 65536 + 65535;
+    static constexpr uint32_t kLowest  = static_cast<uint32_t>(-32768 * 65536 + 65535);
+
+    if (floatInput > 32767.65535)
+    {
+        return kHighest;
+    }
+    else if (floatInput < -32768.65535)
+    {
+        return kLowest;
+    }
+    else
+    {
+        return static_cast<uint32_t>(floatInput * 65536);
+    }
+}
+
 template <typename T>
 inline float normalizedToFloat(T input)
 {
     static_assert(std::numeric_limits<T>::is_integer, "T must be an integer.");
 
     const float inverseMax = 1.0f / std::numeric_limits<T>::max();
     return input * inverseMax;
 }
@@ -558,22 +593,26 @@ inline float average(float a, float b)
 
 inline unsigned short averageHalfFloat(unsigned short a, unsigned short b)
 {
     return float32ToFloat16((float16ToFloat32(a) + float16ToFloat32(b)) * 0.5f);
 }
 
 inline unsigned int averageFloat11(unsigned int a, unsigned int b)
 {
-    return float32ToFloat11((float11ToFloat32(static_cast<unsigned short>(a)) + float11ToFloat32(static_cast<unsigned short>(b))) * 0.5f);
+    return float32ToFloat11((float11ToFloat32(static_cast<unsigned short>(a)) +
+                             float11ToFloat32(static_cast<unsigned short>(b))) *
+                            0.5f);
 }
 
 inline unsigned int averageFloat10(unsigned int a, unsigned int b)
 {
-    return float32ToFloat10((float10ToFloat32(static_cast<unsigned short>(a)) + float10ToFloat32(static_cast<unsigned short>(b))) * 0.5f);
+    return float32ToFloat10((float10ToFloat32(static_cast<unsigned short>(a)) +
+                             float10ToFloat32(static_cast<unsigned short>(b))) *
+                            0.5f);
 }
 
 template <typename T>
 class Range
 {
   public:
     Range() {}
     Range(T lo, T hi) : mLow(lo), mHigh(hi) {}
@@ -682,60 +721,60 @@ inline float Ldexp(float x, int exp)
 // Then, the results are packed into the returned 32-bit unsigned integer.
 // The first float value will be written to the least significant bits of the output;
 // the last float value will be written to the most significant bits.
 // The conversion of each value to fixed point is done as follows :
 // packSnorm2x16 : round(clamp(c, -1, +1) * 32767.0)
 inline uint32_t packSnorm2x16(float f1, float f2)
 {
     int16_t leastSignificantBits = static_cast<int16_t>(roundf(clamp(f1, -1.0f, 1.0f) * 32767.0f));
-    int16_t mostSignificantBits = static_cast<int16_t>(roundf(clamp(f2, -1.0f, 1.0f) * 32767.0f));
+    int16_t mostSignificantBits  = static_cast<int16_t>(roundf(clamp(f2, -1.0f, 1.0f) * 32767.0f));
     return static_cast<uint32_t>(mostSignificantBits) << 16 |
            (static_cast<uint32_t>(leastSignificantBits) & 0xFFFF);
 }
 
-// First, unpacks a single 32-bit unsigned integer u into a pair of 16-bit unsigned integers. Then, each
-// component is converted to a normalized floating-point value to generate the returned two float values.
-// The first float value will be extracted from the least significant bits of the input;
-// the last float value will be extracted from the most-significant bits.
-// The conversion for unpacked fixed-point value to floating point is done as follows:
-// unpackSnorm2x16 : clamp(f / 32767.0, -1, +1)
+// First, unpacks a single 32-bit unsigned integer u into a pair of 16-bit unsigned integers. Then,
+// each component is converted to a normalized floating-point value to generate the returned two
+// float values. The first float value will be extracted from the least significant bits of the
+// input; the last float value will be extracted from the most-significant bits. The conversion for
+// unpacked fixed-point value to floating point is done as follows: unpackSnorm2x16 : clamp(f /
+// 32767.0, -1, +1)
 inline void unpackSnorm2x16(uint32_t u, float *f1, float *f2)
 {
     int16_t leastSignificantBits = static_cast<int16_t>(u & 0xFFFF);
-    int16_t mostSignificantBits = static_cast<int16_t>(u >> 16);
+    int16_t mostSignificantBits  = static_cast<int16_t>(u >> 16);
     *f1 = clamp(static_cast<float>(leastSignificantBits) / 32767.0f, -1.0f, 1.0f);
     *f2 = clamp(static_cast<float>(mostSignificantBits) / 32767.0f, -1.0f, 1.0f);
 }
 
 // First, both normalized floating-point values are converted into 16-bit integer values.
 // Then, the results are packed into the returned 32-bit unsigned integer.
 // The first float value will be written to the least significant bits of the output;
 // the last float value will be written to the most significant bits.
 // The conversion of each value to fixed point is done as follows:
 // packUnorm2x16 : round(clamp(c, 0, +1) * 65535.0)
 inline uint32_t packUnorm2x16(float f1, float f2)
 {
     uint16_t leastSignificantBits = static_cast<uint16_t>(roundf(clamp(f1, 0.0f, 1.0f) * 65535.0f));
-    uint16_t mostSignificantBits = static_cast<uint16_t>(roundf(clamp(f2, 0.0f, 1.0f) * 65535.0f));
-    return static_cast<uint32_t>(mostSignificantBits) << 16 | static_cast<uint32_t>(leastSignificantBits);
+    uint16_t mostSignificantBits  = static_cast<uint16_t>(roundf(clamp(f2, 0.0f, 1.0f) * 65535.0f));
+    return static_cast<uint32_t>(mostSignificantBits) << 16 |
+           static_cast<uint32_t>(leastSignificantBits);
 }
 
-// First, unpacks a single 32-bit unsigned integer u into a pair of 16-bit unsigned integers. Then, each
-// component is converted to a normalized floating-point value to generate the returned two float values.
-// The first float value will be extracted from the least significant bits of the input;
-// the last float value will be extracted from the most-significant bits.
-// The conversion for unpacked fixed-point value to floating point is done as follows:
-// unpackUnorm2x16 : f / 65535.0
+// First, unpacks a single 32-bit unsigned integer u into a pair of 16-bit unsigned integers. Then,
+// each component is converted to a normalized floating-point value to generate the returned two
+// float values. The first float value will be extracted from the least significant bits of the
+// input; the last float value will be extracted from the most-significant bits. The conversion for
+// unpacked fixed-point value to floating point is done as follows: unpackUnorm2x16 : f / 65535.0
 inline void unpackUnorm2x16(uint32_t u, float *f1, float *f2)
 {
     uint16_t leastSignificantBits = static_cast<uint16_t>(u & 0xFFFF);
-    uint16_t mostSignificantBits = static_cast<uint16_t>(u >> 16);
-    *f1 = static_cast<float>(leastSignificantBits) / 65535.0f;
-    *f2 = static_cast<float>(mostSignificantBits) / 65535.0f;
+    uint16_t mostSignificantBits  = static_cast<uint16_t>(u >> 16);
+    *f1                           = static_cast<float>(leastSignificantBits) / 65535.0f;
+    *f2                           = static_cast<float>(mostSignificantBits) / 65535.0f;
 }
 
 // Helper functions intended to be used only here.
 namespace priv
 {
 
 inline uint8_t ToPackedUnorm8(float f)
 {
@@ -816,29 +855,30 @@ inline void UnpackSnorm4x8(uint32_t u, f
 // Returns an unsigned integer obtained by converting the two floating-point values to the 16-bit
 // floating-point representation found in the OpenGL ES Specification, and then packing these
 // two 16-bit integers into a 32-bit unsigned integer.
 // f1: The 16 least-significant bits of the result;
 // f2: The 16 most-significant bits.
 inline uint32_t packHalf2x16(float f1, float f2)
 {
     uint16_t leastSignificantBits = static_cast<uint16_t>(float32ToFloat16(f1));
-    uint16_t mostSignificantBits = static_cast<uint16_t>(float32ToFloat16(f2));
-    return static_cast<uint32_t>(mostSignificantBits) << 16 | static_cast<uint32_t>(leastSignificantBits);
+    uint16_t mostSignificantBits  = static_cast<uint16_t>(float32ToFloat16(f2));
+    return static_cast<uint32_t>(mostSignificantBits) << 16 |
+           static_cast<uint32_t>(leastSignificantBits);
 }
 
-// Returns two floating-point values obtained by unpacking a 32-bit unsigned integer into a pair of 16-bit values,
-// interpreting those values as 16-bit floating-point numbers according to the OpenGL ES Specification,
-// and converting them to 32-bit floating-point values.
-// The first float value is obtained from the 16 least-significant bits of u;
-// the second component is obtained from the 16 most-significant bits of u.
+// Returns two floating-point values obtained by unpacking a 32-bit unsigned integer into a pair of
+// 16-bit values, interpreting those values as 16-bit floating-point numbers according to the OpenGL
+// ES Specification, and converting them to 32-bit floating-point values. The first float value is
+// obtained from the 16 least-significant bits of u; the second component is obtained from the 16
+// most-significant bits of u.
 inline void unpackHalf2x16(uint32_t u, float *f1, float *f2)
 {
     uint16_t leastSignificantBits = static_cast<uint16_t>(u & 0xFFFF);
-    uint16_t mostSignificantBits = static_cast<uint16_t>(u >> 16);
+    uint16_t mostSignificantBits  = static_cast<uint16_t>(u >> 16);
 
     *f1 = float16ToFloat32(leastSignificantBits);
     *f2 = float16ToFloat32(mostSignificantBits);
 }
 
 inline uint8_t sRGBToLinear(uint8_t srgbValue)
 {
     float value = srgbValue / 255.0f;
@@ -999,31 +1039,35 @@ int FindMSB(T bits)
     }
     else
     {
         return static_cast<int>(ScanReverse(bits));
     }
 }
 
 // Returns whether the argument is Not a Number.
-// IEEE 754 single precision NaN representation: Exponent(8 bits) - 255, Mantissa(23 bits) - non-zero.
+// IEEE 754 single precision NaN representation: Exponent(8 bits) - 255, Mantissa(23 bits) -
+// non-zero.
 inline bool isNaN(float f)
 {
     // Exponent mask: ((1u << 8) - 1u) << 23 = 0x7f800000u
     // Mantissa mask: ((1u << 23) - 1u) = 0x7fffffu
-    return ((bitCast<uint32_t>(f) & 0x7f800000u) == 0x7f800000u) && (bitCast<uint32_t>(f) & 0x7fffffu);
+    return ((bitCast<uint32_t>(f) & 0x7f800000u) == 0x7f800000u) &&
+           (bitCast<uint32_t>(f) & 0x7fffffu);
 }
 
 // Returns whether the argument is infinity.
-// IEEE 754 single precision infinity representation: Exponent(8 bits) - 255, Mantissa(23 bits) - zero.
+// IEEE 754 single precision infinity representation: Exponent(8 bits) - 255, Mantissa(23 bits) -
+// zero.
 inline bool isInf(float f)
 {
     // Exponent mask: ((1u << 8) - 1u) << 23 = 0x7f800000u
     // Mantissa mask: ((1u << 23) - 1u) = 0x7fffffu
-    return ((bitCast<uint32_t>(f) & 0x7f800000u) == 0x7f800000u) && !(bitCast<uint32_t>(f) & 0x7fffffu);
+    return ((bitCast<uint32_t>(f) & 0x7f800000u) == 0x7f800000u) &&
+           !(bitCast<uint32_t>(f) & 0x7fffffu);
 }
 
 namespace priv
 {
 template <unsigned int N, unsigned int R>
 struct iSquareRoot
 {
     static constexpr unsigned int solve()
@@ -1112,31 +1156,30 @@ angle::CheckedNumeric<T> CheckedRoundUp(
 inline unsigned int UnsignedCeilDivide(unsigned int value, unsigned int divisor)
 {
     unsigned int divided = value / divisor;
     return (divided + ((value % divisor == 0) ? 0 : 1));
 }
 
 #if defined(_MSC_VER)
 
-#define ANGLE_ROTL(x,y) _rotl(x,y)
-#define ANGLE_ROTR16(x,y) _rotr16(x,y)
+#define ANGLE_ROTL(x, y) _rotl(x, y)
+#define ANGLE_ROTR16(x, y) _rotr16(x, y)
 
 #else
 
 inline uint32_t RotL(uint32_t x, int8_t r)
 {
     return (x << r) | (x >> (32 - r));
 }
 
 inline uint16_t RotR16(uint16_t x, int8_t r)
 {
     return (x >> r) | (x << (16 - r));
 }
 
 #define ANGLE_ROTL(x, y) ::rx::RotL(x, y)
 #define ANGLE_ROTR16(x, y) ::rx::RotR16(x, y)
 
-#endif // namespace rx
-
+#endif  // namespace rx
 }
 
-#endif   // COMMON_MATHUTIL_H_
+#endif  // COMMON_MATHUTIL_H_
--- a/gfx/angle/checkout/src/common/matrix_utils.h
+++ b/gfx/angle/checkout/src/common/matrix_utils.h
@@ -89,16 +89,38 @@ class Matrix
     {
         ASSERT(columns() == m.rows());
         Matrix<T> res  = (*this) * m;
         size_t numElts = res.elements().size();
         mElements.resize(numElts);
         memcpy(mElements.data(), res.data(), numElts * sizeof(float));
     }
 
+    bool operator==(const Matrix<T> &m) const
+    {
+        ASSERT(columns() == m.columns());
+        ASSERT(rows() == m.rows());
+        return mElements == m.elements();
+    }
+
+    bool operator!=(const Matrix<T> &m) const { return !(mElements == m.elements()); }
+
+    bool nearlyEqual(T epsilon, const Matrix<T> &m) const
+    {
+        ASSERT(columns() == m.columns());
+        ASSERT(rows() == m.rows());
+        const auto &otherElts = m.elements();
+        for (size_t i = 0; i < otherElts.size(); i++)
+        {
+            if ((mElements[i] - otherElts[i] > epsilon) && (otherElts[i] - mElements[i] > epsilon))
+                return false;
+        }
+        return true;
+    }
+
     unsigned int size() const
     {
         ASSERT(rows() == columns());
         return rows();
     }
 
     unsigned int rows() const { return mRows; }
 
--- a/gfx/angle/checkout/src/common/utilities.cpp
+++ b/gfx/angle/checkout/src/common/utilities.cpp
@@ -432,60 +432,16 @@ bool IsAtomicCounterType(GLenum type)
 }
 
 bool IsOpaqueType(GLenum type)
 {
     // ESSL 3.10 section 4.1.7 defines opaque types as: samplers, images and atomic counters.
     return IsImageType(type) || IsSamplerType(type) || IsAtomicCounterType(type);
 }
 
-GLenum SamplerTypeToTextureType(GLenum samplerType)
-{
-    switch (samplerType)
-    {
-      case GL_SAMPLER_2D:
-      case GL_INT_SAMPLER_2D:
-      case GL_UNSIGNED_INT_SAMPLER_2D:
-      case GL_SAMPLER_2D_SHADOW:
-        return GL_TEXTURE_2D;
-
-      case GL_SAMPLER_EXTERNAL_OES:
-          return GL_TEXTURE_EXTERNAL_OES;
-
-      case GL_SAMPLER_CUBE:
-      case GL_INT_SAMPLER_CUBE:
-      case GL_UNSIGNED_INT_SAMPLER_CUBE:
-      case GL_SAMPLER_CUBE_SHADOW:
-        return GL_TEXTURE_CUBE_MAP;
-
-      case GL_SAMPLER_2D_ARRAY:
-      case GL_INT_SAMPLER_2D_ARRAY:
-      case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
-      case GL_SAMPLER_2D_ARRAY_SHADOW:
-        return GL_TEXTURE_2D_ARRAY;
-
-      case GL_SAMPLER_3D:
-      case GL_INT_SAMPLER_3D:
-      case GL_UNSIGNED_INT_SAMPLER_3D:
-        return GL_TEXTURE_3D;
-
-      case GL_SAMPLER_2D_MULTISAMPLE:
-      case GL_INT_SAMPLER_2D_MULTISAMPLE:
-      case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE:
-          return GL_TEXTURE_2D_MULTISAMPLE;
-
-      case GL_SAMPLER_2D_RECT_ANGLE:
-          return GL_TEXTURE_RECTANGLE_ANGLE;
-
-      default:
-        UNREACHABLE();
-        return 0;
-    }
-}
-
 bool IsMatrixType(GLenum type)
 {
     return VariableRowCount(type) > 1;
 }
 
 GLenum TransposeMatrixType(GLenum type)
 {
     if (!IsMatrixType(type))
@@ -540,39 +496,16 @@ int AllocateFirstFreeBits(unsigned int *
         }
 
         mask <<= 1;
     }
 
     return -1;
 }
 
-static_assert(GL_TEXTURE_CUBE_MAP_NEGATIVE_X - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 1, "Unexpected GL cube map enum value.");
-static_assert(GL_TEXTURE_CUBE_MAP_POSITIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 2, "Unexpected GL cube map enum value.");
-static_assert(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 3, "Unexpected GL cube map enum value.");
-static_assert(GL_TEXTURE_CUBE_MAP_POSITIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 4, "Unexpected GL cube map enum value.");
-static_assert(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 5, "Unexpected GL cube map enum value.");
-
-bool IsCubeMapTextureTarget(GLenum target)
-{
-    return (target >= FirstCubeMapTextureTarget && target <= LastCubeMapTextureTarget);
-}
-
-size_t CubeMapTextureTargetToLayerIndex(GLenum target)
-{
-    ASSERT(IsCubeMapTextureTarget(target));
-    return target - static_cast<size_t>(FirstCubeMapTextureTarget);
-}
-
-GLenum LayerIndexToCubeMapTextureTarget(size_t index)
-{
-    ASSERT(index <= (LastCubeMapTextureTarget - FirstCubeMapTextureTarget));
-    return FirstCubeMapTextureTarget + static_cast<GLenum>(index);
-}
-
 IndexRange ComputeIndexRange(GLenum indexType,
                              const GLvoid *indices,
                              size_t count,
                              bool primitiveRestartEnabled)
 {
     switch (indexType)
     {
         case GL_UNSIGNED_BYTE:
@@ -991,62 +924,16 @@ const char *GetGenericErrorMessage(EGLin
             return "Unknown error.";
     }
 }
 
 }  // namespace egl
 
 namespace egl_gl
 {
-GLenum EGLCubeMapTargetToGLCubeMapTarget(EGLenum eglTarget)
-{
-    ASSERT(egl::IsCubeMapTextureTarget(eglTarget));
-    return gl::LayerIndexToCubeMapTextureTarget(egl::CubeMapTextureTargetToLayerIndex(eglTarget));
-}
-
-GLenum EGLImageTargetToGLTextureTarget(EGLenum eglTarget)
-{
-    switch (eglTarget)
-    {
-        case EGL_GL_TEXTURE_2D_KHR:
-            return GL_TEXTURE_2D;
-
-        case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR:
-        case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR:
-        case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR:
-        case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR:
-        case EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR:
-        case EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR:
-            return EGLCubeMapTargetToGLCubeMapTarget(eglTarget);
-
-        case EGL_GL_TEXTURE_3D_KHR:
-            return GL_TEXTURE_3D;
-
-        default:
-            UNREACHABLE();
-            return GL_NONE;
-    }
-}
-
-GLenum EGLTextureTargetToGLTextureTarget(EGLenum eglTarget)
-{
-    switch (eglTarget)
-    {
-        case EGL_TEXTURE_2D:
-            return GL_TEXTURE_2D;
-
-        case EGL_TEXTURE_RECTANGLE_ANGLE:
-            return GL_TEXTURE_RECTANGLE_ANGLE;
-
-        default:
-            UNREACHABLE();
-            return GL_NONE;
-    }
-}
-
 GLuint EGLClientBufferToGLObjectHandle(EGLClientBuffer buffer)
 {
     return static_cast<GLuint>(reinterpret_cast<uintptr_t>(buffer));
 }
 }  // namespace egl_gl
 
 namespace gl_egl
 {
--- a/gfx/angle/checkout/src/common/utilities.h
+++ b/gfx/angle/checkout/src/common/utilities.h
@@ -33,33 +33,26 @@ size_t VariableComponentSize(GLenum type
 size_t VariableInternalSize(GLenum type);
 size_t VariableExternalSize(GLenum type);
 int VariableRowCount(GLenum type);
 int VariableColumnCount(GLenum type);
 bool IsSamplerType(GLenum type);
 bool IsImageType(GLenum type);
 bool IsAtomicCounterType(GLenum type);
 bool IsOpaqueType(GLenum type);
-GLenum SamplerTypeToTextureType(GLenum samplerType);
 bool IsMatrixType(GLenum type);
 GLenum TransposeMatrixType(GLenum type);
 int VariableRegisterCount(GLenum type);
 int MatrixRegisterCount(GLenum type, bool isRowMajorMatrix);
 int MatrixComponentCount(GLenum type, bool isRowMajorMatrix);
 int VariableSortOrder(GLenum type);
 GLenum VariableBoolVectorType(GLenum type);
 
 int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsigned int bitsSize);
 
-static const GLenum FirstCubeMapTextureTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
-static const GLenum LastCubeMapTextureTarget = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
-bool IsCubeMapTextureTarget(GLenum target);
-size_t CubeMapTextureTargetToLayerIndex(GLenum target);
-GLenum LayerIndexToCubeMapTextureTarget(size_t index);
-
 // Parse the base resource name and array indices. Returns the base name of the resource.
 // If the provided name doesn't index an array, the outSubscripts vector will be empty.
 // If the provided name indexes an array, the outSubscripts vector will contain indices with
 // outermost array indices in the back. If an array index is invalid, GL_INVALID_INDEX is added to
 // outSubscripts.
 std::string ParseResourceName(const std::string &name, std::vector<unsigned int> *outSubscripts);
 
 // Find the child field which matches 'fullName' == var.name + "." + field.name.
@@ -156,19 +149,16 @@ EGLenum LayerIndexToCubeMapTextureTarget
 bool IsTextureTarget(EGLenum target);
 bool IsRenderbufferTarget(EGLenum target);
 
 const char *GetGenericErrorMessage(EGLint error);
 }  // namespace egl
 
 namespace egl_gl
 {
-GLenum EGLCubeMapTargetToGLCubeMapTarget(EGLenum eglTarget);
-GLenum EGLImageTargetToGLTextureTarget(EGLenum eglTarget);
-GLenum EGLTextureTargetToGLTextureTarget(EGLenum eglTarget);
 GLuint EGLClientBufferToGLObjectHandle(EGLClientBuffer buffer);
 }
 
 namespace gl_egl
 {
 EGLenum GLComponentTypeToEGLColorComponentType(GLenum glComponentType);
 }  // namespace gl_egl
 
--- a/gfx/angle/checkout/src/compiler/preprocessor/Tokenizer.cpp
+++ b/gfx/angle/checkout/src/compiler/preprocessor/Tokenizer.cpp
@@ -932,16 +932,17 @@ typedef pp::SourceLocation YYLTYPE;
 #define YY_USER_INIT                   \
     do {                               \
         yyfileno = 0;                  \
         yylineno = 1;                  \
         yyextra->leadingSpace = false; \
         yyextra->lineStart = true;     \
     } while(0);
 
+#define YY_NO_INPUT
 #define YY_USER_ACTION                                              \
     do                                                              \
     {                                                               \
         pp::Input* input = &yyextra->input;                         \
         pp::Input::Location* scanLoc = &yyextra->scanLoc;           \
         while ((scanLoc->sIndex < input->count()) &&                \
                (scanLoc->cIndex >= input->length(scanLoc->sIndex))) \
         {                                                           \
--- a/gfx/angle/checkout/src/compiler/preprocessor/Tokenizer.l
+++ b/gfx/angle/checkout/src/compiler/preprocessor/Tokenizer.l
@@ -59,16 +59,17 @@ typedef pp::SourceLocation YYLTYPE;
 #define YY_USER_INIT                   \
     do {                               \
         yyfileno = 0;                  \
         yylineno = 1;                  \
         yyextra->leadingSpace = false; \
         yyextra->lineStart = true;     \
     } while(0);
 
+#define YY_NO_INPUT
 #define YY_USER_ACTION                                              \
     do                                                              \
     {                                                               \
         pp::Input* input = &yyextra->input;                         \
         pp::Input::Location* scanLoc = &yyextra->scanLoc;           \
         while ((scanLoc->sIndex < input->count()) &&                \
                (scanLoc->cIndex >= input->length(scanLoc->sIndex))) \
         {                                                           \
--- a/gfx/angle/checkout/src/compiler/preprocessor/numeric_lex.h
+++ b/gfx/angle/checkout/src/compiler/preprocessor/numeric_lex.h
@@ -43,30 +43,24 @@ bool numeric_lex_int(const std::string &
 
     stream >> (*value);
     return !stream.fail();
 }
 
 template <typename FloatType>
 bool numeric_lex_float(const std::string &str, FloatType *value)
 {
-// On 64-bit Intel Android, istringstream is broken.  Until this is fixed in
-// a newer NDK, don't use it.  Android doesn't have locale support, so this
-// doesn't have to force the C locale.
-// TODO(thakis): Remove this once this bug has been fixed in the NDK and
-// that NDK has been rolled into chromium.
-#if defined(ANGLE_PLATFORM_ANDROID) && __x86_64__
-    *value = strtod(str.c_str(), nullptr);
-    return errno != ERANGE;
-#else
     std::istringstream stream(str);
-    // Force "C" locale so that decimal character is always '.', and
-    // not dependent on the current locale.
+
+// Android NDK forbids access to locales by always throwing instead of only accepting the C locale.
+#if !defined(ANGLE_PLATFORM_ANDROID)
+    // Force "C" locale so that decimal character is always '.', and not dependent on the current
+    // locale.
     stream.imbue(std::locale::classic());
+#endif
 
     stream >> (*value);
     return !stream.fail() && std::isfinite(*value);
-#endif
 }
 
 }  // namespace pp.
 
 #endif  // COMPILER_PREPROCESSOR_NUMERICLEX_H_
--- a/gfx/angle/checkout/src/compiler/translator/ASTMetadataHLSL.cpp
+++ b/gfx/angle/checkout/src/compiler/translator/ASTMetadataHLSL.cpp
@@ -4,18 +4,18 @@
 // found in the LICENSE file.
 //
 
 // Analysis of the AST needed for HLSL generation
 
 #include "compiler/translator/ASTMetadataHLSL.h"
 
 #include "compiler/translator/CallDAG.h"
-#include "compiler/translator/IntermTraverse.h"
 #include "compiler/translator/SymbolTable.h"
+#include "compiler/translator/tree_util/IntermTraverse.h"
 
 namespace sh
 {
 
 namespace
 {
 
 // Class used to traverse the AST of a function definition, checking if the
deleted file mode 100644
--- a/gfx/angle/checkout/src/compiler/translator/AddAndTrueToLoopCondition.cpp
+++ /dev/null
@@ -1,58 +0,0 @@
-//
-// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "compiler/translator/AddAndTrueToLoopCondition.h"
-
-#include "compiler/translator/IntermNode_util.h"
-#include "compiler/translator/IntermTraverse.h"
-
-namespace sh
-{
-
-namespace
-{
-
-// An AST traverser that rewrites for and while loops by replacing "condition" with
-// "condition && true" to work around condition bug on Intel Mac.
-class AddAndTrueToLoopConditionTraverser : public TIntermTraverser
-{
-  public:
-    AddAndTrueToLoopConditionTraverser() : TIntermTraverser(true, false, false) {}
-
-    bool visitLoop(Visit, TIntermLoop *loop) override
-    {
-        // do-while loop doesn't have this bug.
-        if (loop->getType() != ELoopFor && loop->getType() != ELoopWhile)
-        {
-            return true;
-        }
-
-        // For loop may not have a condition.
-        if (loop->getCondition() == nullptr)
-        {
-            return true;
-        }
-
-        // Constant true.
-        TIntermTyped *trueValue = CreateBoolNode(true);
-
-        // CONDITION && true.
-        TIntermBinary *andOp = new TIntermBinary(EOpLogicalAnd, loop->getCondition(), trueValue);
-        loop->setCondition(andOp);
-
-        return true;
-    }
-};
-
-}  // anonymous namespace
-
-void AddAndTrueToLoopCondition(TIntermNode *root)
-{
-    AddAndTrueToLoopConditionTraverser traverser;
-    root->traverse(&traverser);
-}
-
-}  // namespace sh
deleted file mode 100644
--- a/gfx/angle/checkout/src/compiler/translator/AddAndTrueToLoopCondition.h
+++ /dev/null
@@ -1,20 +0,0 @@
-//
-// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Rewrite condition in for and while loops to work around driver bug on Intel Mac.
-
-#ifndef COMPILER_TRANSLATOR_ADDANDTRUETOLOOPCONDITION_H_
-#define COMPILER_TRANSLATOR_ADDANDTRUETOLOOPCONDITION_H_
-
-class TIntermNode;
-namespace sh
-{
-
-void AddAndTrueToLoopCondition(TIntermNode *root);
-
-}  // namespace sh
-
-#endif  // COMPILER_TRANSLATOR_ADDANDTRUETOLOOPCONDITION_H_
deleted file mode 100644
--- a/gfx/angle/checkout/src/compiler/translator/AddDefaultReturnStatements.cpp
+++ /dev/null
@@ -1,58 +0,0 @@
-//
-// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// AddDefaultReturnStatements.cpp: Add default return statements to functions that do not end in a
-//                                 return.
-//
-
-#include "compiler/translator/AddDefaultReturnStatements.h"
-
-#include "compiler/translator/IntermNode.h"
-#include "compiler/translator/IntermNode_util.h"
-#include "compiler/translator/util.h"
-
-namespace sh
-{
-
-namespace
-{
-
-bool NeedsReturnStatement(TIntermFunctionDefinition *node, TType *returnType)
-{
-    *returnType = node->getFunctionPrototype()->getType();
-    if (returnType->getBasicType() == EbtVoid)
-    {
-        return false;
-    }
-
-    TIntermBlock *bodyNode    = node->getBody();
-    TIntermBranch *returnNode = bodyNode->getSequence()->back()->getAsBranchNode();
-    if (returnNode != nullptr && returnNode->getFlowOp() == EOpReturn)
-    {
-        return false;
-    }
-
-    return true;
-}
-
-}  // anonymous namespace
-
-void AddDefaultReturnStatements(TIntermBlock *root)
-{
-    TType returnType;
-    for (TIntermNode *node : *root->getSequence())
-    {
-        TIntermFunctionDefinition *definition = node->getAsFunctionDefinition();
-        if (definition != nullptr && NeedsReturnStatement(definition, &returnType))
-        {
-            TIntermBranch *branch = new TIntermBranch(EOpReturn, CreateZeroNode(returnType));
-
-            TIntermBlock *bodyNode = definition->getBody();
-            bodyNode->getSequence()->push_back(branch);
-        }
-    }
-}
-
-}  // namespace sh
deleted file mode 100644
--- a/gfx/angle/checkout/src/compiler/translator/AddDefaultReturnStatements.h
+++ /dev/null
@@ -1,22 +0,0 @@
-//
-// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// AddDefaultReturnStatements.h: Add default return statements to functions that do not end in a
-//                               return.
-//
-
-#ifndef COMPILER_TRANSLATOR_ADDDEFAULTRETURNSTATEMENTS_H_
-#define COMPILER_TRANSLATOR_ADDDEFAULTRETURNSTATEMENTS_H_
-
-class TIntermBlock;
-
-namespace sh
-{
-
-void AddDefaultReturnStatements(TIntermBlock *root);
-
-}  // namespace sh
-
-#endif  // COMPILER_TRANSLATOR_ADDDEFAULTRETURNSTATEMENTS_H_
deleted file mode 100644
--- a/gfx/angle/checkout/src/compiler/translator/ArrayReturnValueToOutParameter.cpp
+++ /dev/null
@@ -1,244 +0,0 @@
-//
-// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// The ArrayReturnValueToOutParameter function changes return values of an array type to out
-// parameters in function definitions, prototypes, and call sites.
-
-#include "compiler/translator/ArrayReturnValueToOutParameter.h"
-
-#include <map>
-
-#include "compiler/translator/IntermNode_util.h"
-#include "compiler/translator/IntermTraverse.h"
-#include "compiler/translator/StaticType.h"
-#include "compiler/translator/SymbolTable.h"
-
-namespace sh
-{
-
-namespace
-{
-
-constexpr const ImmutableString kReturnValueVariableName("angle_return");
-
-void CopyAggregateChildren(TIntermAggregateBase *from, TIntermAggregateBase *to)
-{
-    const TIntermSequence *fromSequence = from->getSequence();
-    for (size_t ii = 0; ii < fromSequence->size(); ++ii)
-    {
-        to->getSequence()->push_back(fromSequence->at(ii));
-    }
-}
-
-class ArrayReturnValueToOutParameterTraverser : private TIntermTraverser
-{
-  public:
-    static void apply(TIntermNode *root, TSymbolTable *symbolTable);
-
-  private:
-    ArrayReturnValueToOutParameterTraverser(TSymbolTable *symbolTable);
-
-    bool visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) override;
-    bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override;
-    bool visitAggregate(Visit visit, TIntermAggregate *node) override;
-    bool visitBranch(Visit visit, TIntermBranch *node) override;
-    bool visitBinary(Visit visit, TIntermBinary *node) override;
-
-    TIntermAggregate *createReplacementCall(TIntermAggregate *originalCall,
-                                            TIntermTyped *returnValueTarget);
-
-    // Set when traversal is inside a function with array return value.
-    TIntermFunctionDefinition *mFunctionWithArrayReturnValue;
-
-    struct ChangedFunction
-    {
-        const TVariable *returnValueVariable;
-        const TFunction *func;
-    };
-
-    // Map from function symbol ids to the changed function.
-    std::map<int, ChangedFunction> mChangedFunctions;
-};
-
-TIntermAggregate *ArrayReturnValueToOutParameterTraverser::createReplacementCall(
-    TIntermAggregate *originalCall,
-    TIntermTyped *returnValueTarget)
-{
-    TIntermSequence *replacementArguments = new TIntermSequence();
-    TIntermSequence *originalArguments    = originalCall->getSequence();
-    for (auto &arg : *originalArguments)
-    {
-        replacementArguments->push_back(arg);
-    }
-    replacementArguments->push_back(returnValueTarget);
-    ASSERT(originalCall->getFunction());
-    const TSymbolUniqueId &originalId = originalCall->getFunction()->uniqueId();
-    TIntermAggregate *replacementCall = TIntermAggregate::CreateFunctionCall(
-        *mChangedFunctions[originalId.get()].func, replacementArguments);
-    replacementCall->setLine(originalCall->getLine());
-    return replacementCall;
-}
-
-void ArrayReturnValueToOutParameterTraverser::apply(TIntermNode *root, TSymbolTable *symbolTable)
-{
-    ArrayReturnValueToOutParameterTraverser arrayReturnValueToOutParam(symbolTable);
-    root->traverse(&arrayReturnValueToOutParam);
-    arrayReturnValueToOutParam.updateTree();
-}
-
-ArrayReturnValueToOutParameterTraverser::ArrayReturnValueToOutParameterTraverser(
-    TSymbolTable *symbolTable)
-    : TIntermTraverser(true, false, true, symbolTable), mFunctionWithArrayReturnValue(nullptr)
-{
-}
-
-bool ArrayReturnValueToOutParameterTraverser::visitFunctionDefinition(
-    Visit visit,
-    TIntermFunctionDefinition *node)
-{
-    if (node->getFunctionPrototype()->isArray() && visit == PreVisit)
-    {
-        // Replacing the function header is done on visitFunctionPrototype().
-        mFunctionWithArrayReturnValue = node;
-    }
-    if (visit == PostVisit)
-    {
-        mFunctionWithArrayReturnValue = nullptr;
-    }
-    return true;
-}
-
-bool ArrayReturnValueToOutParameterTraverser::visitFunctionPrototype(Visit visit,
-                                                                     TIntermFunctionPrototype *node)
-{
-    if (visit == PreVisit && node->isArray())
-    {
-        // Replace the whole prototype node with another node that has the out parameter
-        // added. Also set the function to return void.
-        const TSymbolUniqueId &functionId = node->getFunction()->uniqueId();
-        if (mChangedFunctions.find(functionId.get()) == mChangedFunctions.end())
-        {
-            TType *returnValueVariableType = new TType(node->getType());
-            returnValueVariableType->setQualifier(EvqOut);
-            ChangedFunction changedFunction;
-            changedFunction.returnValueVariable =
-                new TVariable(mSymbolTable, kReturnValueVariableName, returnValueVariableType,
-                              SymbolType::AngleInternal);
-            TFunction *func = new TFunction(mSymbolTable, node->getFunction()->name(),
-                                            node->getFunction()->symbolType(),
-                                            StaticType::GetBasic<EbtVoid>(), false);
-            for (size_t i = 0; i < node->getFunction()->getParamCount(); ++i)
-            {
-                func->addParameter(node->getFunction()->getParam(i));
-            }
-            func->addParameter(TConstParameter(
-                kReturnValueVariableName, static_cast<const TType *>(returnValueVariableType)));
-            changedFunction.func                = func;
-            mChangedFunctions[functionId.get()] = changedFunction;
-        }
-        TIntermFunctionPrototype *replacement =
-            new TIntermFunctionPrototype(mChangedFunctions[functionId.get()].func);
-        CopyAggregateChildren(node, replacement);
-        replacement->getSequence()->push_back(
-            new TIntermSymbol(mChangedFunctions[functionId.get()].returnValueVariable));
-        replacement->setLine(node->getLine());
-
-        queueReplacement(replacement, OriginalNode::IS_DROPPED);
-    }
-    return false;
-}
-
-bool ArrayReturnValueToOutParameterTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
-{
-    ASSERT(!node->isArray() || node->getOp() != EOpCallInternalRawFunction);
-    if (visit == PreVisit && node->isArray() && node->getOp() == EOpCallFunctionInAST)
-    {
-        // Handle call sites where the returned array is not assigned.
-        // Examples where f() is a function returning an array:
-        // 1. f();
-        // 2. another_array == f();
-        // 3. another_function(f());
-        // 4. return f();
-        // Cases 2 to 4 are already converted to simpler cases by
-        // SeparateExpressionsReturningArrays, so we only need to worry about the case where a
-        // function call returning an array forms an expression by itself.
-        TIntermBlock *parentBlock = getParentNode()->getAsBlock();
-        if (parentBlock)
-        {
-            // replace
-            //   f();
-            // with
-            //   type s0[size]; f(s0);
-            TIntermSequence replacements;
-
-            // type s0[size];
-            TIntermDeclaration *returnValueDeclaration = nullptr;
-            TVariable *returnValue = DeclareTempVariable(mSymbolTable, new TType(node->getType()),
-                                                         EvqTemporary, &returnValueDeclaration);
-            replacements.push_back(returnValueDeclaration);
-
-            // f(s0);
-            TIntermSymbol *returnValueSymbol = CreateTempSymbolNode(returnValue);
-            replacements.push_back(createReplacementCall(node, returnValueSymbol));
-            mMultiReplacements.push_back(
-                NodeReplaceWithMultipleEntry(parentBlock, node, replacements));
-        }
-        return false;
-    }
-    return true;
-}
-
-bool ArrayReturnValueToOutParameterTraverser::visitBranch(Visit visit, TIntermBranch *node)
-{
-    if (mFunctionWithArrayReturnValue && node->getFlowOp() == EOpReturn)
-    {
-        // Instead of returning a value, assign to the out parameter and then return.
-        TIntermSequence replacements;
-
-        TIntermTyped *expression = node->getExpression();
-        ASSERT(expression != nullptr);
-        const TSymbolUniqueId &functionId =
-            mFunctionWithArrayReturnValue->getFunction()->uniqueId();
-        ASSERT(mChangedFunctions.find(functionId.get()) != mChangedFunctions.end());
-        TIntermSymbol *returnValueSymbol =
-            new TIntermSymbol(mChangedFunctions[functionId.get()].returnValueVariable);
-        TIntermBinary *replacementAssignment =
-            new TIntermBinary(EOpAssign, returnValueSymbol, expression);
-        replacementAssignment->setLine(expression->getLine());
-        replacements.push_back(replacementAssignment);
-
-        TIntermBranch *replacementBranch = new TIntermBranch(EOpReturn, nullptr);
-        replacementBranch->setLine(node->getLine());
-        replacements.push_back(replacementBranch);
-
-        mMultiReplacements.push_back(
-            NodeReplaceWithMultipleEntry(getParentNode()->getAsBlock(), node, replacements));
-    }
-    return false;
-}
-
-bool ArrayReturnValueToOutParameterTraverser::visitBinary(Visit visit, TIntermBinary *node)
-{
-    if (node->getOp() == EOpAssign && node->getLeft()->isArray())
-    {
-        TIntermAggregate *rightAgg = node->getRight()->getAsAggregate();
-        ASSERT(rightAgg == nullptr || rightAgg->getOp() != EOpCallInternalRawFunction);
-        if (rightAgg != nullptr && rightAgg->getOp() == EOpCallFunctionInAST)
-        {
-            TIntermAggregate *replacementCall = createReplacementCall(rightAgg, node->getLeft());
-            queueReplacement(replacementCall, OriginalNode::IS_DROPPED);
-        }
-    }
-    return false;
-}
-
-}  // namespace
-
-void ArrayReturnValueToOutParameter(TIntermNode *root, TSymbolTable *symbolTable)
-{
-    ArrayReturnValueToOutParameterTraverser::apply(root, symbolTable);
-}
-
-}  // namespace sh
deleted file mode 100644
--- a/gfx/angle/checkout/src/compiler/translator/ArrayReturnValueToOutParameter.h
+++ /dev/null
@@ -1,22 +0,0 @@
-//
-// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// The ArrayReturnValueToOutParameter function changes return values of an array type to out
-// parameters in function definitions, prototypes and call sites.
-
-#ifndef COMPILER_TRANSLATOR_ARRAYRETURNVALUETOOUTPARAMETER_H_
-#define COMPILER_TRANSLATOR_ARRAYRETURNVALUETOOUTPARAMETER_H_
-
-namespace sh
-{
-
-class TIntermNode;
-class TSymbolTable;
-
-void ArrayReturnValueToOutParameter(TIntermNode *root, TSymbolTable *symbolTable);
-
-}  // namespace sh
-
-#endif  // COMPILER_TRANSLATOR_ARRAYRETURNVALUETOOUTPARAMETER_H_
--- a/gfx/angle/checkout/src/compiler/translator/BaseTypes.h
+++ b/gfx/angle/checkout/src/compiler/translator/BaseTypes.h
@@ -52,28 +52,22 @@ inline const char *getPrecisionString(TP
 //
 enum TBasicType
 {
     EbtVoid,
     EbtFloat,
     EbtInt,
     EbtUInt,
     EbtBool,
-    EbtGVec4,              // non type: represents vec4, ivec4, and uvec4
-    EbtGenType,            // non type: represents float, vec2, vec3, and vec4
-    EbtGenIType,           // non type: represents int, ivec2, ivec3, and ivec4
-    EbtGenUType,           // non type: represents uint, uvec2, uvec3, and uvec4
-    EbtGenBType,           // non type: represents bool, bvec2, bvec3, and bvec4
-    EbtVec,                // non type: represents vec2, vec3, and vec4
-    EbtIVec,               // non type: represents ivec2, ivec3, and ivec4
-    EbtUVec,               // non type: represents uvec2, uvec3, and uvec4
-    EbtBVec,               // non type: represents bvec2, bvec3, and bvec4
+
+    EbtAtomicCounter,
     EbtYuvCscStandardEXT,  // Only valid if EXT_YUV_target exists.
+
     EbtGuardSamplerBegin,  // non type: see implementation of IsSampler()
-    EbtSampler2D,
+    EbtSampler2D = EbtGuardSamplerBegin,
     EbtSampler3D,
     EbtSamplerCube,
     EbtSampler2DArray,
     EbtSamplerExternalOES,       // Only valid if OES_EGL_image_external exists.
     EbtSamplerExternal2DY2YEXT,  // Only valid if GL_EXT_YUV_target exists.
     EbtSampler2DRect,            // Only valid if GL_ARB_texture_rectangle exists.
     EbtSampler2DMS,
     EbtISampler2D,
@@ -84,163 +78,67 @@ enum TBasicType
     EbtUSampler2D,
     EbtUSampler3D,
     EbtUSamplerCube,
     EbtUSampler2DArray,
     EbtUSampler2DMS,
     EbtSampler2DShadow,
     EbtSamplerCubeShadow,
     EbtSampler2DArrayShadow,
-    EbtGuardSamplerEnd,  // non type: see implementation of IsSampler()
-    EbtGSampler2D,       // non type: represents sampler2D, isampler2D, and usampler2D
-    EbtGSampler3D,       // non type: represents sampler3D, isampler3D, and usampler3D
-    EbtGSamplerCube,     // non type: represents samplerCube, isamplerCube, and usamplerCube
-    EbtGSampler2DArray,  // non type: represents sampler2DArray, isampler2DArray, and
-                         // usampler2DArray
-    EbtGSampler2DMS,     // non type: represents sampler2DMS, isampler2DMS, and usampler2DMS
+    EbtGuardSamplerEnd = EbtSampler2DArrayShadow,  // non type: see implementation of IsSampler()
 
     // images
     EbtGuardImageBegin,
-    EbtImage2D,
+    EbtImage2D = EbtGuardImageBegin,
     EbtIImage2D,
     EbtUImage2D,
     EbtImage3D,
     EbtIImage3D,
     EbtUImage3D,
     EbtImage2DArray,
     EbtIImage2DArray,
     EbtUImage2DArray,
     EbtImageCube,
     EbtIImageCube,
     EbtUImageCube,
-    EbtGuardImageEnd,
+    EbtGuardImageEnd = EbtUImageCube,
 
-    EbtGuardGImageBegin,
-    EbtGImage2D,       // non type: represents image2D, uimage2D, iimage2D
-    EbtGImage3D,       // non type: represents image3D, uimage3D, iimage3D
-    EbtGImage2DArray,  // non type: represents image2DArray, uimage2DArray, iimage2DArray
-    EbtGImageCube,     // non type: represents imageCube, uimageCube, iimageCube
-    EbtGuardGImageEnd,
+    EbtLastSimpleType = EbtGuardImageEnd,
 
     EbtStruct,
     EbtInterfaceBlock,
-    EbtAddress,  // should be deprecated??
-
-    EbtAtomicCounter,
 
     // end of list
-    EbtLast
+    EbtLast = EbtInterfaceBlock
 };
 
-constexpr const char *GetBasicMangledName(TBasicType t)
+constexpr char GetBasicMangledName(TBasicType t)
 {
-    switch (t)
+    if (t > EbtLastSimpleType)
     {
-        case EbtFloat:
-            return "f";
-        case EbtInt:
-            return "i";
-        case EbtUInt:
-            return "u";
-        case EbtBool:
-            return "b";
-        case EbtYuvCscStandardEXT:
-            return "ycs";
-        case EbtSampler2D:
-            return "s2";
-        case EbtSampler3D:
-            return "s3";
-        case EbtSamplerCube:
-            return "sC";
-        case EbtSampler2DArray:
-            return "s2a";
-        case EbtSamplerExternalOES:
-            return "sext";
-        case EbtSamplerExternal2DY2YEXT:
-            return "sext2y2y";
-        case EbtSampler2DRect:
-            return "s2r";
-        case EbtSampler2DMS:
-            return "s2ms";
-        case EbtISampler2D:
-            return "is2";
-        case EbtISampler3D:
-            return "is3";
-        case EbtISamplerCube:
-            return "isC";
-        case EbtISampler2DArray:
-            return "is2a";
-        case EbtISampler2DMS:
-            return "is2ms";
-        case EbtUSampler2D:
-            return "us2";
-        case EbtUSampler3D:
-            return "us3";
-        case EbtUSamplerCube:
-            return "usC";
-        case EbtUSampler2DArray:
-            return "us2a";
-        case EbtUSampler2DMS:
-            return "us2ms";
-        case EbtSampler2DShadow:
-            return "s2s";
-        case EbtSamplerCubeShadow:
-            return "sCs";
-        case EbtSampler2DArrayShadow:
-            return "s2as";
-        case EbtImage2D:
-            return "im2";
-        case EbtIImage2D:
-            return "iim2";
-        case EbtUImage2D:
-            return "uim2";
-        case EbtImage3D:
-            return "im3";
-        case EbtIImage3D:
-            return "iim3";
-        case EbtUImage3D:
-            return "uim3";
-        case EbtImage2DArray:
-            return "im2a";
-        case EbtIImage2DArray:
-            return "iim2a";
-        case EbtUImage2DArray:
-            return "uim2a";
-        case EbtImageCube:
-            return "imc";
-        case EbtIImageCube:
-            return "iimc";
-        case EbtUImageCube:
-            return "uimc";
-        case EbtAtomicCounter:
-            return "ac";
-        case EbtStruct:
-        case EbtInterfaceBlock:
-            return nullptr;
-        default:
-            // EbtVoid, EbtAddress and non types
-            return "";
+        return '{';
     }
+    static_assert(EbtLastSimpleType < 52, "We only use alphabetic characters for mangled names");
+    if (t < 26)
+    {
+        return static_cast<char>('A' + t);
+    }
+    return static_cast<char>('a' - 26 + t);
 }
 
 const char *getBasicString(TBasicType t);
 
 inline bool IsSampler(TBasicType type)
 {
-    return type > EbtGuardSamplerBegin && type < EbtGuardSamplerEnd;
+    return type >= EbtGuardSamplerBegin && type <= EbtGuardSamplerEnd;
 }
 
 inline bool IsImage(TBasicType type)
 {
-    return type > EbtGuardImageBegin && type < EbtGuardImageEnd;
-}
-
-inline bool IsGImage(TBasicType type)
-{
-    return type > EbtGuardGImageBegin && type < EbtGuardGImageEnd;
+    return type >= EbtGuardImageBegin && type <= EbtGuardImageEnd;
 }
 
 inline bool IsAtomicCounter(TBasicType type)
 {
     return type == EbtAtomicCounter;
 }
 
 inline bool IsOpaqueType(TBasicType type)
deleted file mode 100644
--- a/gfx/angle/checkout/src/compiler/translator/BreakVariableAliasingInInnerLoops.cpp
+++ /dev/null
@@ -1,107 +0,0 @@
-//
-// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// BreakVariableAliasingInInnerLoops.h: To optimize simple assignments, the HLSL compiler frontend
-//      may record a variable as aliasing another. Sometimes the alias information gets garbled
-//      so we work around this issue by breaking the aliasing chain in inner loops.
-
-#include "BreakVariableAliasingInInnerLoops.h"
-
-#include "compiler/translator/IntermNode_util.h"
-#include "compiler/translator/IntermTraverse.h"
-
-// A HLSL compiler developer gave us more details on the root cause and the workaround needed:
-//     The root problem is that if the HLSL compiler is applying aliasing information even on
-//     incomplete simulations (in this case, a single pass). The bug is triggered by an assignment
-//     that comes from a series of assignments, possibly with swizzled or ternary operators with
-//     known conditionals, where the source is before the loop.
-//     So, a workaround is to add a +0 term to variables the first time they are assigned to in
-//     an inner loop (if they are declared in an outside scope, otherwise there is no need).
-//     This will break the aliasing chain.
-
-// For simplicity here we add a +0 to any assignment that is in at least two nested loops. Because
-// the bug only shows up with swizzles, and ternary assignment, whole array or whole structure
-// assignment don't need a workaround.
-
-namespace sh
-{
-
-namespace
-{
-
-class AliasingBreaker : public TIntermTraverser
-{
-  public:
-    AliasingBreaker() : TIntermTraverser(true, false, true) {}
-
-  protected:
-    bool visitBinary(Visit visit, TIntermBinary *binary)
-    {
-        if (visit != PreVisit)
-        {
-            return false;
-        }
-
-        if (mLoopLevel < 2 || !binary->isAssignment())
-        {
-            return true;
-        }
-
-        TIntermTyped *B = binary->getRight();
-        TType type      = B->getType();
-
-        if (!type.isScalar() && !type.isVector() && !type.isMatrix())
-        {
-            return true;
-        }
-
-        if (type.isArray() || IsSampler(type.getBasicType()))
-        {
-            return true;
-        }
-
-        // We have a scalar / vector / matrix assignment with loop depth 2.
-        // Transform it from
-        //    A = B
-        // to
-        //    A = (B + typeof<B>(0));
-
-        TIntermBinary *bPlusZero = new TIntermBinary(EOpAdd, B, CreateZeroNode(type));
-        bPlusZero->setLine(B->getLine());
-
-        binary->replaceChildNode(B, bPlusZero);
-
-        return true;
-    }
-
-    bool visitLoop(Visit visit, TIntermLoop *loop)
-    {
-        if (visit == PreVisit)
-        {
-            mLoopLevel++;
-        }
-        else
-        {
-            ASSERT(mLoopLevel > 0);
-            mLoopLevel--;
-        }
-
-        return true;
-    }
-
-  private:
-    int mLoopLevel = 0;
-};
-
-}  // anonymous namespace
-
-void BreakVariableAliasingInInnerLoops(TIntermNode *root)
-{
-    AliasingBreaker breaker;
-    root->traverse(&breaker);
-}
-
-}  // namespace sh
deleted file mode 100644
--- a/gfx/angle/checkout/src/compiler/translator/BreakVariableAliasingInInnerLoops.h
+++ /dev/null
@@ -1,23 +0,0 @@
-//
-// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// BreakVariableAliasingInInnerLoops.h: To optimize simple assignments, the HLSL compiler frontend
-//      may record a variable as aliasing another. Sometimes the alias information gets garbled
-//      so we work around this issue by breaking the aliasing chain in inner loops.
-
-#ifndef COMPILER_TRANSLATOR_BREAKVARIABLEALIASINGININNERLOOPS_H_
-#define COMPILER_TRANSLATOR_BREAKVARIABLEALIASINGININNERLOOPS_H_
-
-class TIntermNode;
-
-namespace sh
-{
-
-void BreakVariableAliasingInInnerLoops(TIntermNode *root);
-
-}  // namespace sh
-
-#endif  // COMPILER_TRANSLATOR_BREAKVARIABLEALIASINGININNERLOOPS_H_
--- a/gfx/angle/checkout/src/compiler/translator/BuiltInFunctionEmulator.cpp
+++ b/gfx/angle/checkout/src/compiler/translator/BuiltInFunctionEmulator.cpp
@@ -1,174 +1,77 @@
 //
 // Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
 
 #include "compiler/translator/BuiltInFunctionEmulator.h"
 #include "angle_gl.h"
-#include "compiler/translator/IntermTraverse.h"
-#include "compiler/translator/SymbolTable.h"
 #include "compiler/translator/StaticType.h"
+#include "compiler/translator/Symbol.h"
+#include "compiler/translator/tree_util/IntermTraverse.h"
 
 namespace sh
 {
 
 class BuiltInFunctionEmulator::BuiltInFunctionEmulationMarker : public TIntermTraverser
 {
   public:
     BuiltInFunctionEmulationMarker(BuiltInFunctionEmulator &emulator)
         : TIntermTraverser(true, false, false), mEmulator(emulator)
     {
     }
 
     bool visitUnary(Visit visit, TIntermUnary *node) override
     {
-        if (visit == PreVisit)
+        if (node->getFunction())
         {
-            bool needToEmulate =
-                mEmulator.setFunctionCalled(node->getOp(), node->getOperand()->getType());
+            bool needToEmulate = mEmulator.setFunctionCalled(node->getFunction());
             if (needToEmulate)
                 node->setUseEmulatedFunction();
         }
         return true;
     }
 
     bool visitAggregate(Visit visit, TIntermAggregate *node) override
     {
-        if (visit == PreVisit)
+        // Here we handle all the built-in functions mapped to ops, not just the ones that are
+        // currently identified as problematic.
+        if (node->isConstructor() || node->isFunctionCall())
         {
-            // Here we handle all the built-in functions mapped to ops, not just the ones that are
-            // currently identified as problematic.
-            if (node->isConstructor() || node->isFunctionCall())
-            {
-                return true;
-            }
-            const TIntermSequence &sequence = *(node->getSequence());
-            bool needToEmulate              = false;
-            // Right now we only handle built-in functions with two to four parameters.
-            if (sequence.size() == 2)
-            {
-                TIntermTyped *param1 = sequence[0]->getAsTyped();
-                TIntermTyped *param2 = sequence[1]->getAsTyped();
-                if (!param1 || !param2)
-                    return true;
-                needToEmulate = mEmulator.setFunctionCalled(node->getOp(), param1->getType(),
-                                                            param2->getType());
-            }
-            else if (sequence.size() == 3)
-            {
-                TIntermTyped *param1 = sequence[0]->getAsTyped();
-                TIntermTyped *param2 = sequence[1]->getAsTyped();
-                TIntermTyped *param3 = sequence[2]->getAsTyped();
-                if (!param1 || !param2 || !param3)
-                    return true;
-                needToEmulate = mEmulator.setFunctionCalled(node->getOp(), param1->getType(),
-                                                            param2->getType(), param3->getType());
-            }
-            else if (sequence.size() == 4)
-            {
-                TIntermTyped *param1 = sequence[0]->getAsTyped();
-                TIntermTyped *param2 = sequence[1]->getAsTyped();
-                TIntermTyped *param3 = sequence[2]->getAsTyped();
-                TIntermTyped *param4 = sequence[3]->getAsTyped();
-                if (!param1 || !param2 || !param3 || !param4)
-                    return true;
-                needToEmulate =
-                    mEmulator.setFunctionCalled(node->getOp(), param1->getType(), param2->getType(),
-                                                param3->getType(), param4->getType());
-            }
-            else
-            {
-                return true;
-            }
-
-            if (needToEmulate)
-                node->setUseEmulatedFunction();
+            return true;
         }
+        bool needToEmulate = mEmulator.setFunctionCalled(node->getFunction());
+        if (needToEmulate)
+            node->setUseEmulatedFunction();
         return true;
     }
 
   private:
     BuiltInFunctionEmulator &mEmulator;
 };
 
 BuiltInFunctionEmulator::BuiltInFunctionEmulator()
 {
 }
 
-FunctionId BuiltInFunctionEmulator::addEmulatedFunction(TOperator op,
-                                                        const TType *param,
-                                                        const char *emulatedFunctionDefinition)
-{
-    FunctionId id(op, param);
-    mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition);
-    return id;
-}
-
-FunctionId BuiltInFunctionEmulator::addEmulatedFunction(TOperator op,
-                                                        const TType *param1,
-                                                        const TType *param2,
-                                                        const char *emulatedFunctionDefinition)
+void BuiltInFunctionEmulator::addEmulatedFunction(const TSymbolUniqueId &uniqueId,
+                                                  const char *emulatedFunctionDefinition)
 {
-    FunctionId id(op, param1, param2);
-    mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition);
-    return id;
-}
-
-FunctionId BuiltInFunctionEmulator::addEmulatedFunctionWithDependency(
-    const FunctionId &dependency,
-    TOperator op,
-    const TType *param1,
-    const TType *param2,
-    const char *emulatedFunctionDefinition)
-{
-    FunctionId id(op, param1, param2);
-    mEmulatedFunctions[id]    = std::string(emulatedFunctionDefinition);
-    mFunctionDependencies[id] = dependency;
-    return id;
+    mEmulatedFunctions[uniqueId.get()] = std::string(emulatedFunctionDefinition);
 }
 
-FunctionId BuiltInFunctionEmulator::addEmulatedFunction(TOperator op,
-                                                        const TType *param1,
-                                                        const TType *param2,
-                                                        const TType *param3,
-                                                        const char *emulatedFunctionDefinition)
-{
-    FunctionId id(op, param1, param2, param3);
-    mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition);
-    return id;
-}
-
-FunctionId BuiltInFunctionEmulator::addEmulatedFunction(TOperator op,
-                                                        const TType *param1,
-                                                        const TType *param2,
-                                                        const TType *param3,
-                                                        const TType *param4,
-                                                        const char *emulatedFunctionDefinition)
-{
-    FunctionId id(op, param1, param2, param3, param4);
-    mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition);
-    return id;
-}
-
-FunctionId BuiltInFunctionEmulator::addEmulatedFunctionWithDependency(
-    const FunctionId &dependency,
-    TOperator op,
-    const TType *param1,
-    const TType *param2,
-    const TType *param3,
-    const TType *param4,
+void BuiltInFunctionEmulator::addEmulatedFunctionWithDependency(
+    const TSymbolUniqueId &dependency,
+    const TSymbolUniqueId &uniqueId,
     const char *emulatedFunctionDefinition)
 {
-    FunctionId id(op, param1, param2, param3, param4);
-    mEmulatedFunctions[id]    = std::string(emulatedFunctionDefinition);
-    mFunctionDependencies[id] = dependency;
-    return id;
+    mEmulatedFunctions[uniqueId.get()]    = std::string(emulatedFunctionDefinition);
+    mFunctionDependencies[uniqueId.get()] = dependency.get();
 }
 
 bool BuiltInFunctionEmulator::isOutputEmpty() const
 {
     return (mFunctions.size() == 0);
 }
 
 void BuiltInFunctionEmulator::outputEmulatedFunctions(TInfoSinkBase &out) const
@@ -177,86 +80,61 @@ void BuiltInFunctionEmulator::outputEmul
     {
         const char *body = findEmulatedFunction(function);
         ASSERT(body);
         out << body;
         out << "\n\n";
     }
 }
 
-bool BuiltInFunctionEmulator::setFunctionCalled(TOperator op, const TType &param)
-{
-    return setFunctionCalled(FunctionId(op, &param));
-}
-
-bool BuiltInFunctionEmulator::setFunctionCalled(TOperator op,
-                                                const TType &param1,
-                                                const TType &param2)
-{
-    return setFunctionCalled(FunctionId(op, &param1, &param2));
-}
-
-bool BuiltInFunctionEmulator::setFunctionCalled(TOperator op,
-                                                const TType &param1,
-                                                const TType &param2,
-                                                const TType &param3)
-{
-    return setFunctionCalled(FunctionId(op, &param1, &param2, &param3));
-}
-
-bool BuiltInFunctionEmulator::setFunctionCalled(TOperator op,
-                                                const TType &param1,
-                                                const TType &param2,
-                                                const TType &param3,
-                                                const TType &param4)
-{
-    return setFunctionCalled(FunctionId(op, &param1, &param2, &param3, &param4));
-}
-
-const char *BuiltInFunctionEmulator::findEmulatedFunction(const FunctionId &functionId) const
+const char *BuiltInFunctionEmulator::findEmulatedFunction(int uniqueId) const
 {
     for (const auto &queryFunction : mQueryFunctions)
     {
-        const char *result = queryFunction(functionId);
+        const char *result = queryFunction(uniqueId);
         if (result)
         {
             return result;
         }
     }
 
-    const auto &result = mEmulatedFunctions.find(functionId);
+    const auto &result = mEmulatedFunctions.find(uniqueId);
     if (result != mEmulatedFunctions.end())
     {
         return result->second.c_str();
     }
 
     return nullptr;
 }
 
-bool BuiltInFunctionEmulator::setFunctionCalled(const FunctionId &functionId)
+bool BuiltInFunctionEmulator::setFunctionCalled(const TFunction *function)
 {
-    if (!findEmulatedFunction(functionId))
+    ASSERT(function != nullptr);
+    return setFunctionCalled(function->uniqueId().get());
+}
+
+bool BuiltInFunctionEmulator::setFunctionCalled(int uniqueId)
+{
+    if (!findEmulatedFunction(uniqueId))
     {
         return false;
     }
 
     for (size_t i = 0; i < mFunctions.size(); ++i)
     {
-        if (mFunctions[i] == functionId)
+        if (mFunctions[i] == uniqueId)
             return true;
     }
     // If the function depends on another, mark the dependency as called.
-    auto dependency = mFunctionDependencies.find(functionId);
+    auto dependency = mFunctionDependencies.find(uniqueId);
     if (dependency != mFunctionDependencies.end())
     {
         setFunctionCalled((*dependency).second);
     }
-    // Copy the functionId if it needs to be stored, to make sure that the TType pointers inside
-    // remain valid and constant.
-    mFunctions.push_back(functionId.getCopy());
+    mFunctions.push_back(uniqueId);
     return true;
 }
 
 void BuiltInFunctionEmulator::markBuiltInFunctionsForEmulation(TIntermNode *root)
 {
     ASSERT(root);
 
     if (mEmulatedFunctions.empty() && mQueryFunctions.empty())
@@ -279,81 +157,9 @@ void BuiltInFunctionEmulator::addFunctio
 
 // static
 void BuiltInFunctionEmulator::WriteEmulatedFunctionName(TInfoSinkBase &out, const char *name)
 {
     ASSERT(name[strlen(name) - 1] != '(');
     out << name << "_emu";
 }
 
-FunctionId::FunctionId()
-    : mOp(EOpNull),
-      mParam1(StaticType::GetBasic<EbtVoid>()),
-      mParam2(StaticType::GetBasic<EbtVoid>()),
-      mParam3(StaticType::GetBasic<EbtVoid>()),
-      mParam4(StaticType::GetBasic<EbtVoid>())
-{
-}
-
-FunctionId::FunctionId(TOperator op, const TType *param)
-    : mOp(op),
-      mParam1(param),
-      mParam2(StaticType::GetBasic<EbtVoid>()),
-      mParam3(StaticType::GetBasic<EbtVoid>()),
-      mParam4(StaticType::GetBasic<EbtVoid>())
-{
-}
-
-FunctionId::FunctionId(TOperator op, const TType *param1, const TType *param2)
-    : mOp(op),
-      mParam1(param1),
-      mParam2(param2),
-      mParam3(StaticType::GetBasic<EbtVoid>()),
-      mParam4(StaticType::GetBasic<EbtVoid>())
-{
-}
-
-FunctionId::FunctionId(TOperator op, const TType *param1, const TType *param2, const TType *param3)
-    : mOp(op),
-      mParam1(param1),
-      mParam2(param2),
-      mParam3(param3),
-      mParam4(StaticType::GetBasic<EbtVoid>())
-{
-}
-
-FunctionId::FunctionId(TOperator op,
-                       const TType *param1,
-                       const TType *param2,
-                       const TType *param3,
-                       const TType *param4)
-    : mOp(op), mParam1(param1), mParam2(param2), mParam3(param3), mParam4(param4)
-{
-}
-
-bool FunctionId::operator==(const FunctionId &other) const
-{
-    return (mOp == other.mOp && *mParam1 == *other.mParam1 && *mParam2 == *other.mParam2 &&
-            *mParam3 == *other.mParam3 && *mParam4 == *other.mParam4);
-}
-
-bool FunctionId::operator<(const FunctionId &other) const
-{
-    if (mOp != other.mOp)
-        return mOp < other.mOp;
-    if (*mParam1 != *other.mParam1)
-        return *mParam1 < *other.mParam1;
-    if (*mParam2 != *other.mParam2)
-        return *mParam2 < *other.mParam2;
-    if (*mParam3 != *other.mParam3)
-        return *mParam3 < *other.mParam3;
-    if (*mParam4 != *other.mParam4)
-        return *mParam4 < *other.mParam4;
-    return false;  // all fields are equal
-}
-
-FunctionId FunctionId::getCopy() const
-{
-    return FunctionId(mOp, new TType(*mParam1), new TType(*mParam2), new TType(*mParam3),
-                      new TType(*mParam4));
-}
-
 }  // namespace sh
--- a/gfx/angle/checkout/src/compiler/translator/BuiltInFunctionEmulator.h
+++ b/gfx/angle/checkout/src/compiler/translator/BuiltInFunctionEmulator.h
@@ -3,92 +3,25 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
 
 #ifndef COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATOR_H_
 #define COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATOR_H_
 
 #include "compiler/translator/InfoSink.h"
-#include "compiler/translator/IntermNode.h"
-#include "compiler/translator/ParamType.h"
 
 namespace sh
 {
 
-struct MiniFunctionId
-{
-    constexpr MiniFunctionId(TOperator op         = EOpNull,
-                             ParamType paramType1 = ParamType::Void,
-                             ParamType paramType2 = ParamType::Void,
-                             ParamType paramType3 = ParamType::Void,
-                             ParamType paramType4 = ParamType::Void)
-        : op(op),
-          paramType1(paramType1),
-          paramType2(paramType2),
-          paramType3(paramType3),
-          paramType4(paramType4)
-    {
-    }
-
-    TOperator op;
-    ParamType paramType1;
-    ParamType paramType2;
-    ParamType paramType3;
-    ParamType paramType4;
-};
-
-class FunctionId final
-{
-  public:
-    FunctionId();
-    FunctionId(TOperator op, const TType *param);
-    FunctionId(TOperator op, const TType *param1, const TType *param2);
-    FunctionId(TOperator op, const TType *param1, const TType *param2, const TType *param3);
-    FunctionId(TOperator op,
-               const TType *param1,
-               const TType *param2,
-               const TType *param3,
-               const TType *param4);
+class TIntermNode;
+class TFunction;
+class TSymbolUniqueId;
 
-    FunctionId(const FunctionId &) = default;
-    FunctionId &operator=(const FunctionId &) = default;
-
-    bool operator==(const FunctionId &other) const;
-    bool operator<(const FunctionId &other) const;
-
-    FunctionId getCopy() const;
-
-  private:
-    friend bool operator==(const MiniFunctionId &miniId, const FunctionId &functionId);
-    TOperator mOp;
-
-    // The memory that these TType objects use is freed by PoolAllocator. The
-    // BuiltInFunctionEmulator's lifetime can extend until after the memory pool is freed, but
-    // that's not an issue since this class never destructs these objects.
-    const TType *mParam1;
-    const TType *mParam2;
-    const TType *mParam3;
-    const TType *mParam4;
-};
-
-inline bool operator==(ParamType paramType, const TType *type)
-{
-    return SameParamType(paramType, type->getBasicType(), type->getNominalSize(),
-                         type->getSecondarySize());
-}
-
-inline bool operator==(const MiniFunctionId &miniId, const FunctionId &functionId)
-{
-    return miniId.op == functionId.mOp && miniId.paramType1 == functionId.mParam1 &&
-           miniId.paramType2 == functionId.mParam2 && miniId.paramType3 == functionId.mParam3 &&
-           miniId.paramType4 == functionId.mParam4;
-}
-
-using BuiltinQueryFunc = const char *(const FunctionId &);
+using BuiltinQueryFunc = const char *(int);
 
 //
 // This class decides which built-in functions need to be replaced with the emulated ones. It can be
 // used to work around driver bugs or implement functions that are not natively implemented on a
 // specific platform.
 //
 class BuiltInFunctionEmulator
 {
@@ -103,81 +36,45 @@ class BuiltInFunctionEmulator
     static void WriteEmulatedFunctionName(TInfoSinkBase &out, const char *name);
 
     bool isOutputEmpty() const;
 
     // Output function emulation definition. This should be before any other shader source.
     void outputEmulatedFunctions(TInfoSinkBase &out) const;
 
     // Add functions that need to be emulated.
-    FunctionId addEmulatedFunction(TOperator op,
-                                   const TType *param,
-                                   const char *emulatedFunctionDefinition);
-    FunctionId addEmulatedFunction(TOperator op,
-                                   const TType *param1,
-                                   const TType *param2,
-                                   const char *emulatedFunctionDefinition);
-    FunctionId addEmulatedFunction(TOperator op,
-                                   const TType *param1,
-                                   const TType *param2,
-                                   const TType *param3,
-                                   const char *emulatedFunctionDefinition);
-    FunctionId addEmulatedFunction(TOperator op,
-                                   const TType *param1,
-                                   const TType *param2,
-                                   const TType *param3,
-                                   const TType *param4,
-                                   const char *emulatedFunctionDefinition);
+    void addEmulatedFunction(const TSymbolUniqueId &uniqueId,
+                             const char *emulatedFunctionDefinition);
 
-    FunctionId addEmulatedFunctionWithDependency(const FunctionId &dependency,
-                                                 TOperator op,
-                                                 const TType *param1,
-                                                 const TType *param2,
-                                                 const char *emulatedFunctionDefinition);
-    FunctionId addEmulatedFunctionWithDependency(const FunctionId &dependency,
-                                                 TOperator op,
-                                                 const TType *param1,
-                                                 const TType *param2,
-                                                 const TType *param3,
-                                                 const TType *param4,
-                                                 const char *emulatedFunctionDefinition);
+    void addEmulatedFunctionWithDependency(const TSymbolUniqueId &dependency,
+                                           const TSymbolUniqueId &uniqueId,
+                                           const char *emulatedFunctionDefinition);
 
     void addFunctionMap(BuiltinQueryFunc queryFunc);
 
   private:
     class BuiltInFunctionEmulationMarker;
 
     // Records that a function is called by the shader and might need to be emulated. If the
     // function is not in mEmulatedFunctions, this becomes a no-op. Returns true if the function
     // call needs to be replaced with an emulated one.
-    bool setFunctionCalled(TOperator op, const TType &param);
-    bool setFunctionCalled(TOperator op, const TType &param1, const TType &param2);
-    bool setFunctionCalled(TOperator op,
-                           const TType &param1,
-                           const TType &param2,
-                           const TType &param3);
-    bool setFunctionCalled(TOperator op,
-                           const TType &param1,
-                           const TType &param2,
-                           const TType &param3,
-                           const TType &param4);
+    bool setFunctionCalled(const TFunction *function);
+    bool setFunctionCalled(int uniqueId);
 
-    bool setFunctionCalled(const FunctionId &functionId);
+    const char *findEmulatedFunction(int uniqueId) const;
 
-    const char *findEmulatedFunction(const FunctionId &functionId) const;
-
-    // Map from function id to emulated function definition
-    std::map<FunctionId, std::string> mEmulatedFunctions;
+    // Map from function unique id to emulated function definition
+    std::map<int, std::string> mEmulatedFunctions;
 
     // Map from dependent functions to their dependencies. This structure allows each function to
     // have at most one dependency.
-    std::map<FunctionId, FunctionId> mFunctionDependencies;
+    std::map<int, int> mFunctionDependencies;
 
     // Called function ids
-    std::vector<FunctionId> mFunctions;
+    std::vector<int> mFunctions;
 
     // Constexpr function tables.
     std::vector<BuiltinQueryFunc *> mQueryFunctions;
 };
 
 }  // namespace sh
 
 #endif  // COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATOR_H_
--- a/gfx/angle/checkout/src/compiler/translator/BuiltInFunctionEmulatorGLSL.cpp
+++ b/gfx/angle/checkout/src/compiler/translator/BuiltInFunctionEmulatorGLSL.cpp
@@ -2,178 +2,159 @@
 // Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
 
 #include "compiler/translator/BuiltInFunctionEmulatorGLSL.h"
 #include "angle_gl.h"
 #include "compiler/translator/BuiltInFunctionEmulator.h"
-#include "compiler/translator/SymbolTable.h"
-#include "compiler/translator/StaticType.h"
 #include "compiler/translator/VersionGLSL.h"
+#include "compiler/translator/tree_util/BuiltIn_autogen.h"
 
 namespace sh
 {
 
 void InitBuiltInAbsFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu,
                                                       sh::GLenum shaderType)
 {
     if (shaderType == GL_VERTEX_SHADER)
     {
-        const TType *int1 = StaticType::GetBasic<EbtInt>();
-        emu->addEmulatedFunction(EOpAbs, int1, "int abs_emu(int x) { return x * sign(x); }");
+        emu->addEmulatedFunction(BuiltInId::abs_Int1, "int abs_emu(int x) { return x * sign(x); }");
     }
 }
 
 void InitBuiltInIsnanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu,
                                                         int targetGLSLVersion)
 {
     // isnan() is supported since GLSL 1.3.
     if (targetGLSLVersion < GLSL_VERSION_130)
         return;
 
-    const TType *float1 = StaticType::GetBasic<EbtFloat>();
-    const TType *float2 = StaticType::GetBasic<EbtFloat, 2>();
-    const TType *float3 = StaticType::GetBasic<EbtFloat, 3>();
-    const TType *float4 = StaticType::GetBasic<EbtFloat, 4>();
-
     // !(x > 0.0 || x < 0.0 || x == 0.0) will be optimized and always equal to false.
     emu->addEmulatedFunction(
-        EOpIsnan, float1,
+        BuiltInId::isnan_Float1,
         "bool isnan_emu(float x) { return (x > 0.0 || x < 0.0) ? false : x != 0.0; }");
     emu->addEmulatedFunction(
-        EOpIsnan, float2,
+        BuiltInId::isnan_Float2,
         "bvec2 isnan_emu(vec2 x)\n"
         "{\n"
         "    bvec2 isnan;\n"
         "    for (int i = 0; i < 2; i++)\n"
         "    {\n"
         "        isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n"
         "    }\n"
         "    return isnan;\n"
         "}\n");
     emu->addEmulatedFunction(
-        EOpIsnan, float3,
+        BuiltInId::isnan_Float3,
         "bvec3 isnan_emu(vec3 x)\n"
         "{\n"
         "    bvec3 isnan;\n"
         "    for (int i = 0; i < 3; i++)\n"
         "    {\n"
         "        isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n"
         "    }\n"
         "    return isnan;\n"
         "}\n");
     emu->addEmulatedFunction(
-        EOpIsnan, float4,
+        BuiltInId::isnan_Float4,
         "bvec4 isnan_emu(vec4 x)\n"
         "{\n"
         "    bvec4 isnan;\n"
         "    for (int i = 0; i < 4; i++)\n"
         "    {\n"
         "        isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n"
         "    }\n"
         "    return isnan;\n"
         "}\n");
 }
 
 void InitBuiltInAtanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu)
 {
-    const TType *float1 = StaticType::GetBasic<EbtFloat>();
-    auto floatFuncId    = emu->addEmulatedFunction(
-        EOpAtan, float1, float1,
-        "emu_precision float atan_emu(emu_precision float y, emu_precision "
-        "float x)\n"
-        "{\n"
-        "    if (x > 0.0) return atan(y / x);\n"
-        "    else if (x < 0.0 && y >= 0.0) return atan(y / x) + 3.14159265;\n"
-        "    else if (x < 0.0 && y < 0.0) return atan(y / x) - 3.14159265;\n"
-        "    else return 1.57079632 * sign(y);\n"
-        "}\n");
-    static const std::array<const TType *, 5> floatVecs = {
-        nullptr,
-        nullptr,
-        StaticType::GetBasic<EbtFloat, 2>(),
-        StaticType::GetBasic<EbtFloat, 3>(),
-        StaticType::GetBasic<EbtFloat, 4>(),
+    emu->addEmulatedFunction(BuiltInId::atan_Float1_Float1,
+                             "emu_precision float atan_emu(emu_precision float y, emu_precision "
+                             "float x)\n"
+                             "{\n"
+                             "    if (x > 0.0) return atan(y / x);\n"
+                             "    else if (x < 0.0 && y >= 0.0) return atan(y / x) + 3.14159265;\n"
+                             "    else if (x < 0.0 && y < 0.0) return atan(y / x) - 3.14159265;\n"
+                             "    else return 1.57079632 * sign(y);\n"
+                             "}\n");
+    static const std::array<TSymbolUniqueId, 4> ids = {
+        BuiltInId::atan_Float1_Float1, BuiltInId::atan_Float2_Float2, BuiltInId::atan_Float3_Float3,
+        BuiltInId::atan_Float4_Float4,
     };
     for (int dim = 2; dim <= 4; ++dim)
     {
-        const TType *floatVec = floatVecs[dim];
         std::stringstream ss;
         ss << "emu_precision vec" << dim << " atan_emu(emu_precision vec" << dim
            << " y, emu_precision vec" << dim << " x)\n"
            << "{\n"
               "    return vec"
            << dim << "(";
         for (int i = 0; i < dim; ++i)
         {
             ss << "atan_emu(y[" << i << "], x[" << i << "])";
             if (i < dim - 1)
             {
                 ss << ", ";
             }
         }
         ss << ");\n"
               "}\n";
-        emu->addEmulatedFunctionWithDependency(floatFuncId, EOpAtan, floatVec, floatVec,
+        emu->addEmulatedFunctionWithDependency(BuiltInId::atan_Float1_Float1, ids[dim - 1],
                                                ss.str().c_str());
     }
 }
 
 // Emulate built-in functions missing from GLSL 1.30 and higher
 void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator *emu,
                                                         sh::GLenum shaderType,
                                                         int targetGLSLVersion)
 {
     // Emulate packUnorm2x16 and unpackUnorm2x16 (GLSL 4.10)
     if (targetGLSLVersion < GLSL_VERSION_410)
     {
-        const TType *float2 = StaticType::GetBasic<EbtFloat, 2>();
-        const TType *uint1  = StaticType::GetBasic<EbtUInt>();
-
         // clang-format off
-        emu->addEmulatedFunction(EOpPackUnorm2x16, float2,
+        emu->addEmulatedFunction(BuiltInId::packUnorm2x16_Float2,
             "uint packUnorm2x16_emu(vec2 v)\n"
             "{\n"
             "    int x = int(round(clamp(v.x, 0.0, 1.0) * 65535.0));\n"
             "    int y = int(round(clamp(v.y, 0.0, 1.0) * 65535.0));\n"
             "    return uint((y << 16) | (x & 0xFFFF));\n"
             "}\n");
 
-        emu->addEmulatedFunction(EOpUnpackUnorm2x16, uint1,
+        emu->addEmulatedFunction(BuiltInId::unpackUnorm2x16_UInt1,
             "vec2 unpackUnorm2x16_emu(uint u)\n"
             "{\n"
             "    float x = float(u & 0xFFFFu) / 65535.0;\n"
             "    float y = float(u >> 16) / 65535.0;\n"
             "    return vec2(x, y);\n"
             "}\n");
         // clang-format on
     }
 
     // Emulate packSnorm2x16, packHalf2x16, unpackSnorm2x16, and unpackHalf2x16 (GLSL 4.20)
     // by using floatBitsToInt, floatBitsToUint, intBitsToFloat, and uintBitsToFloat (GLSL 3.30).
     if (targetGLSLVersion >= GLSL_VERSION_330 && targetGLSLVersion < GLSL_VERSION_420)
     {
-        const TType *float2 = StaticType::GetBasic<EbtFloat, 2>();
-        const TType *uint1  = StaticType::GetBasic<EbtUInt>();
-
         // clang-format off
-        emu->addEmulatedFunction(EOpPackSnorm2x16, float2,
+        emu->addEmulatedFunction(BuiltInId::packSnorm2x16_Float2,
             "uint packSnorm2x16_emu(vec2 v)\n"
             "{\n"
             "    #if defined(GL_ARB_shading_language_packing)\n"
             "        return packSnorm2x16(v);\n"
             "    #else\n"
             "        int x = int(round(clamp(v.x, -1.0, 1.0) * 32767.0));\n"
             "        int y = int(round(clamp(v.y, -1.0, 1.0) * 32767.0));\n"
             "        return uint((y << 16) | (x & 0xFFFF));\n"
             "    #endif\n"
             "}\n");
-        emu->addEmulatedFunction(EOpUnpackSnorm2x16, uint1,
+        emu->addEmulatedFunction(BuiltInId::unpackSnorm2x16_UInt1,
             "#if !defined(GL_ARB_shading_language_packing)\n"
             "    float fromSnorm(uint x)\n"
             "    {\n"
             "        int xi = (int(x) & 0x7FFF) - (int(x) & 0x8000);\n"
             "        return clamp(float(xi) / 32767.0, -1.0, 1.0);\n"
             "    }\n"
             "#endif\n"
             "\n"
@@ -184,17 +165,17 @@ void InitBuiltInFunctionEmulatorForGLSLM
             "    #else\n"
             "        uint y = (u >> 16);\n"
             "        uint x = u;\n"
             "        return vec2(fromSnorm(x), fromSnorm(y));\n"
             "    #endif\n"
             "}\n");
         // Functions uint f32tof16(float val) and float f16tof32(uint val) are
         // based on the OpenGL redbook Appendix Session "Floating-Point Formats Used in OpenGL".
-        emu->addEmulatedFunction(EOpPackHalf2x16, float2,
+        emu->addEmulatedFunction(BuiltInId::packHalf2x16_Float2,
             "#if !defined(GL_ARB_shading_language_packing)\n"
             "    uint f32tof16(float val)\n"
             "    {\n"
             "        uint f32 = floatBitsToUint(val);\n"
             "        uint f16 = 0u;\n"
             "        uint sign = (f32 >> 16) & 0x8000u;\n"
             "        int exponent = int((f32 >> 23) & 0xFFu) - 127;\n"
             "        uint mantissa = f32 & 0x007FFFFFu;\n"
@@ -231,17 +212,17 @@ void InitBuiltInFunctionEmulatorForGLSLM
             "    #if defined(GL_ARB_shading_language_packing)\n"
             "        return packHalf2x16(v);\n"
             "    #else\n"
             "        uint x = f32tof16(v.x);\n"
             "        uint y = f32tof16(v.y);\n"
             "        return (y << 16) | x;\n"
             "    #endif\n"
             "}\n");
-        emu->addEmulatedFunction(EOpUnpackHalf2x16, uint1,
+        emu->addEmulatedFunction(BuiltInId::unpackHalf2x16_UInt1,
             "#if !defined(GL_ARB_shading_language_packing)\n"
             "    float f16tof32(uint val)\n"
             "    {\n"
             "        uint sign = (val & 0x8000u) << 16;\n"
             "        int exponent = int((val & 0x7C00u) >> 10);\n"
             "        uint mantissa = val & 0x03FFu;\n"
             "        float f32 = 0.0;\n"
             "        if(exponent == 0)\n"
--- a/gfx/angle/checkout/src/compiler/translator/BuiltInFunctionEmulatorHLSL.cpp
+++ b/gfx/angle/checkout/src/compiler/translator/BuiltInFunctionEmulatorHLSL.cpp
@@ -1,142 +1,131 @@
 //
 // Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
 
+#include "compiler/translator/BuiltInFunctionEmulatorHLSL.h"
 #include "angle_gl.h"
 #include "compiler/translator/BuiltInFunctionEmulator.h"
-#include "compiler/translator/BuiltInFunctionEmulatorHLSL.h"
-#include "compiler/translator/SymbolTable.h"
 #include "compiler/translator/VersionGLSL.h"
+#include "compiler/translator/tree_util/BuiltIn_autogen.h"
 
 namespace sh
 {
 
 // Defined in emulated_builtin_functions_hlsl_autogen.cpp.
-const char *FindHLSLFunction(const FunctionId &functionID);
+const char *FindHLSLFunction(int uniqueId);
 
 void InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(BuiltInFunctionEmulator *emu,
                                                         int targetGLSLVersion)
 {
     if (targetGLSLVersion < GLSL_VERSION_130)
         return;
 
-    TType *float1 = new TType(EbtFloat);
-    TType *float2 = new TType(EbtFloat, 2);
-    TType *float3 = new TType(EbtFloat, 3);
-    TType *float4 = new TType(EbtFloat, 4);
-
-    emu->addEmulatedFunction(EOpIsnan, float1,
+    emu->addEmulatedFunction(BuiltInId::isnan_Float1,
                              "bool isnan_emu(float x)\n"
                              "{\n"
                              "    return (x > 0.0 || x < 0.0) ? false : x != 0.0;\n"
                              "}\n"
                              "\n");
 
     emu->addEmulatedFunction(
-        EOpIsnan, float2,
+        BuiltInId::isnan_Float2,
         "bool2 isnan_emu(float2 x)\n"
         "{\n"
         "    bool2 isnan;\n"
         "    for (int i = 0; i < 2; i++)\n"
         "    {\n"
         "        isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n"
         "    }\n"
         "    return isnan;\n"
         "}\n");
 
     emu->addEmulatedFunction(
-        EOpIsnan, float3,
+        BuiltInId::isnan_Float3,
         "bool3 isnan_emu(float3 x)\n"
         "{\n"
         "    bool3 isnan;\n"
         "    for (int i = 0; i < 3; i++)\n"
         "    {\n"
         "        isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n"
         "    }\n"
         "    return isnan;\n"
         "}\n");
 
     emu->addEmulatedFunction(
-        EOpIsnan, float4,
+        BuiltInId::isnan_Float4,
         "bool4 isnan_emu(float4 x)\n"
         "{\n"
         "    bool4 isnan;\n"
         "    for (int i = 0; i < 4; i++)\n"
         "    {\n"
         "        isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n"
         "    }\n"
         "    return isnan;\n"
         "}\n");
 }
 
 void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu)
 {
-    TType *int1   = new TType(EbtInt);
-    TType *int2   = new TType(EbtInt, 2);
-    TType *int3   = new TType(EbtInt, 3);
-    TType *int4   = new TType(EbtInt, 4);
-    TType *uint1  = new TType(EbtUInt);
-    TType *uint2  = new TType(EbtUInt, 2);
-    TType *uint3  = new TType(EbtUInt, 3);
-    TType *uint4  = new TType(EbtUInt, 4);
-
     emu->addFunctionMap(FindHLSLFunction);
 
     // (a + b2^16) * (c + d2^16) = ac + (ad + bc) * 2^16 + bd * 2^32
     // Also note that below, a * d + ((a * c) >> 16) is guaranteed not to overflow, because:
     // a <= 0xffff, d <= 0xffff, ((a * c) >> 16) <= 0xffff and 0xffff * 0xffff + 0xffff = 0xffff0000
-    FunctionId umulExtendedUint1 = emu->addEmulatedFunction(
-        EOpUmulExtended, uint1, uint1, uint1, uint1,
-        "void umulExtended_emu(uint x, uint y, out uint msb, out uint lsb)\n"
-        "{\n"
-        "    lsb = x * y;\n"
-        "    uint a = (x & 0xffffu);\n"
-        "    uint b = (x >> 16);\n"
-        "    uint c = (y & 0xffffu);\n"
-        "    uint d = (y >> 16);\n"
-        "    uint ad = a * d + ((a * c) >> 16);\n"
-        "    uint bc = b * c;\n"
-        "    uint carry = uint(ad > (0xffffffffu - bc));\n"
-        "    msb = ((ad + bc) >> 16) + (carry << 16) + b * d;\n"
-        "}\n");
+    emu->addEmulatedFunction(BuiltInId::umulExtended_UInt1_UInt1_UInt1_UInt1,
+                             "void umulExtended_emu(uint x, uint y, out uint msb, out uint lsb)\n"
+                             "{\n"
+                             "    lsb = x * y;\n"
+                             "    uint a = (x & 0xffffu);\n"
+                             "    uint b = (x >> 16);\n"
+                             "    uint c = (y & 0xffffu);\n"
+                             "    uint d = (y >> 16);\n"
+                             "    uint ad = a * d + ((a * c) >> 16);\n"
+                             "    uint bc = b * c;\n"
+                             "    uint carry = uint(ad > (0xffffffffu - bc));\n"
+                             "    msb = ((ad + bc) >> 16) + (carry << 16) + b * d;\n"
+                             "}\n");
     emu->addEmulatedFunctionWithDependency(
-        umulExtendedUint1, EOpUmulExtended, uint2, uint2, uint2, uint2,
+        BuiltInId::umulExtended_UInt1_UInt1_UInt1_UInt1,
+        BuiltInId::umulExtended_UInt2_UInt2_UInt2_UInt2,
         "void umulExtended_emu(uint2 x, uint2 y, out uint2 msb, out uint2 lsb)\n"
         "{\n"
         "    umulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
         "    umulExtended_emu(x.y, y.y, msb.y, lsb.y);\n"
         "}\n");
     emu->addEmulatedFunctionWithDependency(
-        umulExtendedUint1, EOpUmulExtended, uint3, uint3, uint3, uint3,
+        BuiltInId::umulExtended_UInt1_UInt1_UInt1_UInt1,
+        BuiltInId::umulExtended_UInt3_UInt3_UInt3_UInt3,
         "void umulExtended_emu(uint3 x, uint3 y, out uint3 msb, out uint3 lsb)\n"
         "{\n"
         "    umulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
         "    umulExtended_emu(x.y, y.y, msb.y, lsb.y);\n"
         "    umulExtended_emu(x.z, y.z, msb.z, lsb.z);\n"
         "}\n");
     emu->addEmulatedFunctionWithDependency(
-        umulExtendedUint1, EOpUmulExtended, uint4, uint4, uint4, uint4,
+        BuiltInId::umulExtended_UInt1_UInt1_UInt1_UInt1,
+        BuiltInId::umulExtended_UInt4_UInt4_UInt4_UInt4,
         "void umulExtended_emu(uint4 x, uint4 y, out uint4 msb, out uint4 lsb)\n"
         "{\n"
         "    umulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
         "    umulExtended_emu(x.y, y.y, msb.y, lsb.y);\n"
         "    umulExtended_emu(x.z, y.z, msb.z, lsb.z);\n"
         "    umulExtended_emu(x.w, y.w, msb.w, lsb.w);\n"
         "}\n");
 
     // The imul emulation does two's complement negation on the lsb and msb manually in case the
     // result needs to be negative.
     // TODO(oetuaho): Note that this code doesn't take one edge case into account, where x or y is
     // -2^31. abs(-2^31) is undefined.
-    FunctionId imulExtendedInt1 = emu->addEmulatedFunctionWithDependency(
-        umulExtendedUint1, EOpImulExtended, int1, int1, int1, int1,
+    emu->addEmulatedFunctionWithDependency(
+        BuiltInId::umulExtended_UInt1_UInt1_UInt1_UInt1,
+        BuiltInId::imulExtended_Int1_Int1_Int1_Int1,
         "void imulExtended_emu(int x, int y, out int msb, out int lsb)\n"
         "{\n"
         "    uint unsignedMsb;\n"
         "    uint unsignedLsb;\n"
         "    bool negative = (x < 0) != (y < 0);\n"
         "    umulExtended_emu(uint(abs(x)), uint(abs(y)), unsignedMsb, unsignedLsb);\n"
         "    lsb = asint(unsignedLsb);\n"
         "    msb = asint(unsignedMsb);\n"
@@ -151,32 +140,32 @@ void InitBuiltInFunctionEmulatorForHLSL(
         "        }\n"
         "        else\n"
         "        {\n"
         "            lsb += 1;\n"
         "        }\n"
         "    }\n"
         "}\n");
     emu->addEmulatedFunctionWithDependency(
-        imulExtendedInt1, EOpImulExtended, int2, int2, int2, int2,
+        BuiltInId::imulExtended_Int1_Int1_Int1_Int1, BuiltInId::imulExtended_Int2_Int2_Int2_Int2,
         "void imulExtended_emu(int2 x, int2 y, out int2 msb, out int2 lsb)\n"
         "{\n"
         "    imulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
         "    imulExtended_emu(x.y, y.y, msb.y, lsb.y);\n"
         "}\n");
     emu->addEmulatedFunctionWithDependency(
-        imulExtendedInt1, EOpImulExtended, int3, int3, int3, int3,
+        BuiltInId::imulExtended_Int1_Int1_Int1_Int1, BuiltInId::imulExtended_Int3_Int3_Int3_Int3,
         "void imulExtended_emu(int3 x, int3 y, out int3 msb, out int3 lsb)\n"
         "{\n"
         "    imulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
         "    imulExtended_emu(x.y, y.y, msb.y, lsb.y);\n"
         "    imulExtended_emu(x.z, y.z, msb.z, lsb.z);\n"
         "}\n");
     emu->addEmulatedFunctionWithDependency(
-        imulExtendedInt1, EOpImulExtended, int4, int4, int4, int4,
+        BuiltInId::imulExtended_Int1_Int1_Int1_Int1, BuiltInId::imulExtended_Int4_Int4_Int4_Int4,
         "void imulExtended_emu(int4 x, int4 y, out int4 msb, out int4 lsb)\n"
         "{\n"
         "    imulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
         "    imulExtended_emu(x.y, y.y, msb.y, lsb.y);\n"
         "    imulExtended_emu(x.z, y.z, msb.z, lsb.z);\n"
         "    imulExtended_emu(x.w, y.w, msb.w, lsb.w);\n"
         "}\n");
 }
--- a/gfx/angle/checkout/src/compiler/translator/CallDAG.cpp
+++ b/gfx/angle/checkout/src/compiler/translator/CallDAG.cpp
@@ -6,18 +6,18 @@
 
 // CallDAG.h: Implements a call graph DAG of functions to be re-used accross
 // analyses, allows to efficiently traverse the functions in topological
 // order.
 
 #include "compiler/translator/CallDAG.h"
 
 #include "compiler/translator/Diagnostics.h"
-#include "compiler/translator/IntermTraverse.h"
 #include "compiler/translator/SymbolTable.h"
+#include "compiler/translator/tree_util/IntermTraverse.h"
 
 namespace sh
 {
 
 // The CallDAGCreator does all the processing required to create the CallDAG
 // structure so that the latter contains only the necessary variables.
 class CallDAG::CallDAGCreator : public TIntermTraverser
 {
@@ -111,26 +111,23 @@ class CallDAG::CallDAGCreator : public T
         mCurrentFunction->name           = node->getFunction()->name();
         mCurrentFunction->definitionNode = node;
 
         node->getBody()->traverse(this);
         mCurrentFunction = nullptr;
         return false;
     }
 
-    bool visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) override
+    void visitFunctionPrototype(TIntermFunctionPrototype *node) override
     {
         ASSERT(mCurrentFunction == nullptr);
 
         // Function declaration, create an empty record.
         auto &record = mFunctions[node->getFunction()->uniqueId().get()];
         record.name  = node->getFunction()->name();
-
-        // No need to traverse the parameters.
-        return false;
     }
 
     // Track functions called from another function.
     bool visitAggregate(Visit visit, TIntermAggregate *node) override
     {
         if (node->getOp() == EOpCallFunctionInAST)
         {
             // Function call, add the callees
deleted file mode 100644
--- a/gfx/angle/checkout/src/compiler/translator/ClampFragDepth.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-//
-// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// ClampFragDepth.cpp: Limit the value that is written to gl_FragDepth to the range [0.0, 1.0].
-// The clamping is run at the very end of shader execution, and is only performed if the shader
-// statically accesses gl_FragDepth.
-//
-
-#include "compiler/translator/ClampFragDepth.h"
-
-#include "compiler/translator/FindSymbolNode.h"
-#include "compiler/translator/ImmutableString.h"
-#include "compiler/translator/IntermNode_util.h"
-#include "compiler/translator/RunAtTheEndOfShader.h"
-#include "compiler/translator/SymbolTable.h"
-
-namespace sh
-{
-
-void ClampFragDepth(TIntermBlock *root, TSymbolTable *symbolTable)
-{
-    // Only clamp gl_FragDepth if it's used in the shader.
-    if (!FindSymbolNode(root, ImmutableString("gl_FragDepth")))
-    {
-        return;
-    }
-
-    TIntermSymbol *fragDepthNode =
-        ReferenceBuiltInVariable(ImmutableString("gl_FragDepth"), *symbolTable, 300);
-
-    TIntermTyped *minFragDepthNode = CreateZeroNode(TType(EbtFloat, EbpHigh, EvqConst));
-
-    TConstantUnion *maxFragDepthConstant = new TConstantUnion();
-    maxFragDepthConstant->setFConst(1.0);
-    TIntermConstantUnion *maxFragDepthNode =
-        new TIntermConstantUnion(maxFragDepthConstant, TType(EbtFloat, EbpHigh, EvqConst));
-
-    // clamp(gl_FragDepth, 0.0, 1.0)
-    TIntermSequence *clampArguments = new TIntermSequence();
-    clampArguments->push_back(fragDepthNode->deepCopy());
-    clampArguments->push_back(minFragDepthNode);
-    clampArguments->push_back(maxFragDepthNode);
-    TIntermTyped *clampedFragDepth =
-        CreateBuiltInFunctionCallNode("clamp", clampArguments, *symbolTable, 100);
-
-    // gl_FragDepth = clamp(gl_FragDepth, 0.0, 1.0)
-    TIntermBinary *assignFragDepth = new TIntermBinary(EOpAssign, fragDepthNode, clampedFragDepth);
-
-    RunAtTheEndOfShader(root, assignFragDepth, symbolTable);
-}
-
-}  // namespace sh
deleted file mode 100644
--- a/gfx/angle/checkout/src/compiler/translator/ClampFragDepth.h
+++ /dev/null
@@ -1,24 +0,0 @@
-//
-// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// ClampFragDepth.h: Limit the value that is written to gl_FragDepth to the range [0.0, 1.0].
-// The clamping is run at the very end of shader execution, and is only performed if the shader
-// statically accesses gl_FragDepth.
-//
-
-#ifndef COMPILER_TRANSLATOR_CLAMPFRAGDEPTH_H_
-#define COMPILER_TRANSLATOR_CLAMPFRAGDEPTH_H_
-
-namespace sh
-{
-
-class TIntermBlock;
-class TSymbolTable;
-
-void ClampFragDepth(TIntermBlock *root, TSymbolTable *symbolTable);
-
-}  // namespace sh
-
-#endif  // COMPILER_TRANSLATOR_CLAMPFRAGDEPTH_H_
deleted file mode 100644
--- a/gfx/angle/checkout/src/compiler/translator/ClampPointSize.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-//
-// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// ClampPointSize.cpp: Limit the value that is written to gl_PointSize.
-//
-
-#include "compiler/translator/ClampPointSize.h"
-
-#include "compiler/translator/FindSymbolNode.h"
-#include "compiler/translator/IntermNode_util.h"
-#include "compiler/translator/RunAtTheEndOfShader.h"
-#include "compiler/translator/SymbolTable.h"
-
-namespace sh
-{
-
-void ClampPointSize(TIntermBlock *root, float maxPointSize, TSymbolTable *symbolTable)
-{
-    // Only clamp gl_PointSize if it's used in the shader.
-    if (!FindSymbolNode(root, ImmutableString("gl_PointSize")))
-    {
-        return;
-    }
-
-    TIntermSymbol *pointSizeNode =
-        ReferenceBuiltInVariable(ImmutableString("gl_PointSize"), *symbolTable, 100);
-
-    TConstantUnion *maxPointSizeConstant = new TConstantUnion();
-    maxPointSizeConstant->setFConst(maxPointSize);
-    TIntermConstantUnion *maxPointSizeNode =
-        new TIntermConstantUnion(maxPointSizeConstant, TType(EbtFloat, EbpHigh, EvqConst));
-
-    // min(gl_PointSize, maxPointSize)
-    TIntermSequence *minArguments = new TIntermSequence();
-    minArguments->push_back(pointSizeNode->deepCopy());
-    minArguments->push_back(maxPointSizeNode);
-    TIntermTyped *clampedPointSize =
-        CreateBuiltInFunctionCallNode("min", minArguments, *symbolTable, 100);
-
-    // gl_PointSize = min(gl_PointSize, maxPointSize)
-    TIntermBinary *assignPointSize = new TIntermBinary(EOpAssign, pointSizeNode, clampedPointSize);
-
-    RunAtTheEndOfShader(root, assignPointSize, symbolTable);
-}
-
-}  // namespace sh
deleted file mode 100644
--- a/gfx/angle/checkout/src/compiler/translator/ClampPointSize.h
+++ /dev/null
@@ -1,22 +0,0 @@
-//
-// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// ClampPointSize.h: Limit the value that is written to gl_PointSize.
-//
-
-#ifndef COMPILER_TRANSLATOR_CLAMPPOINTSIZE_H_
-#define COMPILER_TRANSLATOR_CLAMPPOINTSIZE_H_
-
-namespace sh
-{
-
-class TIntermBlock;
-class TSymbolTable;
-
-void ClampPointSize(TIntermBlock *root, float maxPointSize, TSymbolTable *symbolTable);
-
-}  // namespace sh
-
-#endif  // COMPILER_TRANSLATOR_CLAMPPOINTSIZE_H_
--- a/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp
+++ b/gfx/angle/checkout/src/compiler/translator/CollectVariables.cpp
@@ -5,18 +5,18 @@
 //
 // CollectVariables.cpp: Collect lists of shader interface variables based on the AST.
 
 #include "compiler/translator/CollectVariables.h"
 
 #include "angle_gl.h"
 #include "common/utilities.h"
 #include "compiler/translator/HashNames.h"
-#include "compiler/translator/IntermTraverse.h"
 #include "compiler/translator/SymbolTable.h"
+#include "compiler/translator/tree_util/IntermTraverse.h"
 #include "compiler/translator/util.h"
 
 namespace sh
 {
 
 namespace
 {
 
@@ -63,44 +63,46 @@ VarT *FindVariable(const ImmutableString
     {
         if (name == (*infoList)[ii].name)
             return &((*infoList)[ii]);
     }
 
     return nullptr;
 }
 
-// Note that this shouldn't be called for interface blocks - static use information is collected for
+// Note that this shouldn't be called for interface blocks - active information is collected for
 // individual fields in case of interface blocks.
-void MarkStaticallyUsed(ShaderVariable *variable)
+void MarkActive(ShaderVariable *variable)
 {
-    if (!variable->staticUse)
+    if (!variable->active)
     {
         if (variable->isStruct())
         {
             // Conservatively assume all fields are statically used as well.
             for (auto &field : variable->fields)
             {
-                MarkStaticallyUsed(&field);
+                MarkActive(&field);
             }
         }
-        variable->staticUse = true;
+        ASSERT(variable->staticUse);
+        variable->active    = true;
     }
 }
 
 ShaderVariable *FindVariableInInterfaceBlock(const ImmutableString &name,
                                              const TInterfaceBlock *interfaceBlock,
                                              std::vector<InterfaceBlock> *infoList)
 {
     ASSERT(interfaceBlock);
     InterfaceBlock *namedBlock = FindVariable(interfaceBlock->name(), infoList);
     ASSERT(namedBlock);
 
     // Set static use on the parent interface block here
     namedBlock->staticUse = true;
+    namedBlock->active    = true;
     return FindVariable(name, &namedBlock->fields);
 }
 
 // Traverses the intermediate tree to collect all attributes, uniforms, varyings, fragment outputs,
 // and interface blocks.
 class CollectVariablesTraverser : public TIntermTraverser
 {
   public:
@@ -109,50 +111,53 @@ class CollectVariablesTraverser : public
                               std::vector<Uniform> *uniforms,
                               std::vector<Varying> *inputVaryings,
                               std::vector<Varying> *outputVaryings,
                               std::vector<InterfaceBlock> *uniformBlocks,
                               std::vector<InterfaceBlock> *shaderStorageBlocks,
                               std::vector<InterfaceBlock> *inBlocks,
                               ShHashFunction64 hashFunction,
                               TSymbolTable *symbolTable,
-                              int shaderVersion,
                               GLenum shaderType,
                               const TExtensionBehavior &extensionBehavior);
 
+    bool visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node) override;
     void visitSymbol(TIntermSymbol *symbol) override;
     bool visitDeclaration(Visit, TIntermDeclaration *node) override;
     bool visitBinary(Visit visit, TIntermBinary *binaryNode) override;
 
   private:
     std::string getMappedName(const TSymbol *symbol) const;
 
-    void setFieldOrVariableProperties(const TType &type, ShaderVariable *variableOut) const;
+    void setFieldOrVariableProperties(const TType &type,
+                                      bool staticUse,
+                                      ShaderVariable *variableOut) const;
     void setFieldProperties(const TType &type,
                             const ImmutableString &name,
+                            bool staticUse,
                             ShaderVariable *variableOut) const;
     void setCommonVariableProperties(const TType &type,
                                      const TVariable &variable,
                                      ShaderVariable *variableOut) const;
 
     Attribute recordAttribute(const TIntermSymbol &variable) const;
     OutputVariable recordOutputVariable(const TIntermSymbol &variable) const;
     Varying recordVarying(const TIntermSymbol &variable) const;
     void recordInterfaceBlock(const char *instanceName,
                               const TType &interfaceBlockType,
                               InterfaceBlock *interfaceBlock) const;
     Uniform recordUniform(const TIntermSymbol &variable) const;
 
-    void setBuiltInInfoFromSymbolTable(const ImmutableString &name, ShaderVariable *info);
+    void setBuiltInInfoFromSymbol(const TVariable &variable, ShaderVariable *info);
 
-    void recordBuiltInVaryingUsed(const ImmutableString &name,
+    void recordBuiltInVaryingUsed(const TVariable &variable,
                                   bool *addedFlag,
                                   std::vector<Varying> *varyings);
-    void recordBuiltInFragmentOutputUsed(const ImmutableString &name, bool *addedFlag);
-    void recordBuiltInAttributeUsed(const ImmutableString &name, bool *addedFlag);
+    void recordBuiltInFragmentOutputUsed(const TVariable &variable, bool *addedFlag);
+    void recordBuiltInAttributeUsed(const TVariable &variable, bool *addedFlag);
     InterfaceBlock *recordGLInUsed(const TType &glInType);
     InterfaceBlock *findNamedInterfaceBlock(const ImmutableString &name) const;
 
     std::vector<Attribute> *mAttribs;
     std::vector<OutputVariable> *mOutputVariables;
     std::vector<Uniform> *mUniforms;
     std::vector<Varying> *mInputVaryings;
     std::vector<Varying> *mOutputVaryings;
@@ -191,33 +196,31 @@ class CollectVariablesTraverser : public
     bool mInvocationIDAdded;
 
     // Geometry Shader and Fragment Shader builtins
     bool mPrimitiveIDAdded;
     bool mLayerAdded;
 
     ShHashFunction64 mHashFunction;
 
-    int mShaderVersion;
     GLenum mShaderType;
     const TExtensionBehavior &mExtensionBehavior;
 };
 
 CollectVariablesTraverser::CollectVariablesTraverser(
     std::vector<sh::Attribute> *attribs,
     std::vector<sh::OutputVariable> *outputVariables,
     std::vector<sh::Uniform> *uniforms,
     std::vector<sh::Varying> *inputVaryings,
     std::vector<sh::Varying> *outputVaryings,
     std::vector<sh::InterfaceBlock> *uniformBlocks,
     std::vector<sh::InterfaceBlock> *shaderStorageBlocks,
     std::vector<sh::InterfaceBlock> *inBlocks,
     ShHashFunction64 hashFunction,
     TSymbolTable *symbolTable,
-    int shaderVersion,
     GLenum shaderType,
     const TExtensionBehavior &extensionBehavior)
     : TIntermTraverser(true, false, false, symbolTable),
       mAttribs(attribs),
       mOutputVariables(outputVariables),
       mUniforms(uniforms),
       mInputVaryings(inputVaryings),
       mOutputVaryings(outputVaryings),
@@ -240,112 +243,116 @@ CollectVariablesTraverser::CollectVariab
       mSecondaryFragColorEXTAdded(false),
       mSecondaryFragDataEXTAdded(false),
       mPerVertexInAdded(false),
       mPrimitiveIDInAdded(false),
       mInvocationIDAdded(false),
       mPrimitiveIDAdded(false),
       mLayerAdded(false),
       mHashFunction(hashFunction),
-      mShaderVersion(shaderVersion),
       mShaderType(shaderType),
       mExtensionBehavior(extensionBehavior)
 {
 }
 
 std::string CollectVariablesTraverser::getMappedName(const TSymbol *symbol) const
 {
     return HashName(symbol, mHashFunction, nullptr).data();
 }
 
-void CollectVariablesTraverser::setBuiltInInfoFromSymbolTable(const ImmutableString &name,
-                                                              ShaderVariable *info)
+void CollectVariablesTraverser::setBuiltInInfoFromSymbol(const TVariable &variable,
+                                                         ShaderVariable *info)
 {
-    const TVariable *symbolTableVar =
-        reinterpret_cast<const TVariable *>(mSymbolTable->findBuiltIn(name, mShaderVersion));
-    ASSERT(symbolTableVar);
-    const TType &type = symbolTableVar->getType();
+    const TType &type = variable.getType();
 
-    info->name       = name.data();
-    info->mappedName = name.data();
+    info->name       = variable.name().data();
+    info->mappedName = variable.name().data();
     info->type       = GLVariableType(type);
     info->precision = GLVariablePrecision(type);
     if (auto *arraySizes = type.getArraySizes())
     {
         info->arraySizes.assign(arraySizes->begin(), arraySizes->end());
     }
 }
 
-void CollectVariablesTraverser::recordBuiltInVaryingUsed(const ImmutableString &name,
+void CollectVariablesTraverser::recordBuiltInVaryingUsed(const TVariable &variable,
                                                          bool *addedFlag,
                                                          std::vector<Varying> *varyings)
 {
     ASSERT(varyings);
     if (!(*addedFlag))
     {
         Varying info;
-        setBuiltInInfoFromSymbolTable(name, &info);
+        setBuiltInInfoFromSymbol(variable, &info);
         info.staticUse   = true;
-        info.isInvariant = mSymbolTable->isVaryingInvariant(name);
+        info.active      = true;
+        info.isInvariant = mSymbolTable->isVaryingInvariant(variable.name());
         varyings->push_back(info);
         (*addedFlag) = true;
     }
 }
 
-void CollectVariablesTraverser::recordBuiltInFragmentOutputUsed(const ImmutableString &name,
+void CollectVariablesTraverser::recordBuiltInFragmentOutputUsed(const TVariable &variable,
                                                                 bool *addedFlag)
 {
     if (!(*addedFlag))
     {
         OutputVariable info;
-        setBuiltInInfoFromSymbolTable(name, &info);
+        setBuiltInInfoFromSymbol(variable, &info);
         info.staticUse = true;
+        info.active    = true;
         mOutputVariables->push_back(info);
         (*addedFlag) = true;
     }
 }
 
-void CollectVariablesTraverser::recordBuiltInAttributeUsed(const ImmutableString &name,
+void CollectVariablesTraverser::recordBuiltInAttributeUsed(const TVariable &variable,
                                                            bool *addedFlag)
 {
     if (!(*addedFlag))
     {
         Attribute info;
-        setBuiltInInfoFromSymbolTable(name, &info);
+        setBuiltInInfoFromSymbol(variable, &info);
         info.staticUse = true;
+        info.active    = true;
         info.location  = -1;
         mAttribs->push_back(info);
         (*addedFlag) = true;
     }
 }
 
 InterfaceBlock *CollectVariablesTraverser::recordGLInUsed(const TType &glInType)
 {
     if (!mPerVertexInAdded)
     {
         ASSERT(glInType.getQualifier() == EvqPerVertexIn);
         InterfaceBlock info;
         recordInterfaceBlock("gl_in", glInType, &info);
-        info.staticUse = true;
 
         mPerVertexInAdded = true;
         mInBlocks->push_back(info);
         return &mInBlocks->back();
     }
     else
     {
         return FindVariable(ImmutableString("gl_PerVertex"), mInBlocks);
     }
 }
 
-// We want to check whether a uniform/varying is statically used
-// because we only count the used ones in packing computing.
-// Also, gl_FragCoord, gl_PointCoord, and gl_FrontFacing count
-// toward varying counting if they are statically used in a fragment
-// shader.
+bool CollectVariablesTraverser::visitInvariantDeclaration(Visit visit,
+                                                          TIntermInvariantDeclaration *node)
+{
+    // We should not mark variables as active just based on an invariant declaration, so we don't
+    // traverse the symbols declared invariant.
+    return false;
+}
+
+// We want to check whether a uniform/varying is active because we need to skip updating inactive
+// ones. We also only count the active ones in packing computing. Also, gl_FragCoord, gl_PointCoord,
+// and gl_FrontFacing count toward varying counting if they are active in a fragment shader.
 void CollectVariablesTraverser::visitSymbol(TIntermSymbol *symbol)
 {
     ASSERT(symbol != nullptr);
 
     if (symbol->variable().symbolType() == SymbolType::AngleInternal ||
         symbol->variable().symbolType() == SymbolType::Empty)
     {
         // Internal variables or nameless variables are not collected.
@@ -380,37 +387,41 @@ void CollectVariablesTraverser::visitSym
         {
             Uniform info;
             const char kName[] = "gl_DepthRange";
             info.name          = kName;
             info.mappedName    = kName;
             info.type          = GL_NONE;
             info.precision     = GL_NONE;
             info.staticUse     = true;
+            info.active        = true;
 
             ShaderVariable nearInfo(GL_FLOAT);
             const char kNearName[] = "near";
             nearInfo.name          = kNearName;
             nearInfo.mappedName    = kNearName;
             nearInfo.precision     = GL_HIGH_FLOAT;
             nearInfo.staticUse     = true;
+            nearInfo.active        = true;
 
             ShaderVariable farInfo(GL_FLOAT);
             const char kFarName[] = "far";
             farInfo.name          = kFarName;
             farInfo.mappedName    = kFarName;
             farInfo.precision     = GL_HIGH_FLOAT;
             farInfo.staticUse     = true;
+            farInfo.active        = true;
 
             ShaderVariable diffInfo(GL_FLOAT);
             const char kDiffName[] = "diff";
             diffInfo.name          = kDiffName;
             diffInfo.mappedName    = kDiffName;
             diffInfo.precision     = GL_HIGH_FLOAT;
             diffInfo.staticUse     = true;
+            diffInfo.active        = true;
 
             info.fields.push_back(nearInfo);
             info.fields.push_back(farInfo);
             info.fields.push_back(diffInfo);
 
             mUniforms->push_back(info);
             mDepthRangeAdded = true;
         }
@@ -445,148 +456,126 @@ void CollectVariablesTraverser::visitSym
             case EvqBuffer:
             {
                 const TInterfaceBlock *interfaceBlock = symbol->getType().getInterfaceBlock();
                 var =
                     FindVariableInInterfaceBlock(symbolName, interfaceBlock, mShaderStorageBlocks);
             }
             break;
             case EvqFragCoord:
-                recordBuiltInVaryingUsed(ImmutableString("gl_FragCoord"), &mFragCoordAdded,
-                                         mInputVaryings);
+                recordBuiltInVaryingUsed(symbol->variable(), &mFragCoordAdded, mInputVaryings);
                 return;
             case EvqFrontFacing:
-                recordBuiltInVaryingUsed(ImmutableString("gl_FrontFacing"), &mFrontFacingAdded,
-                                         mInputVaryings);
+                recordBuiltInVaryingUsed(symbol->variable(), &mFrontFacingAdded, mInputVaryings);
                 return;
             case EvqPointCoord:
-                recordBuiltInVaryingUsed(ImmutableString("gl_PointCoord"), &mPointCoordAdded,
-                                         mInputVaryings);
+                recordBuiltInVaryingUsed(symbol->variable(), &mPointCoordAdded, mInputVaryings);
                 return;
             case EvqInstanceID:
                 // Whenever the SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW option is set,
                 // gl_InstanceID is added inside expressions to initialize ViewID_OVR and
-                // InstanceID. gl_InstanceID is not added to the symbol table for ESSL1 shaders
-                // which makes it necessary to populate the type information explicitly instead of
-                // extracting it from the symbol table.
-                if (!mInstanceIDAdded)
-                {
-                    Attribute info;
-                    const char kName[] = "gl_InstanceID";
-                    info.name          = kName;
-                    info.mappedName    = kName;
-                    info.type          = GL_INT;
-                    info.precision     = GL_HIGH_INT;  // Defined by spec.
-                    info.staticUse     = true;
-                    info.location      = -1;
-                    mAttribs->push_back(info);
-                    mInstanceIDAdded = true;
-                }
+                // InstanceID. Note that gl_InstanceID is not added to the symbol table for ESSL1
+                // shaders.
+                recordBuiltInAttributeUsed(symbol->variable(), &mInstanceIDAdded);
                 return;
             case EvqVertexID:
-                recordBuiltInAttributeUsed(ImmutableString("gl_VertexID"), &mVertexIDAdded);
+                recordBuiltInAttributeUsed(symbol->variable(), &mVertexIDAdded);
                 return;
             case EvqPosition:
-                recordBuiltInVaryingUsed(ImmutableString("gl_Position"), &mPositionAdded,
-                                         mOutputVaryings);
+                recordBuiltInVaryingUsed(symbol->variable(), &mPositionAdded, mOutputVaryings);
                 return;
             case EvqPointSize:
-                recordBuiltInVaryingUsed(ImmutableString("gl_PointSize"), &mPointSizeAdded,
-                                         mOutputVaryings);
+                recordBuiltInVaryingUsed(symbol->variable(), &mPointSizeAdded, mOutputVaryings);
                 return;
             case EvqLastFragData:
-                recordBuiltInVaryingUsed(ImmutableString("gl_LastFragData"), &mLastFragDataAdded,
-                                         mInputVaryings);
+                recordBuiltInVaryingUsed(symbol->variable(), &mLastFragDataAdded, mInputVaryings);
                 return;
             case EvqFragColor:
-                recordBuiltInFragmentOutputUsed(ImmutableString("gl_FragColor"), &mFragColorAdded);
+                recordBuiltInFragmentOutputUsed(symbol->variable(), &mFragColorAdded);
                 return;
             case EvqFragData:
                 if (!mFragDataAdded)
                 {
                     OutputVariable info;
-                    setBuiltInInfoFromSymbolTable(ImmutableString("gl_FragData"), &info);
+                    setBuiltInInfoFromSymbol(symbol->variable(), &info);
                     if (!IsExtensionEnabled(mExtensionBehavior, TExtension::EXT_draw_buffers))
                     {
                         ASSERT(info.arraySizes.size() == 1u);
                         info.arraySizes.back() = 1u;
                     }
                     info.staticUse = true;
+                    info.active    = true;
                     mOutputVariables->push_back(info);
                     mFragDataAdded = true;
                 }
                 return;
             case EvqFragDepthEXT:
-                recordBuiltInFragmentOutputUsed(ImmutableString("gl_FragDepthEXT"),
-                                                &mFragDepthEXTAdded);
+                recordBuiltInFragmentOutputUsed(symbol->variable(), &mFragDepthEXTAdded);
                 return;
             case EvqFragDepth:
-                recordBuiltInFragmentOutputUsed(ImmutableString("gl_FragDepth"), &mFragDepthAdded);
+                recordBuiltInFragmentOutputUsed(symbol->variable(), &mFragDepthAdded);
                 return;
             case EvqSecondaryFragColorEXT:
-                recordBuiltInFragmentOutputUsed(ImmutableString("gl_SecondaryFragColorEXT"),
-                                                &mSecondaryFragColorEXTAdded);
+                recordBuiltInFragmentOutputUsed(symbol->variable(), &mSecondaryFragColorEXTAdded);
                 return;
             case EvqSecondaryFragDataEXT:
-                recordBuiltInFragmentOutputUsed(ImmutableString("gl_SecondaryFragDataEXT"),
-                                                &mSecondaryFragDataEXTAdded);
+                recordBuiltInFragmentOutputUsed(symbol->variable(), &mSecondaryFragDataEXTAdded);
                 return;
             case EvqInvocationID:
-                recordBuiltInVaryingUsed(ImmutableString("gl_InvocationID"), &mInvocationIDAdded,
-                                         mInputVaryings);
+                recordBuiltInVaryingUsed(symbol->variable(), &mInvocationIDAdded, mInputVaryings);
                 break;
             case EvqPrimitiveIDIn:
-                recordBuiltInVaryingUsed(ImmutableString("gl_PrimitiveIDIn"), &mPrimitiveIDInAdded,
-                                         mInputVaryings);
+                recordBuiltInVaryingUsed(symbol->variable(), &mPrimitiveIDInAdded, mInputVaryings);
                 break;
             case EvqPrimitiveID:
                 if (mShaderType == GL_GEOMETRY_SHADER_EXT)
                 {
-                    recordBuiltInVaryingUsed(ImmutableString("gl_PrimitiveID"), &mPrimitiveIDAdded,
+                    recordBuiltInVaryingUsed(symbol->variable(), &mPrimitiveIDAdded,
                                              mOutputVaryings);
                 }
                 else
                 {
                     ASSERT(mShaderType == GL_FRAGMENT_SHADER);
-                    recordBuiltInVaryingUsed(ImmutableString("gl_PrimitiveID"), &mPrimitiveIDAdded,
+                    recordBuiltInVaryingUsed(symbol->variable(), &mPrimitiveIDAdded,
                                              mInputVaryings);
                 }
                 break;
             case EvqLayer:
                 if (mShaderType == GL_GEOMETRY_SHADER_EXT)
                 {
-                    recordBuiltInVaryingUsed(ImmutableString("gl_Layer"), &mLayerAdded,
-                                             mOutputVaryings);
+                    recordBuiltInVaryingUsed(symbol->variable(), &mLayerAdded, mOutputVaryings);
                 }
                 else if (mShaderType == GL_FRAGMENT_SHADER)
                 {
-                    recordBuiltInVaryingUsed(ImmutableString("gl_Layer"), &mLayerAdded,
-                                             mInputVaryings);
+                    recordBuiltInVaryingUsed(symbol->variable(), &mLayerAdded, mInputVaryings);
                 }
                 else
                 {
                     ASSERT(mShaderType == GL_VERTEX_SHADER &&
                            IsExtensionEnabled(mExtensionBehavior, TExtension::OVR_multiview));
                 }
                 break;
             default:
                 break;
         }
     }
     if (var)
     {
-        MarkStaticallyUsed(var);
+        MarkActive(var);
     }
 }
 
 void CollectVariablesTraverser::setFieldOrVariableProperties(const TType &type,
+                                                             bool staticUse,
                                                              ShaderVariable *variableOut) const
 {
     ASSERT(variableOut);
 
+    variableOut->staticUse = staticUse;
+
     const TStructure *structure = type.getStruct();
     if (!structure)
     {
         variableOut->type      = GLVariableType(type);
         variableOut->precision = GLVariablePrecision(type);
     }
     else
     {
@@ -599,43 +588,45 @@ void CollectVariablesTraverser::setField
 
         const TFieldList &fields = structure->fields();
 
         for (const TField *field : fields)
         {
             // Regardless of the variable type (uniform, in/out etc.) its fields are always plain
             // ShaderVariable objects.
             ShaderVariable fieldVariable;
-            setFieldProperties(*field->type(), field->name(), &fieldVariable);
+            setFieldProperties(*field->type(), field->name(), staticUse, &fieldVariable);
             variableOut->fields.push_back(fieldVariable);
         }
     }
     if (auto *arraySizes = type.getArraySizes())
     {
         variableOut->arraySizes.assign(arraySizes->begin(), arraySizes->end());
     }
 }
 
 void CollectVariablesTraverser::setFieldProperties(const TType &type,
                                                    const ImmutableString &name,
+                                                   bool staticUse,
                                                    ShaderVariable *variableOut) const
 {
     ASSERT(variableOut);
-    setFieldOrVariableProperties(type, variableOut);
+    setFieldOrVariableProperties(type, staticUse, variableOut);
     variableOut->name.assign(name.data(), name.length());
     variableOut->mappedName = HashName(name, mHashFunction, nullptr).data();
 }
 
 void CollectVariablesTraverser::setCommonVariableProperties(const TType &type,
                                                             const TVariable &variable,
                                                             ShaderVariable *variableOut) const
 {
     ASSERT(variableOut);
 
-    setFieldOrVariableProperties(type, variableOut);
+    variableOut->staticUse = mSymbolTable->isStaticallyUsed(variable);
+    setFieldOrVariableProperties(type, variableOut->staticUse, variableOut);
     ASSERT(variable.symbolType() != SymbolType::Empty);
     variableOut->name.assign(variable.name().data(), variable.name().length());
     variableOut->mappedName = getMappedName(&variable);
 }
 
 Attribute CollectVariablesTraverser::recordAttribute(const TIntermSymbol &variable) const
 {
     const TType &type = variable.getType();
@@ -701,41 +692,73 @@ void CollectVariablesTraverser::recordIn
     const TInterfaceBlock *blockType = interfaceBlockType.getInterfaceBlock();
     ASSERT(blockType);
 
     interfaceBlock->name       = blockType->name().data();
     interfaceBlock->mappedName = getMappedName(blockType);
     if (instanceName != nullptr)
     {
         interfaceBlock->instanceName = instanceName;
+        const TSymbol *blockSymbol   = nullptr;
+        if (strncmp(instanceName, "gl_in", 5u) == 0)
+        {
+            blockSymbol = mSymbolTable->getGlInVariableWithArraySize();
+        }
+        else
+        {
+            blockSymbol = mSymbolTable->findGlobal(ImmutableString(instanceName));
+        }
+        ASSERT(blockSymbol && blockSymbol->isVariable());
+        interfaceBlock->staticUse =
+            mSymbolTable->isStaticallyUsed(*static_cast<const TVariable *>(blockSymbol));
     }
     ASSERT(!interfaceBlockType.isArrayOfArrays());  // Disallowed by GLSL ES 3.10 section 4.3.9
     interfaceBlock->arraySize = interfaceBlockType.isArray() ? interfaceBlockType.getOutermostArraySize() : 0;
 
     interfaceBlock->blockType = GetBlockType(interfaceBlockType.getQualifier());
     if (interfaceBlock->blockType == BlockType::BLOCK_UNIFORM ||
         interfaceBlock->blockType == BlockType::BLOCK_BUFFER)
     {
         // TODO(oetuaho): Remove setting isRowMajorLayout.
         interfaceBlock->isRowMajorLayout = false;
         interfaceBlock->binding          = blockType->blockBinding();
         interfaceBlock->layout           = GetBlockLayoutType(blockType->blockStorage());
     }
 
     // Gather field information
+    bool anyFieldStaticallyUsed = false;
     for (const TField *field : blockType->fields())
     {
         const TType &fieldType = *field->type();
 
+        bool staticUse = false;
+        if (instanceName == nullptr)
+        {
+            // Static use of individual fields has been recorded, since they are present in the
+            // symbol table as variables.
+            const TSymbol *fieldSymbol = mSymbolTable->findGlobal(field->name());
+            ASSERT(fieldSymbol && fieldSymbol->isVariable());
+            staticUse =
+                mSymbolTable->isStaticallyUsed(*static_cast<const TVariable *>(fieldSymbol));
+            if (staticUse)
+            {
+                anyFieldStaticallyUsed = true;
+            }
+        }
+
         InterfaceBlockField fieldVariable;
-        setFieldProperties(fieldType, field->name(), &fieldVariable);
+        setFieldProperties(fieldType, field->name(), staticUse, &fieldVariable);
         fieldVariable.isRowMajorLayout =
             (fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor);
         interfaceBlock->fields.push_back(fieldVariable);
     }
+    if (anyFieldStaticallyUsed)
+    {
+        interfaceBlock->staticUse = true;
+    }
 }
 
 Uniform CollectVariablesTraverser::recordUniform(const TIntermSymbol &variable) const
 {
     Uniform uniform;
     setCommonVariableProperties(variable.getType(), variable.variable(), &uniform);
     uniform.binding  = variable.getType().getLayoutQualifier().binding;
     uniform.location = variable.getType().getLayoutQualifier().location;
@@ -843,17 +866,17 @@ InterfaceBlock *CollectVariablesTraverse
     }
     return namedBlock;
 }
 
 bool CollectVariablesTraverser::visitBinary(Visit, TIntermBinary *binaryNode)
 {
     if (binaryNode->getOp() == EOpIndexDirectInterfaceBlock)
     {
-        // NOTE: we do not determine static use for individual blocks of an array
+        // NOTE: we do not determine static use / activeness for individual blocks of an array.
         TIntermTyped *blockNode = binaryNode->getLeft()->getAsTyped();
         ASSERT(blockNode);
 
         TIntermConstantUnion *constantUnion = binaryNode->getRight()->getAsConstantUnion();
         ASSERT(constantUnion);
 
         InterfaceBlock *namedBlock = nullptr;
 
@@ -877,20 +900,25 @@ bool CollectVariablesTraverser::visitBin
         }
 
         const TInterfaceBlock *interfaceBlock = blockNode->getType().getInterfaceBlock();
         if (!namedBlock)
         {
             namedBlock = findNamedInterfaceBlock(interfaceBlock->name());
         }
         ASSERT(namedBlock);
-        namedBlock->staticUse   = true;
+        ASSERT(namedBlock->staticUse);
+        namedBlock->active      = true;
         unsigned int fieldIndex = static_cast<unsigned int>(constantUnion->getIConst(0));
         ASSERT(fieldIndex < namedBlock->fields.size());
+        // TODO(oetuaho): Would be nicer to record static use of fields of named interface blocks
+        // more accurately at parse time - now we only mark the fields statically used if they are
+        // active. http://anglebug.com/2440
         namedBlock->fields[fieldIndex].staticUse = true;
+        namedBlock->fields[fieldIndex].active    = true;
 
         if (traverseIndexExpression)
         {
             ASSERT(interfaceIndexingNode);
             interfaceIndexingNode->getRight()->traverse(this);
         }
         return false;
     }
@@ -906,20 +934,18 @@ void CollectVariables(TIntermBlock *root
                       std::vector<Uniform> *uniforms,
                       std::vector<Varying> *inputVaryings,
                       std::vector<Varying> *outputVaryings,
                       std::vector<InterfaceBlock> *uniformBlocks,
                       std::vector<InterfaceBlock> *shaderStorageBlocks,
                       std::vector<InterfaceBlock> *inBlocks,
                       ShHashFunction64 hashFunction,
                       TSymbolTable *symbolTable,
-                      int shaderVersion,
                       GLenum shaderType,
                       const TExtensionBehavior &extensionBehavior)
 {
     CollectVariablesTraverser collect(attributes, outputVariables, uniforms, inputVaryings,
                                       outputVaryings, uniformBlocks, shaderStorageBlocks, inBlocks,
-                                      hashFunction, symbolTable, shaderVersion, shaderType,
-                                      extensionBehavior);
+                                      hashFunction, symbolTable, shaderType, extensionBehavior);
     root->traverse(&collect);
 }
 
 }  // namespace sh
--- a/gfx/angle/checkout/src/compiler/translator/CollectVariables.h
+++ b/gfx/angle/checkout/src/compiler/translator/CollectVariables.h
@@ -24,14 +24,13 @@ void CollectVariables(TIntermBlock *root
                       std::vector<Uniform> *uniforms,
                       std::vector<Varying> *inputVaryings,
                       std::vector<Varying> *outputVaryings,
                       std::vector<InterfaceBlock> *uniformBlocks,
                       std::vector<InterfaceBlock> *shaderStorageBlocks,
                       std::vector<InterfaceBlock> *inBlocks,
                       ShHashFunction64 hashFunction,
                       TSymbolTable *symbolTable,
-                      int shaderVersion,
                       GLenum shaderType,
                       const TExtensionBehavior &extensionBehavior);
 }
 
 #endif  // COMPILER_TRANSLATOR_COLLECTVARIABLES_H_
--- a/gfx/angle/checkout/src/compiler/translator/Compiler.cpp
+++ b/gfx/angle/checkout/src/compiler/translator/Compiler.cpp
@@ -5,53 +5,53 @@
 //
 
 #include "compiler/translator/Compiler.h"
 
 #include <sstream>
 
 #include "angle_gl.h"
 #include "common/utilities.h"
-#include "compiler/translator/AddAndTrueToLoopCondition.h"
 #include "compiler/translator/CallDAG.h"
-#include "compiler/translator/ClampFragDepth.h"
-#include "compiler/translator/ClampPointSize.h"
 #include "compiler/translator/CollectVariables.h"
-#include "compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.h"
-#include "compiler/translator/DeferGlobalInitializers.h"
-#include "compiler/translator/EmulateGLFragColorBroadcast.h"
-#include "compiler/translator/EmulatePrecision.h"
-#include "compiler/translator/FoldExpressions.h"
 #include "compiler/translator/Initialize.h"
-#include "compiler/translator/InitializeVariables.h"
-#include "compiler/translator/IntermNodePatternMatcher.h"
 #include "compiler/translator/IsASTDepthBelowLimit.h"
 #include "compiler/translator/OutputTree.h"
 #include "compiler/translator/ParseContext.h"
-#include "compiler/translator/PruneNoOps.h"
-#include "compiler/translator/RegenerateStructNames.h"
-#include "compiler/translator/RemoveArrayLengthMethod.h"
-#include "compiler/translator/RemoveEmptySwitchStatements.h"
-#include "compiler/translator/RemoveInvariantDeclaration.h"
-#include "compiler/translator/RemoveNoOpCasesFromEndOfSwitchStatements.h"
-#include "compiler/translator/RemovePow.h"
-#include "compiler/translator/RemoveUnreferencedVariables.h"
-#include "compiler/translator/RewriteDoWhile.h"
-#include "compiler/translator/ScalarizeVecAndMatConstructorArgs.h"
-#include "compiler/translator/SeparateDeclarations.h"
-#include "compiler/translator/SimplifyLoopConditions.h"
-#include "compiler/translator/SplitSequenceOperator.h"
-#include "compiler/translator/UnfoldShortCircuitAST.h"
-#include "compiler/translator/UseInterfaceBlockFields.h"
 #include "compiler/translator/ValidateLimitations.h"
 #include "compiler/translator/ValidateMaxParameters.h"
 #include "compiler/translator/ValidateOutputs.h"
 #include "compiler/translator/ValidateVaryingLocations.h"
 #include "compiler/translator/VariablePacker.h"
-#include "compiler/translator/VectorizeVectorScalarArithmetic.h"
+#include "compiler/translator/tree_ops/AddAndTrueToLoopCondition.h"
+#include "compiler/translator/tree_ops/ClampFragDepth.h"
+#include "compiler/translator/tree_ops/ClampPointSize.h"
+#include "compiler/translator/tree_ops/DeclareAndInitBuiltinsForInstancedMultiview.h"
+#include "compiler/translator/tree_ops/DeferGlobalInitializers.h"
+#include "compiler/translator/tree_ops/EmulateGLFragColorBroadcast.h"
+#include "compiler/translator/tree_ops/EmulatePrecision.h"
+#include "compiler/translator/tree_ops/FoldExpressions.h"
+#include "compiler/translator/tree_ops/InitializeVariables.h"
+#include "compiler/translator/tree_ops/PruneEmptyCases.h"
+#include "compiler/translator/tree_ops/PruneNoOps.h"
+#include "compiler/translator/tree_ops/RegenerateStructNames.h"
+#include "compiler/translator/tree_ops/RemoveArrayLengthMethod.h"
+#include "compiler/translator/tree_ops/RemoveInvariantDeclaration.h"
+#include "compiler/translator/tree_ops/RemovePow.h"
+#include "compiler/translator/tree_ops/RemoveUnreferencedVariables.h"
+#include "compiler/translator/tree_ops/RewriteDoWhile.h"
+#include "compiler/translator/tree_ops/ScalarizeVecAndMatConstructorArgs.h"
+#include "compiler/translator/tree_ops/SeparateDeclarations.h"
+#include "compiler/translator/tree_ops/SimplifyLoopConditions.h"
+#include "compiler/translator/tree_ops/SplitSequenceOperator.h"
+#include "compiler/translator/tree_ops/UnfoldShortCircuitAST.h"
+#include "compiler/translator/tree_ops/UseInterfaceBlockFields.h"
+#include "compiler/translator/tree_ops/VectorizeVectorScalarArithmetic.h"
+#include "compiler/translator/tree_util/BuiltIn_autogen.h"
+#include "compiler/translator/tree_util/IntermNodePatternMatcher.h"
 #include "compiler/translator/util.h"
 #include "third_party/compiler/ArrayBoundsClamper.h"
 
 namespace sh
 {
 
 namespace
 {
@@ -188,22 +188,22 @@ class TScopedPoolAllocator
     TPoolAllocator *mAllocator;
 };
 
 class TScopedSymbolTableLevel
 {
   public:
     TScopedSymbolTableLevel(TSymbolTable *table) : mTable(table)
     {
-        ASSERT(mTable->atBuiltInLevel());
+        ASSERT(mTable->isEmpty());
         mTable->push();
     }
     ~TScopedSymbolTableLevel()
     {
-        while (!mTable->atBuiltInLevel())
+        while (!mTable->isEmpty())
             mTable->pop();
     }
 
   private:
     TSymbolTable *mTable;
 };
 
 int MapSpecToShaderVersion(ShShaderSpec spec)
@@ -220,16 +220,61 @@ int MapSpecToShaderVersion(ShShaderSpec 
         case SH_WEBGL3_SPEC:
             return 310;
         default:
             UNREACHABLE();
             return 0;
     }
 }
 
+bool ValidateFragColorAndFragData(GLenum shaderType,
+                                  int shaderVersion,
+                                  const TSymbolTable &symbolTable,
+                                  TDiagnostics *diagnostics)
+{
+    if (shaderVersion > 100 || shaderType != GL_FRAGMENT_SHADER)
+    {
+        return true;
+    }
+
+    bool usesFragColor = false;
+    bool usesFragData  = false;
+    // This validation is a bit stricter than the spec - it's only an error to write to
+    // both FragData and FragColor. But because it's better not to have reads from undefined
+    // variables, we always return an error if they are both referenced, rather than only if they
+    // are written.
+    if (symbolTable.isStaticallyUsed(*BuiltInVariable::gl_FragColor()) ||
+        symbolTable.isStaticallyUsed(*BuiltInVariable::gl_SecondaryFragColorEXT()))
+    {
+        usesFragColor = true;
+    }
+    // Extension variables may not always be initialized (saves some time at symbol table init).
+    bool secondaryFragDataUsed =
+        symbolTable.gl_SecondaryFragDataEXT() != nullptr &&
+        symbolTable.isStaticallyUsed(*symbolTable.gl_SecondaryFragDataEXT());
+    if (symbolTable.isStaticallyUsed(*symbolTable.gl_FragData()) || secondaryFragDataUsed)
+    {
+        usesFragData = true;
+    }
+    if (usesFragColor && usesFragData)
+    {
+        const char *errorMessage = "cannot use both gl_FragData and gl_FragColor";
+        if (symbolTable.isStaticallyUsed(*BuiltInVariable::gl_SecondaryFragColorEXT()) ||
+            secondaryFragDataUsed)
+        {
+            errorMessage =
+                "cannot use both output variable sets (gl_FragData, gl_SecondaryFragDataEXT)"
+                " and (gl_FragColor, gl_SecondaryFragColorEXT)";
+        }
+        diagnostics->globalError(errorMessage);
+        return false;
+    }
+    return true;
+}
+
 }  // namespace
 
 TShHandleBase::TShHandleBase()
 {
     allocator.push();
     SetGlobalPoolAllocator(&allocator);
 }
 
@@ -446,41 +491,36 @@ bool TCompiler::checkAndSimplifyAST(TInt
     }
 
     if (shouldRunLoopAndIndexingValidation(compileOptions) &&
         !ValidateLimitations(root, shaderType, &symbolTable, &mDiagnostics))
     {
         return false;
     }
 
+    if (!ValidateFragColorAndFragData(shaderType, shaderVersion, symbolTable, &mDiagnostics))
+    {
+        return false;
+    }
+
     // Fold expressions that could not be folded before validation that was done as a part of
     // parsing.
     FoldExpressions(root, &mDiagnostics);
     // Folding should only be able to generate warnings.
     ASSERT(mDiagnostics.numErrors() == 0);
 
     // We prune no-ops to work around driver bugs and to keep AST processing and output simple.
     // The following kinds of no-ops are pruned:
     //   1. Empty declarations "int;".
     //   2. Literal statements: "1.0;". The ESSL output doesn't define a default precision
     //      for float, so float literal statements would end up with no precision which is
     //      invalid ESSL.
     // After this empty declarations are not allowed in the AST.
     PruneNoOps(root, &symbolTable);
 
-    // In case the last case inside a switch statement is a certain type of no-op, GLSL
-    // compilers in drivers may not accept it. In this case we clean up the dead code from the
-    // end of switch statements. This is also required because PruneNoOps may have left switch
-    // statements that only contained an empty declaration inside the final case in an invalid
-    // state. Relies on that PruneNoOps has already been run.
-    RemoveNoOpCasesFromEndOfSwitchStatements(root, &symbolTable);
-
-    // Remove empty switch statements - this makes output simpler.
-    RemoveEmptySwitchStatements(root);
-
     // Create the function DAG and check there is no recursion
     if (!initCallDag(root))
     {
         return false;
     }
 
     if ((compileOptions & SH_LIMIT_CALL_STACK_DEPTH) && !checkCallDepth())
     {
@@ -543,17 +583,17 @@ bool TCompiler::checkAndSimplifyAST(TInt
 
     if (compileOptions & SH_UNFOLD_SHORT_CIRCUIT)
     {
         UnfoldShortCircuitAST(root);
     }
 
     if (compileOptions & SH_REMOVE_POW_WITH_CONSTANT_EXPONENT)
     {
-        RemovePow(root);
+        RemovePow(root, &symbolTable);
     }
 
     if (compileOptions & SH_REGENERATE_STRUCT_NAMES)
     {
         RegenerateStructNames gen(&symbolTable);
         root->traverse(&gen);
     }
 
@@ -583,16 +623,24 @@ bool TCompiler::checkAndSimplifyAST(TInt
 
     SplitSequenceOperator(root, IntermNodePatternMatcher::kArrayLengthMethod | simplifyScalarized,
                           &getSymbolTable());
 
     RemoveArrayLengthMethod(root);
 
     RemoveUnreferencedVariables(root, &symbolTable);
 
+    // In case the last case inside a switch statement is a certain type of no-op, GLSL compilers in
+    // drivers may not accept it. In this case we clean up the dead code from the end of switch
+    // statements. This is also required because PruneNoOps or RemoveUnreferencedVariables may have
+    // left switch statements that only contained an empty declaration inside the final case in an
+    // invalid state. Relies on that PruneNoOps and RemoveUnreferencedVariables have already been
+    // run.
+    PruneEmptyCases(root);
+
     // Built-in function emulation needs to happen after validateLimitations pass.
     // TODO(jmadill): Remove global pool allocator.
     GetGlobalPoolAllocator()->lock();
     initBuiltInFunctionEmulator(&builtInFunctionEmulator, compileOptions);
     GetGlobalPoolAllocator()->unlock();
     builtInFunctionEmulator.markBuiltInFunctionsForEmulation(root);
 
     if (compileOptions & SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS)
@@ -600,17 +648,17 @@ bool TCompiler::checkAndSimplifyAST(TInt
         ScalarizeVecAndMatConstructorArgs(root, shaderType, fragmentPrecisionHigh, &symbolTable);
     }
 
     if (shouldCollectVariables(compileOptions))
     {
         ASSERT(!variablesCollected);
         CollectVariables(root, &attributes, &outputVariables, &uniforms, &inputVaryings,
                          &outputVaryings, &uniformBlocks, &shaderStorageBlocks, &inBlocks,
-                         hashFunction, &symbolTable, shaderVersion, shaderType, extensionBehavior);
+                         hashFunction, &symbolTable, shaderType, extensionBehavior);
         collectInterfaceBlocks();
         variablesCollected = true;
         if (compileOptions & SH_USE_UNUSED_STANDARD_SHARED_BLOCKS)
         {
             useAllMembersInUnusedStandardAndSharedBlocks(root);
         }
         if (compileOptions & SH_ENFORCE_PACKING_RESTRICTIONS)
         {
deleted file mode 100644
--- a/gfx/angle/checkout/src/compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.cpp
+++ /dev/null
@@ -1,210 +0,0 @@
-//
-// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// Applies the necessary AST transformations to support multiview rendering through instancing.
-// Check the header file For more information.
-//
-
-#include "compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.h"
-
-#include "compiler/translator/FindMain.h"
-#include "compiler/translator/InitializeVariables.h"
-#include "compiler/translator/IntermNode_util.h"
-#include "compiler/translator/IntermTraverse.h"
-#include "compiler/translator/ReplaceVariable.h"
-#include "compiler/translator/StaticType.h"
-#include "compiler/translator/SymbolTable.h"
-#include "compiler/translator/util.h"
-
-namespace sh
-{
-
-namespace
-{
-
-constexpr const ImmutableString kGlLayerString("gl_Layer");
-constexpr const ImmutableString kGlViewportIndexString("gl_ViewportIndex");
-constexpr const ImmutableString kGlViewIdOVRString("gl_ViewID_OVR");
-constexpr const ImmutableString kGlInstanceIdString("gl_InstanceID");
-constexpr const ImmutableString kViewIDVariableName("ViewID_OVR");
-constexpr const ImmutableString kInstanceIDVariableName("InstanceID");
-constexpr const ImmutableString kMultiviewBaseViewLayerIndexVariableName(
-    "multiviewBaseViewLayerIndex");
-
-TIntermSymbol *CreateGLInstanceIDSymbol(const TSymbolTable &symbolTable)
-{
-    return ReferenceBuiltInVariable(kGlInstanceIdString, symbolTable, 300);
-}
-
-// Adds the InstanceID and ViewID_OVR initializers to the end of the initializers' sequence.
-void InitializeViewIDAndInstanceID(const TVariable *viewID,
-                                   const TVariable *instanceID,
-                                   unsigned numberOfViews,
-                                   const TSymbolTable &symbolTable,
-                                   TIntermSequence *initializers)
-{
-    // Create an unsigned numberOfViews node.
-    TConstantUnion *numberOfViewsUnsignedConstant = new TConstantUnion();
-    numberOfViewsUnsignedConstant->setUConst(numberOfViews);
-    TIntermConstantUnion *numberOfViewsUint =
-        new TIntermConstantUnion(numberOfViewsUnsignedConstant, TType(EbtUInt, EbpHigh, EvqConst));
-
-    // Create a uint(gl_InstanceID) node.
-    TIntermSequence *glInstanceIDSymbolCastArguments = new TIntermSequence();
-    glInstanceIDSymbolCastArguments->push_back(CreateGLInstanceIDSymbol(symbolTable));
-    TIntermAggregate *glInstanceIDAsUint = TIntermAggregate::CreateConstructor(
-        TType(EbtUInt, EbpHigh, EvqTemporary), glInstanceIDSymbolCastArguments);
-
-    // Create a uint(gl_InstanceID) / numberOfViews node.
-    TIntermBinary *normalizedInstanceID =
-        new TIntermBinary(EOpDiv, glInstanceIDAsUint, numberOfViewsUint);
-
-    // Create an int(uint(gl_InstanceID) / numberOfViews) node.
-    TIntermSequence *normalizedInstanceIDCastArguments = new TIntermSequence();
-    normalizedInstanceIDCastArguments->push_back(normalizedInstanceID);
-    TIntermAggregate *normalizedInstanceIDAsInt = TIntermAggregate::CreateConstructor(
-        TType(EbtInt, EbpHigh, EvqTemporary), normalizedInstanceIDCastArguments);
-
-    // Create an InstanceID = int(uint(gl_InstanceID) / numberOfViews) node.
-    TIntermBinary *instanceIDInitializer =
-        new TIntermBinary(EOpAssign, new TIntermSymbol(instanceID), normalizedInstanceIDAsInt);
-    initializers->push_back(instanceIDInitializer);
-
-    // Create a uint(gl_InstanceID) % numberOfViews node.
-    TIntermBinary *normalizedViewID =
-        new TIntermBinary(EOpIMod, glInstanceIDAsUint->deepCopy(), numberOfViewsUint->deepCopy());
-
-    // Create a ViewID_OVR = uint(gl_InstanceID) % numberOfViews node.
-    TIntermBinary *viewIDInitializer =
-        new TIntermBinary(EOpAssign, new TIntermSymbol(viewID), normalizedViewID);
-    initializers->push_back(viewIDInitializer);
-}
-
-void DeclareGlobalVariable(TIntermBlock *root, const TVariable *variable)
-{
-    TIntermDeclaration *declaration = new TIntermDeclaration();
-    declaration->appendDeclarator(new TIntermSymbol(variable));
-
-    TIntermSequence *globalSequence = root->getSequence();
-    globalSequence->insert(globalSequence->begin(), declaration);
-}
-
-// Adds a branch to write int(ViewID_OVR) to either gl_ViewportIndex or gl_Layer. The branch is
-// added to the end of the initializers' sequence.
-void SelectViewIndexInVertexShader(const TVariable *viewID,
-                                   const TVariable *multiviewBaseViewLayerIndex,
-                                   TIntermSequence *initializers,
-                                   const TSymbolTable &symbolTable)
-{
-    // Create an int(ViewID_OVR) node.
-    TIntermSequence *viewIDSymbolCastArguments = new TIntermSequence();
-    viewIDSymbolCastArguments->push_back(new TIntermSymbol(viewID));
-    TIntermAggregate *viewIDAsInt = TIntermAggregate::CreateConstructor(
-        TType(EbtInt, EbpHigh, EvqTemporary), viewIDSymbolCastArguments);
-
-    // Create a gl_ViewportIndex node.
-    TIntermSymbol *viewportIndexSymbol =
-        ReferenceBuiltInVariable(kGlViewportIndexString, symbolTable, 0);
-
-    // Create a { gl_ViewportIndex = int(ViewID_OVR) } node.
-    TIntermBlock *viewportIndexInitializerInBlock = new TIntermBlock();
-    viewportIndexInitializerInBlock->appendStatement(
-        new TIntermBinary(EOpAssign, viewportIndexSymbol, viewIDAsInt));
-
-    // Create a gl_Layer node.
-    TIntermSymbol *layerSymbol = ReferenceBuiltInVariable(kGlLayerString, symbolTable, 0);
-
-    // Create an int(ViewID_OVR) + multiviewBaseViewLayerIndex node
-    TIntermBinary *sumOfViewIDAndBaseViewIndex = new TIntermBinary(
-        EOpAdd, viewIDAsInt->deepCopy(), new TIntermSymbol(multiviewBaseViewLayerIndex));
-
-    // Create a { gl_Layer = int(ViewID_OVR) + multiviewBaseViewLayerIndex } node.
-    TIntermBlock *layerInitializerInBlock = new TIntermBlock();
-    layerInitializerInBlock->appendStatement(
-        new TIntermBinary(EOpAssign, layerSymbol, sumOfViewIDAndBaseViewIndex));
-
-    // Create a node to compare whether the base view index uniform is less than zero.
-    TIntermBinary *multiviewBaseViewLayerIndexZeroComparison =
-        new TIntermBinary(EOpLessThan, new TIntermSymbol(multiviewBaseViewLayerIndex),
-                          CreateZeroNode(TType(EbtInt, EbpHigh, EvqConst)));
-
-    // Create an if-else statement to select the code path.
-    TIntermIfElse *multiviewBranch =
-        new TIntermIfElse(multiviewBaseViewLayerIndexZeroComparison,
-                          viewportIndexInitializerInBlock, layerInitializerInBlock);
-
-    initializers->push_back(multiviewBranch);
-}
-
-}  // namespace
-
-void DeclareAndInitBuiltinsForInstancedMultiview(TIntermBlock *root,
-                                                 unsigned numberOfViews,
-                                                 GLenum shaderType,
-                                                 ShCompileOptions compileOptions,
-                                                 ShShaderOutput shaderOutput,
-                                                 TSymbolTable *symbolTable)
-{
-    ASSERT(shaderType == GL_VERTEX_SHADER || shaderType == GL_FRAGMENT_SHADER);
-
-    TQualifier viewIDQualifier  = (shaderType == GL_VERTEX_SHADER) ? EvqFlatOut : EvqFlatIn;
-    const TVariable *viewID =
-        new TVariable(symbolTable, kViewIDVariableName,
-                      new TType(EbtUInt, EbpHigh, viewIDQualifier), SymbolType::AngleInternal);
-
-    DeclareGlobalVariable(root, viewID);
-    ReplaceVariable(
-        root,
-        static_cast<const TVariable *>(symbolTable->findBuiltIn(kGlViewIdOVRString, 300, true)),
-        viewID);
-    if (shaderType == GL_VERTEX_SHADER)
-    {
-        // Replacing gl_InstanceID with InstanceID should happen before adding the initializers of
-        // InstanceID and ViewID.
-        const TType *instanceIDVariableType   = StaticType::Get<EbtInt, EbpHigh, EvqGlobal, 1, 1>();
-        const TVariable *instanceID =
-            new TVariable(symbolTable, kInstanceIDVariableName, instanceIDVariableType,
-                          SymbolType::AngleInternal);
-        DeclareGlobalVariable(root, instanceID);
-        ReplaceVariable(root,
-                        static_cast<const TVariable *>(
-                            symbolTable->findBuiltIn(kGlInstanceIdString, 300, true)),
-                        instanceID);
-
-        TIntermSequence *initializers = new TIntermSequence();
-        InitializeViewIDAndInstanceID(viewID, instanceID, numberOfViews, *symbolTable,
-                                      initializers);
-
-        // The AST transformation which adds the expression to select the viewport index should
-        // be done only for the GLSL and ESSL output.
-        const bool selectView = (compileOptions & SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER) != 0u;
-        // Assert that if the view is selected in the vertex shader, then the output is
-        // either GLSL or ESSL.
-        ASSERT(!selectView || IsOutputGLSL(shaderOutput) || IsOutputESSL(shaderOutput));
-        if (selectView)
-        {
-            // Add a uniform to switch between side-by-side and layered rendering.
-            const TType *baseLayerIndexVariableType =
-                StaticType::Get<EbtInt, EbpHigh, EvqUniform, 1, 1>();
-            const TVariable *multiviewBaseViewLayerIndex =
-                new TVariable(symbolTable, kMultiviewBaseViewLayerIndexVariableName,
-                              baseLayerIndexVariableType, SymbolType::AngleInternal);
-            DeclareGlobalVariable(root, multiviewBaseViewLayerIndex);
-
-            // Setting a value to gl_ViewportIndex or gl_Layer should happen after ViewID_OVR's
-            // initialization.
-            SelectViewIndexInVertexShader(viewID, multiviewBaseViewLayerIndex, initializers,
-                                          *symbolTable);
-        }
-
-        // Insert initializers at the beginning of main().
-        TIntermBlock *initializersBlock = new TIntermBlock();
-        initializersBlock->getSequence()->swap(*initializers);
-        TIntermBlock *mainBody = FindMainBody(root);
-        mainBody->getSequence()->insert(mainBody->getSequence()->begin(), initializersBlock);
-    }
-}
-
-}  // namespace sh
\ No newline at end of file
deleted file mode 100644
--- a/gfx/angle/checkout/src/compiler/translator/DeclareAndInitBuiltinsForInstancedMultiview.h
+++ /dev/null
@@ -1,48 +0,0 @@
-//
-// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// Regardless of the shader type, the following AST transformations are applied:
-// - Add declaration of View_ID_OVR.
-// - Replace every occurrence of gl_ViewID_OVR with ViewID_OVR, mark ViewID_OVR as internal and
-// declare it as a flat varying.
-//
-// If the shader type is a vertex shader, the following AST transformations are applied:
-// - Replace every occurrence of gl_InstanceID with InstanceID, mark InstanceID as internal and set
-// its qualifier to EvqTemporary.
-// - Add initializers of ViewID_OVR and InstanceID to the beginning of the body of main. The pass
-// should be executed before any variables get collected so that usage of gl_InstanceID is recorded.
-// - If the output is ESSL or GLSL and the SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER option is
-// enabled, the expression
-// "if (multiviewBaseViewLayerIndex < 0) {
-//      gl_ViewportIndex = int(ViewID_OVR);
-//  } else {
-//      gl_Layer = int(ViewID_OVR) + multiviewBaseViewLayerIndex;
-//  }"
-// is added after ViewID and InstanceID are initialized. Also, MultiviewRenderPath is added as a
-// uniform.
-//
-
-#ifndef COMPILER_TRANSLATOR_DECLAREANDINITBUILTINSFORINSTANCEDMULTIVIEW_H_
-#define COMPILER_TRANSLATOR_DECLAREANDINITBUILTINSFORINSTANCEDMULTIVIEW_H_
-
-#include "GLSLANG/ShaderLang.h"
-#include "angle_gl.h"
-
-namespace sh
-{
-
-class TIntermBlock;
-class TSymbolTable;
-
-void DeclareAndInitBuiltinsForInstancedMultiview(TIntermBlock *root,
-                                                 unsigned numberOfViews,
-                                                 GLenum shaderType,
-                                                 ShCompileOptions compileOptions,
-                                                 ShShaderOutput shaderOutput,
-                                                 TSymbolTable *symbolTable);
-
-}  // namespace sh
-
-#endif  // COMPILER_TRANSLATOR_DECLAREANDINITBUILTINSFORINSTANCEDMULTIVIEW_H_
\ No newline at end of file
deleted file mode 100644
--- a/gfx/angle/checkout/src/compiler/translator/DeferGlobalInitializers.cpp
+++ /dev/null
@@ -1,167 +0,0 @@
-//
-// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// DeferGlobalInitializers is an AST traverser that moves global initializers into a separate
-// function that is called in the beginning of main(). This enables initialization of globals with
-// uniforms or non-constant globals, as allowed by the WebGL spec. Some initializers referencing
-// non-constants may need to be unfolded into if statements in HLSL - this kind of steps should be
-// done after DeferGlobalInitializers is run. Note that it's important that the function definition
-// is at the end of the shader, as some globals may be declared after main().
-//
-// It can also initialize all uninitialized globals.
-//
-
-#include "compiler/translator/DeferGlobalInitializers.h"
-
-#include <vector>
-
-#include "compiler/translator/FindMain.h"
-#include "compiler/translator/InitializeVariables.h"
-#include "compiler/translator/IntermNode.h"
-#include "compiler/translator/IntermNode_util.h"
-#include "compiler/translator/ReplaceVariable.h"
-#include "compiler/translator/StaticType.h"
-#include "compiler/translator/SymbolTable.h"
-
-namespace sh
-{
-
-namespace
-{
-
-constexpr const ImmutableString kInitGlobalsString("initGlobals");
-
-void GetDeferredInitializers(TIntermDeclaration *declaration,
-                             bool initializeUninitializedGlobals,
-                             bool canUseLoopsToInitialize,
-                             bool highPrecisionSupported,
-                             TIntermSequence *deferredInitializersOut,
-                             std::vector<const TVariable *> *variablesToReplaceOut,
-                             TSymbolTable *symbolTable)
-{
-    // SeparateDeclarations should have already been run.
-    ASSERT(declaration->getSequence()->size() == 1);
-
-    TIntermNode *declarator = declaration->getSequence()->back();
-    TIntermBinary *init     = declarator->getAsBinaryNode();
-    if (init)
-    {
-        TIntermSymbol *symbolNode = init->getLeft()->getAsSymbolNode();
-        ASSERT(symbolNode);
-        TIntermTyped *expression = init->getRight();
-
-        if (expression->getQualifier() != EvqConst || !expression->hasConstantValue())
-        {
-            // For variables which are not constant, defer their real initialization until
-            // after we initialize uniforms.
-            // Deferral is done also in any cases where the variable can not be converted to a
-            // constant union, since otherwise there's a chance that HLSL output will generate extra
-            // statements from the initializer expression.
-
-            // Change const global to a regular global if its initialization is deferred.
-            // This can happen if ANGLE has not been able to fold the constant expression used
-            // as an initializer.
-            ASSERT(symbolNode->getQualifier() == EvqConst ||
-                   symbolNode->getQualifier() == EvqGlobal);
-            if (symbolNode->getQualifier() == EvqConst)
-            {
-                variablesToReplaceOut->push_back(&symbolNode->variable());
-            }
-
-            TIntermBinary *deferredInit =
-                new TIntermBinary(EOpAssign, symbolNode->deepCopy(), init->getRight());
-            deferredInitializersOut->push_back(deferredInit);
-
-            // Remove the initializer from the global scope and just declare the global instead.
-            declaration->replaceChildNode(init, symbolNode);
-        }
-    }
-    else if (initializeUninitializedGlobals)
-    {
-        TIntermSymbol *symbolNode = declarator->getAsSymbolNode();
-        ASSERT(symbolNode);
-
-        // Ignore ANGLE internal variables and nameless declarations.
-        if (symbolNode->variable().symbolType() == SymbolType::AngleInternal ||
-            symbolNode->variable().symbolType() == SymbolType::Empty)
-            return;
-
-        if (symbolNode->getQualifier() == EvqGlobal)
-        {
-            TIntermSequence *initCode = CreateInitCode(symbolNode, canUseLoopsToInitialize,
-                                                       highPrecisionSupported, symbolTable);
-            deferredInitializersOut->insert(deferredInitializersOut->end(), initCode->begin(),
-                                            initCode->end());
-        }
-    }
-}
-
-void InsertInitCallToMain(TIntermBlock *root,
-                          TIntermSequence *deferredInitializers,
-                          TSymbolTable *symbolTable)
-{
-    TIntermBlock *initGlobalsBlock = new TIntermBlock();
-    initGlobalsBlock->getSequence()->swap(*deferredInitializers);
-
-    TFunction *initGlobalsFunction =
-        new TFunction(symbolTable, kInitGlobalsString, SymbolType::AngleInternal,
-                      StaticType::GetBasic<EbtVoid>(), false);
-
-    TIntermFunctionPrototype *initGlobalsFunctionPrototype =
-        CreateInternalFunctionPrototypeNode(*initGlobalsFunction);
-    root->getSequence()->insert(root->getSequence()->begin(), initGlobalsFunctionPrototype);
-    TIntermFunctionDefinition *initGlobalsFunctionDefinition =
-        CreateInternalFunctionDefinitionNode(*initGlobalsFunction, initGlobalsBlock);
-    root->appendStatement(initGlobalsFunctionDefinition);
-
-    TIntermAggregate *initGlobalsCall =
-        TIntermAggregate::CreateFunctionCall(*initGlobalsFunction, new TIntermSequence());
-
-    TIntermBlock *mainBody = FindMainBody(root);
-    mainBody->getSequence()->insert(mainBody->getSequence()->begin(), initGlobalsCall);
-}
-
-}  // namespace
-
-void DeferGlobalInitializers(TIntermBlock *root,
-                             bool initializeUninitializedGlobals,
-                             bool canUseLoopsToInitialize,
-                             bool highPrecisionSupported,
-                             TSymbolTable *symbolTable)
-{
-    TIntermSequence *deferredInitializers = new TIntermSequence();
-    std::vector<const TVariable *> variablesToReplace;
-
-    // Loop over all global statements and process the declarations. This is simpler than using a
-    // traverser.
-    for (TIntermNode *statement : *root->getSequence())
-    {
-        TIntermDeclaration *declaration = statement->getAsDeclarationNode();
-        if (declaration)
-        {
-            GetDeferredInitializers(declaration, initializeUninitializedGlobals,
-                                    canUseLoopsToInitialize, highPrecisionSupported,
-                                    deferredInitializers, &variablesToReplace, symbolTable);
-        }
-    }
-
-    // Add the function with initialization and the call to that.
-    if (!deferredInitializers->empty())
-    {
-        InsertInitCallToMain(root, deferredInitializers, symbolTable);
-    }
-
-    // Replace constant variables with non-constant global variables.
-    for (const TVariable *var : variablesToReplace)
-    {
-        TType *replacementType = new TType(var->getType());
-        replacementType->setQualifier(EvqGlobal);
-        TVariable *replacement =
-            new TVariable(symbolTable, var->name(), replacementType, var->symbolType());
-        ReplaceVariable(root, var, replacement);
-    }
-}
-
-}  // namespace sh
deleted file mode 100644
--- a/gfx/angle/checkout/src/compiler/translator/DeferGlobalInitializers.h
+++ /dev/null
@@ -1,33 +0,0 @@
-//
-// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// DeferGlobalInitializers is an AST traverser that moves global initializers into a separate
-// function that is called in the beginning of main(). This enables initialization of globals with
-// uniforms or non-constant globals, as allowed by the WebGL spec. Some initializers referencing
-// non-constants may need to be unfolded into if statements in HLSL - this kind of steps should be
-// done after DeferGlobalInitializers is run. Note that it's important that the function definition
-// is at the end of the shader, as some globals may be declared after main().
-//
-// It can also initialize all uninitialized globals.
-//
-
-#ifndef COMPILER_TRANSLATOR_DEFERGLOBALINITIALIZERS_H_
-#define COMPILER_TRANSLATOR_DEFERGLOBALINITIALIZERS_H_
-
-namespace sh
-{
-
-class TIntermBlock;
-class TSymbolTable;
-
-void DeferGlobalInitializers(TIntermBlock *root,
-                             bool initializeUninitializedGlobals,
-                             bool canUseLoopsToInitialize,
-                             bool highPrecisionSupported,
-                             TSymbolTable *symbolTable);
-
-}  // namespace sh
-
-#endif  // COMPILER_TRANSLATOR_DEFERGLOBALINITIALIZERS_H_
deleted file mode 100644
--- a/gfx/angle/checkout/src/compiler/translator/EmulateGLFragColorBroadcast.cpp
+++ /dev/null
@@ -1,132 +0,0 @@
-//
-// Copyright (c) 2002-2016 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// gl_FragColor needs to broadcast to all color buffers in ES2 if
-// GL_EXT_draw_buffers is explicitly enabled in a fragment shader.
-//
-// We emulate this by replacing all gl_FragColor with gl_FragData[0], and in the end
-// of main() function, assigning gl_FragData[1], ..., gl_FragData[maxDrawBuffers-1]
-// with gl_FragData[0].
-//
-
-#include "compiler/translator/EmulateGLFragColorBroadcast.h"
-
-#include "compiler/translator/IntermNode_util.h"
-#include "compiler/translator/IntermTraverse.h"
-#include "compiler/translator/RunAtTheEndOfShader.h"
-#include "compiler/translator/Symbol.h"
-
-namespace sh
-{
-
-namespace
-{
-
-constexpr const ImmutableString kGlFragDataString("gl_FragData");
-
-class GLFragColorBroadcastTraverser : public TIntermTraverser
-{
-  public:
-    GLFragColorBroadcastTraverser(int maxDrawBuffers, TSymbolTable *symbolTable, int shaderVersion)
-        : TIntermTraverser(true, false, false, symbolTable),
-          mGLFragColorUsed(false),
-          mMaxDrawBuffers(maxDrawBuffers),
-          mShaderVersion(shaderVersion)
-    {
-    }
-
-    void broadcastGLFragColor(TIntermBlock *root);
-
-    bool isGLFragColorUsed() const { return mGLFragColorUsed; }
-
-  protected:
-    void visitSymbol(TIntermSymbol *node) override;
-
-    TIntermBinary *constructGLFragDataNode(int index) const;
-    TIntermBinary *constructGLFragDataAssignNode(int index) const;
-
-  private:
-    bool mGLFragColorUsed;
-    int mMaxDrawBuffers;
-    const int mShaderVersion;
-};
-
-TIntermBinary *GLFragColorBroadcastTraverser::constructGLFragDataNode(int index) const
-{
-    TIntermSymbol *symbol =
-        ReferenceBuiltInVariable(kGlFragDataString, *mSymbolTable, mShaderVersion);
-    TIntermTyped *indexNode = CreateIndexNode(index);
-
-    TIntermBinary *binary = new TIntermBinary(EOpIndexDirect, symbol, indexNode);
-    return binary;
-}
-
-TIntermBinary *GLFragColorBroadcastTraverser::constructGLFragDataAssignNode(int index) const
-{
-    TIntermTyped *fragDataIndex = constructGLFragDataNode(index);
-    TIntermTyped *fragDataZero  = constructGLFragDataNode(0);
-
-    return new TIntermBinary(EOpAssign, fragDataIndex, fragDataZero);
-}
-
-void GLFragColorBroadcastTraverser::visitSymbol(TIntermSymbol *node)
-{
-    if (node->variable().symbolType() == SymbolType::BuiltIn && node->getName() == "gl_FragColor")
-    {
-        queueReplacement(constructGLFragDataNode(0), OriginalNode::IS_DROPPED);
-        mGLFragColorUsed = true;
-    }
-}
-
-void GLFragColorBroadcastTraverser::broadcastGLFragColor(TIntermBlock *root)
-{
-    ASSERT(mMaxDrawBuffers > 1);
-    if (!mGLFragColorUsed)
-    {
-        return;
-    }
-
-    TIntermBlock *broadcastBlock = new TIntermBlock();
-    // Now insert statements
-    //   gl_FragData[1] = gl_FragData[0];
-    //   ...
-    //   gl_FragData[maxDrawBuffers - 1] = gl_FragData[0];
-    for (int colorIndex = 1; colorIndex < mMaxDrawBuffers; ++colorIndex)
-    {
-        broadcastBlock->appendStatement(constructGLFragDataAssignNode(colorIndex));
-    }
-    RunAtTheEndOfShader(root, broadcastBlock, mSymbolTable);
-}
-
-}  // namespace anonymous
-
-void EmulateGLFragColorBroadcast(TIntermBlock *root,
-                                 int maxDrawBuffers,
-                                 std::vector<sh::OutputVariable> *outputVariables,
-                                 TSymbolTable *symbolTable,
-                                 int shaderVersion)
-{
-    ASSERT(maxDrawBuffers > 1);
-    GLFragColorBroadcastTraverser traverser(maxDrawBuffers, symbolTable, shaderVersion);
-    root->traverse(&traverser);
-    if (traverser.isGLFragColorUsed())
-    {
-        traverser.updateTree();
-        traverser.broadcastGLFragColor(root);
-        for (auto &var : *outputVariables)
-        {
-            if (var.name == "gl_FragColor")
-            {
-                // TODO(zmo): Find a way to keep the original variable information.
-                var.name       = "gl_FragData";
-                var.mappedName = "gl_FragData";
-                var.arraySizes.push_back(maxDrawBuffers);
-                ASSERT(var.arraySizes.size() == 1u);
-            }
-        }
-    }
-}
-
-}  // namespace sh
deleted file mode 100644
--- a/gfx/angle/checkout/src/compiler/translator/EmulateGLFragColorBroadcast.h
+++ /dev/null
@@ -1,31 +0,0 @@
-//
-// Copyright (c) 2002-2016 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// Emulate gl_FragColor broadcast behaviors in ES2 where
-// GL_EXT_draw_buffers is explicitly enabled in a fragment shader.
-//
-
-#ifndef COMPILER_TRANSLATOR_EMULATEGLFRAGCOLORBROADCAST_H_
-#define COMPILER_TRANSLATOR_EMULATEGLFRAGCOLORBROADCAST_H_
-
-#include <vector>
-
-namespace sh
-{
-struct OutputVariable;
-class TIntermBlock;
-class TSymbolTable;
-
-// Replace all gl_FragColor with gl_FragData[0], and in the end of main() function,
-// assign gl_FragData[1] ... gl_FragData[maxDrawBuffers - 1] with gl_FragData[0].
-// If gl_FragColor is in outputVariables, it is replaced by gl_FragData.
-void EmulateGLFragColorBroadcast(TIntermBlock *root,
-                                 int maxDrawBuffers,
-                                 std::vector<OutputVariable> *outputVariables,
-                                 TSymbolTable *symbolTable,
-                                 int shaderVersion);
-}
-
-#endif  // COMPILER_TRANSLATOR_EMULATEGLFRAGCOLORBROADCAST_H_
deleted file mode 100644
--- a/gfx/angle/checkout/src/compiler/translator/EmulatePrecision.cpp
+++ /dev/null
@@ -1,779 +0,0 @@
-//
-// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "compiler/translator/EmulatePrecision.h"
-
-#include "compiler/translator/FunctionLookup.h"
-
-#include <memory>
-
-namespace sh
-{
-
-namespace
-{
-
-constexpr const ImmutableString kParamXName("x");
-constexpr const ImmutableString kParamYName("y");
-constexpr const ImmutableString kAngleFrmString("angle_frm");
-constexpr const ImmutableString kAngleFrlString("angle_frl");
-
-class RoundingHelperWriter : angle::NonCopyable
-{
-  public:
-    static RoundingHelperWriter *createHelperWriter(const ShShaderOutput outputLanguage);
-
-    void writeCommonRoundingHelpers(TInfoSinkBase &sink, const int shaderVersion);
-    void writeCompoundAssignmentHelper(TInfoSinkBase &sink,
-                                       const char *lType,
-                                       const char *rType,
-                                       const char *opStr,
-                                       const char *opNameStr);
-
-    virtual ~RoundingHelperWriter() {}
-
-  protected:
-    RoundingHelperWriter(const ShShaderOutput outputLanguage) : mOutputLanguage(outputLanguage) {}
-    RoundingHelperWriter() = delete;
-
-    const ShShaderOutput mOutputLanguage;
-
-  private:
-    virtual std::string getTypeString(const char *glslType)     = 0;
-    virtual void writeFloatRoundingHelpers(TInfoSinkBase &sink) = 0;
-    virtual void writeVectorRoundingHelpers(TInfoSinkBase &sink, const unsigned int size) = 0;
-    virtual void writeMatrixRoundingHelper(TInfoSinkBase &sink,
-                                           const unsigned int columns,
-                                           const unsigned int rows,
-                                           const char *functionName) = 0;
-};
-
-class RoundingHelperWriterGLSL : public RoundingHelperWriter
-{
-  public:
-    RoundingHelperWriterGLSL(const ShShaderOutput outputLanguage)
-        : RoundingHelperWriter(outputLanguage)
-    {
-    }
-
-  private:
-    std::string getTypeString(const char *glslType) override;
-    void writeFloatRoundingHelpers(TInfoSinkBase &sink) override;
-    void writeVectorRoundingHelpers(TInfoSinkBase &sink, const unsigned int size) override;
-    void writeMatrixRoundingHelper(TInfoSinkBase &sink,
-                                   const unsigned int columns,
-                                   const unsigned int rows,
-                                   const char *functionName) override;
-};
-
-class RoundingHelperWriterESSL : public RoundingHelperWriterGLSL
-{
-  public:
-    RoundingHelperWriterESSL(const ShShaderOutput outputLanguage)
-        : RoundingHelperWriterGLSL(outputLanguage)
-    {
-    }
-
-  private:
-    std::string getTypeString(const char *glslType) override;
-};
-
-class RoundingHelperWriterHLSL : public RoundingHelperWriter
-{
-  public:
-    RoundingHelperWriterHLSL(const ShShaderOutput outputLanguage)
-        : RoundingHelperWriter(outputLanguage)
-    {
-    }
-
-  private:
-    std::string getTypeString(const char *glslType) override;
-    void writeFloatRoundingHelpers(TInfoSinkBase &sink) override;
-    void writeVectorRoundingHelpers(TInfoSinkBase &sink, const unsigned int size) override;
-    void writeMatrixRoundingHelper(TInfoSinkBase &sink,
-                                   const unsigned int columns,
-                                   const unsigned int rows,
-                                   const char *functionName) override;
-};
-
-RoundingHelperWriter *RoundingHelperWriter::createHelperWriter(const ShShaderOutput outputLanguage)
-{
-    ASSERT(EmulatePrecision::SupportedInLanguage(outputLanguage));
-    switch (outputLanguage)
-    {
-        case SH_HLSL_4_1_OUTPUT:
-            return new RoundingHelperWriterHLSL(outputLanguage);
-        case SH_ESSL_OUTPUT:
-            return new RoundingHelperWriterESSL(outputLanguage);
-        default:
-            return new RoundingHelperWriterGLSL(outputLanguage);
-    }
-}
-
-void RoundingHelperWriter::writeCommonRoundingHelpers(TInfoSinkBase &sink, const int shaderVersion)
-{
-    // Write the angle_frm functions that round floating point numbers to
-    // half precision, and angle_frl functions that round them to minimum lowp
-    // precision.
-
-    writeFloatRoundingHelpers(sink);
-    writeVectorRoundingHelpers(sink, 2);
-    writeVectorRoundingHelpers(sink, 3);
-    writeVectorRoundingHelpers(sink, 4);
-    if (shaderVersion > 100)
-    {
-        for (unsigned int columns = 2; columns <= 4; ++columns)
-        {
-            for (unsigned int rows = 2; rows <= 4; ++rows)
-            {
-                writeMatrixRoundingHelper(sink, columns, rows, "angle_frm");
-                writeMatrixRoundingHelper(sink, columns, rows, "angle_frl");
-            }
-        }
-    }
-    else
-    {
-        for (unsigned int size = 2; size <= 4; ++size)
-        {
-            writeMatrixRoundingHelper(sink, size, size, "angle_frm");
-            writeMatrixRoundingHelper(sink, size, size, "angle_frl");
-        }
-    }
-}
-
-void RoundingHelperWriter::writeCompoundAssignmentHelper(TInfoSinkBase &sink,
-                                                         const char *lType,
-                                                         const char *rType,
-                                                         const char *opStr,
-                                                         const char *opNameStr)
-{
-    std::string lTypeStr = getTypeString(lType);
-    std::string rTypeStr = getTypeString(rType);
-
-    // Note that y should be passed through angle_frm at the function call site,
-    // but x can't be passed through angle_frm there since it is an inout parameter.
-    // So only pass x and the result through angle_frm here.
-    // clang-format off
-    sink <<
-        lTypeStr << " angle_compound_" << opNameStr << "_frm(inout " << lTypeStr << " x, in " << rTypeStr << " y) {\n"
-        "    x = angle_frm(angle_frm(x) " << opStr << " y);\n"
-        "    return x;\n"
-        "}\n";
-    sink <<
-        lTypeStr << " angle_compound_" << opNameStr << "_frl(inout " << lTypeStr << " x, in " << rTypeStr << " y) {\n"
-        "    x = angle_frl(angle_frl(x) " << opStr << " y);\n"
-        "    return x;\n"
-        "}\n";
-    // clang-format on
-}
-
-std::string RoundingHelperWriterGLSL::getTypeString(const char *glslType)
-{
-    return glslType;
-}
-
-std::string RoundingHelperWriterESSL::getTypeString(const char *glslType)
-{
-    std::stringstream typeStrStr;
-    typeStrStr << "highp " << glslType;
-    return typeStrStr.str();
-}
-
-void RoundingHelperWriterGLSL::writeFloatRoundingHelpers(TInfoSinkBase &sink)
-{
-    // Unoptimized version of angle_frm for single floats:
-    //
-    // int webgl_maxNormalExponent(in int exponentBits)
-    // {
-    //     int possibleExponents = int(exp2(float(exponentBits)));
-    //     int exponentBias = possibleExponents / 2 - 1;
-    //     int allExponentBitsOne = possibleExponents - 1;
-    //     return (allExponentBitsOne - 1) - exponentBias;
-    // }
-    //
-    // float angle_frm(in float x)
-    // {
-    //     int mantissaBits = 10;
-    //     int exponentBits = 5;
-    //     float possibleMantissas = exp2(float(mantissaBits));
-    //     float mantissaMax = 2.0 - 1.0 / possibleMantissas;
-    //     int maxNE = webgl_maxNormalExponent(exponentBits);
-    //     float max = exp2(float(maxNE)) * mantissaMax;
-    //     if (x > max)
-    //     {
-    //         return max;
-    //     }
-    //     if (x < -max)
-    //     {
-    //         return -max;
-    //     }
-    //     float exponent = floor(log2(abs(x)));
-    //     if (abs(x) == 0.0 || exponent < -float(maxNE))
-    //     {
-    //         return 0.0 * sign(x)
-    //     }
-    //     x = x * exp2(-(exponent - float(mantissaBits)));
-    //     x = sign(x) * floor(abs(x));
-    //     return x * exp2(exponent - float(mantissaBits));
-    // }
-
-    // All numbers with a magnitude less than 2^-15 are subnormal, and are
-    // flushed to zero.
-
-    // Note the constant numbers below:
-    // a) 65504 is the maximum possible mantissa (1.1111111111 in binary) times
-    //    2^15, the maximum normal exponent.
-    // b) 10.0 is the number of mantissa bits.
-    // c) -25.0 is the minimum normal half-float exponent -15.0 minus the number
-    //    of mantissa bits.
-    // d) + 1e-30 is to make sure the argument of log2() won't be zero. It can
-    //    only affect the result of log2 on x where abs(x) < 1e-22. Since these
-    //    numbers will be flushed to zero either way (2^-15 is the smallest
-    //    normal positive number), this does not introduce any error.
-
-    std::string floatType = getTypeString("float");
-
-    // clang-format off
-    sink <<
-        floatType << " angle_frm(in " << floatType << " x) {\n"
-        "    x = clamp(x, -65504.0, 65504.0);\n"
-        "    " << floatType << " exponent = floor(log2(abs(x) + 1e-30)) - 10.0;\n"
-        "    bool isNonZero = (exponent >= -25.0);\n"
-        "    x = x * exp2(-exponent);\n"
-        "    x = sign(x) * floor(abs(x));\n"
-        "    return x * exp2(exponent) * float(isNonZero);\n"
-        "}\n";
-
-    sink <<
-        floatType << " angle_frl(in " << floatType << " x) {\n"
-        "    x = clamp(x, -2.0, 2.0);\n"
-        "    x = x * 256.0;\n"
-        "    x = sign(x) * floor(abs(x));\n"
-        "    return x * 0.00390625;\n"
-        "}\n";
-    // clang-format on
-}
-
-void RoundingHelperWriterGLSL::writeVectorRoundingHelpers(TInfoSinkBase &sink,
-                                                          const unsigned int size)
-{
-    std::stringstream vecTypeStrStr;
-    vecTypeStrStr << "vec" << size;
-    std::string vecType = getTypeString(vecTypeStrStr.str().c_str());
-
-    // clang-format off
-    sink <<
-        vecType << " angle_frm(in " << vecType << " v) {\n"
-        "    v = clamp(v, -65504.0, 65504.0);\n"
-        "    " << vecType << " exponent = floor(log2(abs(v) + 1e-30)) - 10.0;\n"
-        "    bvec" << size << " isNonZero = greaterThanEqual(exponent, vec" << size << "(-25.0));\n"
-        "    v = v * exp2(-exponent);\n"
-        "    v = sign(v) * floor(abs(v));\n"
-        "    return v * exp2(exponent) * vec" << size << "(isNonZero);\n"
-        "}\n";
-
-    sink <<
-        vecType << " angle_frl(in " << vecType << " v) {\n"
-        "    v = clamp(v, -2.0, 2.0);\n"
-        "    v = v * 256.0;\n"
-        "    v = sign(v) * floor(abs(v));\n"
-        "    return v * 0.00390625;\n"
-        "}\n";
-    // clang-format on
-}
-
-void RoundingHelperWriterGLSL::writeMatrixRoundingHelper(TInfoSinkBase &sink,
-                                                         const unsigned int columns,
-                                                         const unsigned int rows,
-                                                         const char *functionName)
-{
-    std::stringstream matTypeStrStr;
-    matTypeStrStr << "mat" << columns;
-    if (rows != columns)
-    {
-        matTypeStrStr << "x" << rows;
-    }
-    std::string matType = getTypeString(matTypeStrStr.str().c_str());
-
-    sink << matType << " " << functionName << "(in " << matType << " m) {\n"
-         << "    " << matType << " rounded;\n";
-
-    for (unsigned int i = 0; i < columns; ++i)
-    {
-        sink << "    rounded[" << i << "] = " << functionName << "(m[" << i << "]);\n";
-    }
-
-    sink << "    return rounded;\n"
-            "}\n";
-}
-
-static const char *GetHLSLTypeStr(const char *floatTypeStr)
-{
-    if (strcmp(floatTypeStr, "float") == 0)
-    {
-        return "float";
-    }
-    if (strcmp(floatTypeStr, "vec2") == 0)
-    {
-        return "float2";
-    }
-    if (strcmp(floatTypeStr, "vec3") == 0)
-    {
-        return "float3";
-    }
-    if (strcmp(floatTypeStr, "vec4") == 0)
-    {
-        return "float4";
-    }
-    if (strcmp(floatTypeStr, "mat2") == 0)
-    {
-        return "float2x2";
-    }
-    if (strcmp(floatTypeStr, "mat3") == 0)
-    {
-        return "float3x3";
-    }
-    if (strcmp(floatTypeStr, "mat4") == 0)
-    {
-        return "float4x4";
-    }
-    if (strcmp(floatTypeStr, "mat2x3") == 0)
-    {
-        return "float2x3";
-    }
-    if (strcmp(floatTypeStr, "mat2x4") == 0)
-    {
-        return "float2x4";
-    }
-    if (strcmp(floatTypeStr, "mat3x2") == 0)
-    {
-        return "float3x2";
-    }
-    if (strcmp(floatTypeStr, "mat3x4") == 0)
-    {
-        return "float3x4";
-    }
-    if (strcmp(floatTypeStr, "mat4x2") == 0)
-    {
-        return "float4x2";
-    }
-    if (strcmp(floatTypeStr, "mat4x3") == 0)
-    {
-        return "float4x3";
-    }
-    UNREACHABLE();
-    return nullptr;
-}
-
-std::string RoundingHelperWriterHLSL::getTypeString(const char *glslType)
-{
-    return GetHLSLTypeStr(glslType);
-}
-
-void RoundingHelperWriterHLSL::writeFloatRoundingHelpers(TInfoSinkBase &sink)
-{
-    // In HLSL scalars are the same as 1-vectors.
-    writeVectorRoundingHelpers(sink, 1);
-}
-
-void RoundingHelperWriterHLSL::writeVectorRoundingHelpers(TInfoSinkBase &sink,
-                                                          const unsigned int size)
-{
-    std::stringstream vecTypeStrStr;
-    vecTypeStrStr << "float" << size;
-    std::string vecType = vecTypeStrStr.str();
-
-    // clang-format off
-    sink <<
-        vecType << " angle_frm(" << vecType << " v) {\n"
-        "    v = clamp(v, -65504.0, 65504.0);\n"
-        "    " << vecType << " exponent = floor(log2(abs(v) + 1e-30)) - 10.0;\n"
-        "    bool" << size << " isNonZero = exponent < -25.0;\n"
-        "    v = v * exp2(-exponent);\n"
-        "    v = sign(v) * floor(abs(v));\n"
-        "    return v * exp2(exponent) * (float" << size << ")(isNonZero);\n"
-        "}\n";
-
-    sink <<
-        vecType << " angle_frl(" << vecType << " v) {\n"
-        "    v = clamp(v, -2.0, 2.0);\n"
-        "    v = v * 256.0;\n"
-        "    v = sign(v) * floor(abs(v));\n"
-        "    return v * 0.00390625;\n"
-        "}\n";
-    // clang-format on
-}
-
-void RoundingHelperWriterHLSL::writeMatrixRoundingHelper(TInfoSinkBase &sink,
-                                                         const unsigned int columns,
-                                                         const unsigned int rows,
-                                                         const char *functionName)
-{
-    std::stringstream matTypeStrStr;
-    matTypeStrStr << "float" << columns << "x" << rows;
-    std::string matType = matTypeStrStr.str();
-
-    sink << matType << " " << functionName << "(" << matType << " m) {\n"
-         << "    " << matType << " rounded;\n";
-
-    for (unsigned int i = 0; i < columns; ++i)
-    {
-        sink << "    rounded[" << i << "] = " << functionName << "(m[" << i << "]);\n";
-    }
-
-    sink << "    return rounded;\n"
-            "}\n";
-}
-
-bool canRoundFloat(const TType &type)
-{
-    return type.getBasicType() == EbtFloat && !type.isArray() &&
-           (type.getPrecision() == EbpLow || type.getPrecision() == EbpMedium);
-}
-
-bool ParentUsesResult(TIntermNode *parent, TIntermTyped *node)
-{
-    if (!parent)
-    {
-        return false;
-    }
-
-    TIntermBlock *blockParent = parent->getAsBlock();
-    // If the parent is a block, the result is not assigned anywhere,
-    // so rounding it is not needed. In particular, this can avoid a lot of
-    // unnecessary rounding of unused return values of assignment.
-    if (blockParent)
-    {
-        return false;
-    }
-    TIntermBinary *binaryParent = parent->getAsBinaryNode();
-    if (binaryParent && binaryParent->getOp() == EOpComma && (binaryParent->getRight() != node))
-    {
-        return false;
-    }
-    return true;
-}
-
-bool ParentConstructorTakesCareOfRounding(TIntermNode *parent, TIntermTyped *node)
-{
-    if (!parent)
-    {
-        return false;
-    }
-    TIntermAggregate *parentConstructor = parent->getAsAggregate();
-    if (!parentConstructor || parentConstructor->getOp() != EOpConstruct)
-    {
-        return false;
-    }
-    if (parentConstructor->getPrecision() != node->getPrecision())
-    {
-        return false;
-    }
-    return canRoundFloat(parentConstructor->getType());
-}
-
-}  // namespace anonymous
-
-EmulatePrecision::EmulatePrecision(TSymbolTable *symbolTable)
-    : TLValueTrackingTraverser(true, true, true, symbolTable), mDeclaringVariables(false)
-{
-}
-
-void EmulatePrecision::visitSymbol(TIntermSymbol *node)
-{
-    TIntermNode *parent = getParentNode();
-    if (canRoundFloat(node->getType()) && ParentUsesResult(parent, node) &&
-        !ParentConstructorTakesCareOfRounding(parent, node) && !mDeclaringVariables &&
-        !isLValueRequiredHere())
-    {
-        TIntermNode *replacement = createRoundingFunctionCallNode(node);
-        queueReplacement(replacement, OriginalNode::BECOMES_CHILD);
-    }
-}
-
-bool EmulatePrecision::visitBinary(Visit visit, TIntermBinary *node)
-{
-    bool visitChildren = true;
-
-    TOperator op = node->getOp();
-
-    // RHS of initialize is not being declared.
-    if (op == EOpInitialize && visit == InVisit)
-        mDeclaringVariables = false;
-
-    if ((op == EOpIndexDirectStruct) && visit == InVisit)
-        visitChildren = false;
-
-    if (visit != PreVisit)
-        return visitChildren;
-
-    const TType &type = node->getType();
-    bool roundFloat   = canRoundFloat(type);
-
-    if (roundFloat)
-    {
-        switch (op)
-        {
-            // Math operators that can result in a float may need to apply rounding to the return
-            // value. Note that in the case of assignment, the rounding is applied to its return
-            // value here, not the value being assigned.
-            case EOpAssign:
-            case EOpAdd:
-            case EOpSub:
-            case EOpMul:
-            case EOpDiv:
-            case EOpVectorTimesScalar:
-            case EOpVectorTimesMatrix:
-            case EOpMatrixTimesVector:
-            case EOpMatrixTimesScalar:
-            case EOpMatrixTimesMatrix:
-            {
-                TIntermNode *parent = getParentNode();
-                if (!ParentUsesResult(parent, node) ||
-                    ParentConstructorTakesCareOfRounding(parent, node))
-                {
-                    break;
-                }
-                TIntermNode *replacement = createRoundingFunctionCallNode(node);
-                queueReplacement(replacement, OriginalNode::BECOMES_CHILD);
-                break;
-            }
-
-            // Compound assignment cases need to replace the operator with a function call.
-            case EOpAddAssign:
-            {
-                mEmulateCompoundAdd.insert(
-                    TypePair(type.getBuiltInTypeNameString(),
-                             node->getRight()->getType().getBuiltInTypeNameString()));
-                TIntermNode *replacement = createCompoundAssignmentFunctionCallNode(
-                    node->getLeft(), node->getRight(), "add");
-                queueReplacement(replacement, OriginalNode::IS_DROPPED);
-                break;
-            }
-            case EOpSubAssign:
-            {
-                mEmulateCompoundSub.insert(
-                    TypePair(type.getBuiltInTypeNameString(),
-                             node->getRight()->getType().getBuiltInTypeNameString()));
-                TIntermNode *replacement = createCompoundAssignmentFunctionCallNode(
-                    node->getLeft(), node->getRight(), "sub");
-                queueReplacement(replacement, OriginalNode::IS_DROPPED);
-                break;
-            }
-            case EOpMulAssign:
-            case EOpVectorTimesMatrixAssign:
-            case EOpVectorTimesScalarAssign:
-            case EOpMatrixTimesScalarAssign:
-            case EOpMatrixTimesMatrixAssign:
-            {
-                mEmulateCompoundMul.insert(
-                    TypePair(type.getBuiltInTypeNameString(),
-                             node->getRight()->getType().getBuiltInTypeNameString()));
-                TIntermNode *replacement = createCompoundAssignmentFunctionCallNode(
-                    node->getLeft(), node->getRight(), "mul");
-                queueReplacement(replacement, OriginalNode::IS_DROPPED);
-                break;
-            }
-            case EOpDivAssign:
-            {
-                mEmulateCompoundDiv.insert(
-                    TypePair(type.getBuiltInTypeNameString(),
-                             node->getRight()->getType().getBuiltInTypeNameString()));
-                TIntermNode *replacement = createCompoundAssignmentFunctionCallNode(
-                    node->getLeft(), node->getRight(), "div");
-                queueReplacement(replacement, OriginalNode::IS_DROPPED);
-                break;
-            }
-            default:
-                // The rest of the binary operations should not need precision emulation.
-                break;
-        }
-    }
-    return visitChildren;
-}
-
-bool EmulatePrecision::visitDeclaration(Visit visit, TIntermDeclaration *node)
-{
-    // Variable or interface block declaration.
-    if (visit == PreVisit)
-    {
-        mDeclaringVariables = true;
-    }
-    else if (visit == InVisit)
-    {
-        mDeclaringVariables = true;
-    }
-    else
-    {
-        mDeclaringVariables = false;
-    }
-    return true;
-}
-
-bool EmulatePrecision::visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node)
-{
-    return false;
-}
-
-bool EmulatePrecision::visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node)
-{
-    return false;
-}
-
-bool EmulatePrecision::visitAggregate(Visit visit, TIntermAggregate *node)
-{
-    if (visit != PreVisit)
-        return true;
-
-    // User-defined function return values are not rounded. The calculations that produced
-    // the value inside the function definition should have been rounded.
-    TOperator op = node->getOp();
-    if (op == EOpCallInternalRawFunction || op == EOpCallFunctionInAST ||
-        (op == EOpConstruct && node->getBasicType() == EbtStruct))
-    {
-        return true;
-    }
-
-    TIntermNode *parent = getParentNode();
-    if (canRoundFloat(node->getType()) && ParentUsesResult(parent, node) &&
-        !ParentConstructorTakesCareOfRounding(parent, node))
-    {
-        TIntermNode *replacement = createRoundingFunctionCallNode(node);
-        queueReplacement(replacement, OriginalNode::BECOMES_CHILD);
-    }
-    return true;
-}
-
-bool EmulatePrecision::visitUnary(Visit visit, TIntermUnary *node)
-{
-    switch (node->getOp())
-    {
-        case EOpNegative:
-        case EOpLogicalNot:
-        case EOpPostIncrement:
-        case EOpPostDecrement:
-        case EOpPreIncrement:
-        case EOpPreDecrement:
-        case EOpLogicalNotComponentWise:
-            break;
-        default:
-            if (canRoundFloat(node->getType()) && visit == PreVisit)
-            {
-                TIntermNode *replacement = createRoundingFunctionCallNode(node);
-                queueReplacement(replacement, OriginalNode::BECOMES_CHILD);
-            }
-            break;
-    }
-
-    return true;
-}
-
-void EmulatePrecision::writeEmulationHelpers(TInfoSinkBase &sink,
-                                             const int shaderVersion,
-                                             const ShShaderOutput outputLanguage)
-{
-    std::unique_ptr<RoundingHelperWriter> roundingHelperWriter(
-        RoundingHelperWriter::createHelperWriter(outputLanguage));
-
-    roundingHelperWriter->writeCommonRoundingHelpers(sink, shaderVersion);
-
-    EmulationSet::const_iterator it;
-    for (it = mEmulateCompoundAdd.begin(); it != mEmulateCompoundAdd.end(); it++)
-        roundingHelperWriter->writeCompoundAssignmentHelper(sink, it->lType, it->rType, "+", "add");
-    for (it = mEmulateCompoundSub.begin(); it != mEmulateCompoundSub.end(); it++)
-        roundingHelperWriter->writeCompoundAssignmentHelper(sink, it->lType, it->rType, "-", "sub");
-    for (it = mEmulateCompoundDiv.begin(); it != mEmulateCompoundDiv.end(); it++)
-        roundingHelperWriter->writeCompoundAssignmentHelper(sink, it->lType, it->rType, "/", "div");
-    for (it = mEmulateCompoundMul.begin(); it != mEmulateCompoundMul.end(); it++)
-        roundingHelperWriter->writeCompoundAssignmentHelper(sink, it->lType, it->rType, "*", "mul");
-}
-
-// static
-bool EmulatePrecision::SupportedInLanguage(const ShShaderOutput outputLanguage)
-{
-    switch (outputLanguage)
-    {
-        case SH_HLSL_4_1_OUTPUT:
-        case SH_ESSL_OUTPUT:
-            return true;
-        default:
-            // Other languages not yet supported
-            return (outputLanguage == SH_GLSL_COMPATIBILITY_OUTPUT ||
-                    sh::IsGLSL130OrNewer(outputLanguage));
-    }
-}
-
-const TFunction *EmulatePrecision::getInternalFunction(const ImmutableString &functionName,
-                                                       const TType &returnType,
-                                                       TIntermSequence *arguments,
-                                                       const TVector<TConstParameter> &parameters,
-                                                       bool knownToNotHaveSideEffects)
-{
-    ImmutableString mangledName = TFunctionLookup::GetMangledName(functionName.data(), *arguments);
-    if (mInternalFunctions.find(mangledName) == mInternalFunctions.end())
-    {
-        TFunction *func = new TFunction(mSymbolTable, functionName, SymbolType::AngleInternal,
-                                        new TType(returnType), knownToNotHaveSideEffects);
-        ASSERT(parameters.size() == arguments->size());
-        for (size_t i = 0; i < parameters.size(); ++i)
-        {
-            func->addParameter(parameters[i]);
-        }
-        mInternalFunctions[mangledName] = func;
-    }
-    return mInternalFunctions[mangledName];
-}
-
-TIntermAggregate *EmulatePrecision::createRoundingFunctionCallNode(TIntermTyped *roundedChild)
-{
-    const ImmutableString *roundFunctionName = &kAngleFrmString;
-    if (roundedChild->getPrecision() == EbpLow)
-        roundFunctionName = &kAngleFrlString;
-    TIntermSequence *arguments = new TIntermSequence();
-    arguments->push_back(roundedChild);
-
-    TVector<TConstParameter> parameters;
-    TType *paramType = new TType(roundedChild->getType());
-    paramType->setPrecision(EbpHigh);
-    paramType->setQualifier(EvqIn);
-    parameters.push_back(TConstParameter(kParamXName, static_cast<const TType *>(paramType)));
-
-    return TIntermAggregate::CreateRawFunctionCall(
-        *getInternalFunction(*roundFunctionName, roundedChild->getType(), arguments, parameters,
-                             true),
-        arguments);
-}
-
-TIntermAggregate *EmulatePrecision::createCompoundAssignmentFunctionCallNode(TIntermTyped *left,
-                                                                             TIntermTyped *right,
-                                                                             const char *opNameStr)
-{
-    std::stringstream strstr;
-    if (left->getPrecision() == EbpMedium)
-        strstr << "angle_compound_" << opNameStr << "_frm";
-    else
-        strstr << "angle_compound_" << opNameStr << "_frl";
-    ImmutableString functionName = ImmutableString(strstr.str());
-    TIntermSequence *arguments = new TIntermSequence();
-    arguments->push_back(left);
-    arguments->push_back(right);
-
-    TVector<TConstParameter> parameters;
-    TType *leftParamType = new TType(left->getType());
-    leftParamType->setPrecision(EbpHigh);
-    leftParamType->setQualifier(EvqOut);
-    parameters.push_back(TConstParameter(kParamXName, static_cast<const TType *>(leftParamType)));
-    TType *rightParamType = new TType(right->getType());
-    rightParamType->setPrecision(EbpHigh);
-    rightParamType->setQualifier(EvqIn);
-    parameters.push_back(TConstParameter(kParamYName, static_cast<const TType *>(rightParamType)));
-
-    return TIntermAggregate::CreateRawFunctionCall(
-        *getInternalFunction(functionName, left->getType(), arguments, parameters, false),
-        arguments);
-}
-
-}  // namespace sh
deleted file mode 100644
--- a/gfx/angle/checkout/src/compiler/translator/EmulatePrecision.h
+++ /dev/null
@@ -1,86 +0,0 @@
-//
-// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#ifndef COMPILER_TRANSLATOR_EMULATE_PRECISION_H_
-#define COMPILER_TRANSLATOR_EMULATE_PRECISION_H_
-
-#include "GLSLANG/ShaderLang.h"
-#include "common/angleutils.h"
-#include "compiler/translator/Compiler.h"
-#include "compiler/translator/InfoSink.h"
-#include "compiler/translator/IntermTraverse.h"
-
-// This class gathers all compound assignments from the AST and can then write
-// the functions required for their precision emulation. This way there is no
-// need to write a huge number of variations of the emulated compound assignment
-// to every translated shader with emulation enabled.
-
-namespace sh
-{
-
-class EmulatePrecision : public TLValueTrackingTraverser
-{
-  public:
-    EmulatePrecision(TSymbolTable *symbolTable);
-
-    void visitSymbol(TIntermSymbol *node) override;
-    bool visitBinary(Visit visit, TIntermBinary *node) override;
-    bool visitUnary(Visit visit, TIntermUnary *node) override;
-    bool visitAggregate(Visit visit, TIntermAggregate *node) override;
-    bool visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node) override;
-    bool visitDeclaration(Visit visit, TIntermDeclaration *node) override;
-    bool visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node) override;
-
-    void writeEmulationHelpers(TInfoSinkBase &sink,
-                               const int shaderVersion,
-                               const ShShaderOutput outputLanguage);
-
-    static bool SupportedInLanguage(const ShShaderOutput outputLanguage);
-
-  private:
-    struct TypePair
-    {
-        TypePair(const char *l, const char *r) : lType(l), rType(r) {}
-
-        const char *lType;
-        const char *rType;
-    };
-
-    struct TypePairComparator
-    {
-        bool operator()(const TypePair &l, const TypePair &r) const
-        {
-            if (l.lType == r.lType)
-                return l.rType < r.rType;
-            return l.lType < r.lType;
-        }
-    };
-
-    const TFunction *getInternalFunction(const ImmutableString &functionName,
-                                         const TType &returnType,
-                                         TIntermSequence *arguments,
-                                         const TVector<TConstParameter> &parameters,
-                                         bool knownToNotHaveSideEffects);
-    TIntermAggregate *createRoundingFunctionCallNode(TIntermTyped *roundedChild);
-    TIntermAggregate *createCompoundAssignmentFunctionCallNode(TIntermTyped *left,
-                                                               TIntermTyped *right,
-                                                               const char *opNameStr);
-
-    typedef std::set<TypePair, TypePairComparator> EmulationSet;
-    EmulationSet mEmulateCompoundAdd;
-    EmulationSet mEmulateCompoundSub;
-    EmulationSet mEmulateCompoundMul;
-    EmulationSet mEmulateCompoundDiv;
-
-    // Map from mangled name to function.
-    TMap<ImmutableString, const TFunction *> mInternalFunctions;
-
-    bool mDeclaringVariables;
-};
-
-}  // namespace sh
-
-#endif  // COMPILER_TRANSLATOR_EMULATE_PRECISION_H_
deleted file mode 100644
--- a/gfx/angle/checkout/src/compiler/translator/ExpandIntegerPowExpressions.cpp
+++ /dev/null
@@ -1,147 +0,0 @@
-//
-// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// Implementation of the integer pow expressions HLSL bug workaround.
-// See header for more info.
-
-#include "compiler/translator/ExpandIntegerPowExpressions.h"
-
-#include <cmath>
-#include <cstdlib>
-
-#include "compiler/translator/IntermNode_util.h"
-#include "compiler/translator/IntermTraverse.h"
-
-namespace sh
-{
-
-namespace
-{
-
-class Traverser : public TIntermTraverser
-{
-  public:
-    static void Apply(TIntermNode *root, TSymbolTable *symbolTable);
-
-  private:
-    Traverser(TSymbolTable *symbolTable);
-    bool visitAggregate(Visit visit, TIntermAggregate *node) override;
-    void nextIteration();
-
-    bool mFound = false;
-};
-
-// static
-void Traverser::Apply(TIntermNode *root, TSymbolTable *symbolTable)
-{
-    Traverser traverser(symbolTable);
-    do
-    {
-        traverser.nextIteration();
-        root->traverse(&traverser);
-        if (traverser.mFound)
-        {
-            traverser.updateTree();
-        }
-    } while (traverser.mFound);
-}
-
-Traverser::Traverser(TSymbolTable *symbolTable) : TIntermTraverser(true, false, false, symbolTable)
-{
-}
-
-void Traverser::nextIteration()
-{
-    mFound = false;
-}
-
-bool Traverser::visitAggregate(Visit visit, TIntermAggregate *node)
-{
-    if (mFound)
-    {
-        return false;
-    }
-
-    // Test 0: skip non-pow operators.
-    if (node->getOp() != EOpPow)
-    {
-        return true;
-    }
-
-    const TIntermSequence *sequence = node->getSequence();
-    ASSERT(sequence->size() == 2u);
-    const TIntermConstantUnion *constantExponent = sequence->at(1)->getAsConstantUnion();
-
-    // Test 1: check for a single constant.
-    if (!constantExponent || constantExponent->getNominalSize() != 1)
-    {
-        return true;
-    }
-
-    ASSERT(constantExponent->getBasicType() == EbtFloat);
-    float exponentValue = constantExponent->getConstantValue()->getFConst();
-
-    // Test 2: exponentValue is in the problematic range.
-    if (exponentValue < -5.0f || exponentValue > 9.0f)
-    {
-        return true;
-    }
-
-    // Test 3: exponentValue is integer or pretty close to an integer.
-    if (std::abs(exponentValue - std::round(exponentValue)) > 0.0001f)
-    {
-        return true;
-    }
-
-    // Test 4: skip -1, 0, and 1
-    int exponent = static_cast<int>(std::round(exponentValue));
-    int n        = std::abs(exponent);
-    if (n < 2)
-    {
-        return true;
-    }
-
-    // Potential problem case detected, apply workaround.
-
-    TIntermTyped *lhs = sequence->at(0)->getAsTyped();
-    ASSERT(lhs);
-
-    TIntermDeclaration *lhsVariableDeclaration = nullptr;
-    TVariable *lhsVariable =
-        DeclareTempVariable(mSymbolTable, lhs, EvqTemporary, &lhsVariableDeclaration);
-    insertStatementInParentBlock(lhsVariableDeclaration);
-
-    // Create a chain of n-1 multiples.
-    TIntermTyped *current = CreateTempSymbolNode(lhsVariable);
-    for (int i = 1; i < n; ++i)
-    {
-        TIntermBinary *mul = new TIntermBinary(EOpMul, current, CreateTempSymbolNode(lhsVariable));
-        mul->setLine(node->getLine());
-        current = mul;
-    }
-
-    // For negative pow, compute the reciprocal of the positive pow.
-    if (exponent < 0)
-    {
-        TConstantUnion *oneVal = new TConstantUnion();
-        oneVal->setFConst(1.0f);
-        TIntermConstantUnion *oneNode = new TIntermConstantUnion(oneVal, node->getType());
-        TIntermBinary *div            = new TIntermBinary(EOpDiv, oneNode, current);
-        current                       = div;
-    }
-
-    queueReplacement(current, OriginalNode::IS_DROPPED);
-    mFound = true;
-    return false;
-}
-
-}  // anonymous namespace
-
-void ExpandIntegerPowExpressions(TIntermNode *root, TSymbolTable *symbolTable)
-{
-    Traverser::Apply(root, symbolTable);
-}
-
-}  // namespace sh
deleted file mode 100644
--- a/gfx/angle/checkout/src/compiler/translator/ExpandIntegerPowExpressions.h
+++ /dev/null
@@ -1,29 +0,0 @@
-//
-// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// This mutating tree traversal works around a bug in the HLSL compiler optimizer with "pow" that
-// manifests under the following conditions:
-//
-// - If pow() has a literal exponent value
-// - ... and this value is integer or within 10e-6 of an integer
-// - ... and it is in {-4, -3, -2, 2, 3, 4, 5, 6, 7, 8}
-//
-// The workaround is to replace the pow with a series of multiplies.
-// See http://anglebug.com/851
-
-#ifndef COMPILER_TRANSLATOR_EXPANDINTEGERPOWEXPRESSIONS_H_
-#define COMPILER_TRANSLATOR_EXPANDINTEGERPOWEXPRESSIONS_H_
-
-namespace sh
-{
-
-class TIntermNode;
-class TSymbolTable;
-
-void ExpandIntegerPowExpressions(TIntermNode *root, TSymbolTable *symbolTable);
-
-}  // namespace sh
-
-#endif  // COMPILER_TRANSLATOR_EXPANDINTEGERPOWEXPRESSIONS_H_
--- a/gfx/angle/checkout/src/compiler/translator/ExtensionGLSL.h
+++ b/gfx/angle/checkout/src/compiler/translator/ExtensionGLSL.h
@@ -7,17 +7,17 @@
 // shaders.
 
 #ifndef COMPILER_TRANSLATOR_EXTENSIONGLSL_H_
 #define COMPILER_TRANSLATOR_EXTENSIONGLSL_H_
 
 #include <set>
 #include <string>
 
-#include "compiler/translator/IntermTraverse.h"
+#include "compiler/translator/tree_util/IntermTraverse.h"
 
 namespace sh
 {
 
 // Traverses the intermediate tree to determine which GLSL extensions are required
 // to support the shader.
 class TExtensionGLSL : public TIntermTraverser
 {
deleted file mode 100644
--- a/gfx/angle/checkout/src/compiler/translator/FindMain.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-//
-// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// FindMain.cpp: Find the main() function definition in a given AST.
-
-#include "compiler/translator/FindMain.h"
-
-#include "compiler/translator/IntermNode.h"
-#include "compiler/translator/Symbol.h"
-
-namespace sh
-{
-
-TIntermFunctionDefinition *FindMain(TIntermBlock *root)
-{
-    for (TIntermNode *node : *root->getSequence())
-    {
-        TIntermFunctionDefinition *nodeFunction = node->getAsFunctionDefinition();
-        if (nodeFunction != nullptr && nodeFunction->getFunction()->isMain())
-        {
-            return nodeFunction;
-        }
-    }
-    return nullptr;
-}
-
-TIntermBlock *FindMainBody(TIntermBlock *root)
-{
-    TIntermFunctionDefinition *main = FindMain(root);
-    ASSERT(main != nullptr);
-    TIntermBlock *mainBody = main->getBody();
-    ASSERT(mainBody != nullptr);
-    return mainBody;
-}
-
-}  // namespace sh
deleted file mode 100644
--- a/gfx/angle/checkout/src/compiler/translator/FindMain.h
+++ /dev/null
@@ -1,23 +0,0 @@
-//
-// Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// FindMain.h: Adds functions to get the main function definition and its body.
-
-#ifndef COMPILER_TRANSLATOR_FINDMAIN_H_
-#define COMPILER_TRANSLATOR_FINDMAIN_H_
-
-namespace sh
-{
-
-class TIntermBlock;
-class TIntermFunctionDefinition;
-
-TIntermFunctionDefinition *FindMain(TIntermBlock *root);
-TIntermBlock *FindMainBody(TIntermBlock *root);
-
-}  // namespace sh
-
-#endif  // COMPILER_TRANSLATOR_FINDMAIN_H_
\ No newline at end of file
deleted file mode 100644
--- a/gfx/angle/checkout/src/compiler/translator/FindSymbolNode.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-//
-// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// FindSymbol.cpp:
-//     Utility for finding a symbol node inside an AST tree.
-
-#include "compiler/translator/FindSymbolNode.h"
-
-#include "compiler/translator/ImmutableString.h"
-#include "compiler/translator/IntermTraverse.h"
-#include "compiler/translator/Symbol.h"
-
-namespace sh
-{
-
-namespace
-{
-
-class SymbolFinder : public TIntermTraverser
-{
-  public:
-    SymbolFinder(const ImmutableString &symbolName)
-        : TIntermTraverser(true, false, false), mSymbolName(symbolName), mNodeFound(nullptr)
-    {
-    }
-
-    void visitSymbol(TIntermSymbol *node)
-    {
-        if (node->variable().symbolType() != SymbolType::Empty && node->getName() == mSymbolName)
-        {
-            mNodeFound = node;
-        }
-    }
-
-    bool isFound() const { return mNodeFound != nullptr; }
-    const TIntermSymbol *getNode() const { return mNodeFound; }
-
-  private:
-    ImmutableString mSymbolName;
-    TIntermSymbol *mNodeFound;
-};
-
-}  // anonymous namespace
-
-const TIntermSymbol *FindSymbolNode(TIntermNode *root, const ImmutableString &symbolName)
-{
-    SymbolFinder finder(symbolName);
-    root->traverse(&finder);
-    return finder.getNode();
-}
-
-}  // namespace sh
deleted file mode 100644
--- a/gfx/angle/checkout/src/compiler/translator/FindSymbolNode.h
+++ /dev/null
@@ -1,23 +0,0 @@
-//
-// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// FindSymbolNode.h:
-//     Utility for finding a symbol node inside an AST tree.
-
-#ifndef COMPILER_TRANSLATOR_FIND_SYMBOL_H_
-#define COMPILER_TRANSLATOR_FIND_SYMBOL_H_
-
-namespace sh
-{
-
-class ImmutableString;
-class TIntermNode;
-class TIntermSymbol;
-
-const TIntermSymbol *FindSymbolNode(TIntermNode *root, const ImmutableString &symbolName);
-
-}  // namespace sh
-
-#endif  // COMPILER_TRANSLATOR_FIND_SYMBOL_H_
\ No newline at end of file
--- a/gfx/angle/checkout/src/compiler/translator/FlagStd140Structs.cpp
+++ b/gfx/angle/checkout/src/compiler/translator/FlagStd140Structs.cpp
@@ -3,18 +3,18 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
 // FlagStd140Structs.cpp: Find structs in std140 blocks, where the padding added in the translator
 // conflicts with the "natural" unpadded type.
 
 #include "compiler/translator/FlagStd140Structs.h"
 
-#include "compiler/translator/IntermTraverse.h"
 #include "compiler/translator/SymbolTable.h"
+#include "compiler/translator/tree_util/IntermTraverse.h"
 
 namespace sh
 {
 
 namespace
 {
 
 class FlagStd140StructsTraverser : public TIntermTraverser
deleted file mode 100644
--- a/gfx/angle/checkout/src/compiler/translator/FoldExpressions.cpp
+++ /dev/null
@@ -1,116 +0,0 @@
-//
-// Copyright (c) 2018 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// FoldExpressions.cpp: Fold expressions. This may fold expressions so that the qualifier of the
-// folded node differs from the qualifier of the original expression, so it needs to be done after
-// parsing and validation of qualifiers is complete. Expressions that are folded:
-//  1. Ternary ops with a constant condition.
-//  2. Sequence aka comma ops where the left side has no side effects.
-//  3. Any expressions containing any of the above.
-
-#include "compiler/translator/FoldExpressions.h"
-
-#include "compiler/translator/Diagnostics.h"
-#include "compiler/translator/IntermNode.h"
-#include "compiler/translator/IntermTraverse.h"
-
-namespace sh
-{
-
-namespace
-{
-
-class FoldExpressionsTraverser : public TIntermTraverser
-{
-  public:
-    FoldExpressionsTraverser(TDiagnostics *diagnostics)
-        : TIntermTraverser(true, false, false), mDiagnostics(diagnostics), mDidReplace(false)
-    {
-    }
-
-    bool didReplace() { return mDidReplace; }
-
-    void nextIteration() { mDidReplace = false; }
-
-  protected:
-    bool visitTernary(Visit visit, TIntermTernary *node) override
-    {
-        TIntermTyped *folded = node->fold(mDiagnostics);
-        if (folded != node)
-        {
-            queueReplacement(folded, OriginalNode::IS_DROPPED);
-            mDidReplace = true;
-            return false;
-        }
-        return true;
-    }
-
-    bool visitAggregate(Visit visit, TIntermAggregate *node) override
-    {
-        TIntermTyped *folded = node->fold(mDiagnostics);
-        if (folded != node)
-        {
-            queueReplacement(folded, OriginalNode::IS_DROPPED);
-            mDidReplace = true;
-            return false;
-        }
-        return true;
-    }
-
-    bool visitBinary(Visit visit, TIntermBinary *node) override
-    {
-        TIntermTyped *folded = node->fold(mDiagnostics);
-        if (folded != node)
-        {
-            queueReplacement(folded, OriginalNode::IS_DROPPED);
-            mDidReplace = true;
-            return false;
-        }
-        return true;
-    }
-
-    bool visitUnary(Visit visit, TIntermUnary *node) override
-    {
-        TIntermTyped *folded = node->fold(mDiagnostics);
-        if (folded != node)
-        {
-            queueReplacement(folded, OriginalNode::IS_DROPPED);
-            mDidReplace = true;
-            return false;
-        }
-        return true;
-    }
-
-    bool visitSwizzle(Visit visit, TIntermSwizzle *node) override
-    {
-        TIntermTyped *folded = node->fold(mDiagnostics);
-        if (folded != node)
-        {
-            queueReplacement(folded, OriginalNode::IS_DROPPED);
-            mDidReplace = true;
-            return false;
-        }
-        return true;
-    }
-
-  private:
-    TDiagnostics *mDiagnostics;
-    bool mDidReplace;
-};
-
-}  // anonymous namespace
-
-void FoldExpressions(TIntermBlock *root, TDiagnostics *diagnostics)
-{
-    FoldExpressionsTraverser traverser(diagnostics);
-    do
-    {
-        traverser.nextIteration();
-        root->traverse(&traverser);
-        traverser.updateTree();
-    } while (traverser.didReplace());
-}
-
-}  // namespace sh
deleted file mode 100644
--- a/gfx/angle/checkout/src/compiler/translator/FoldExpressions.h
+++ /dev/null
@@ -1,24 +0,0 @@
-//
-// Copyright (c) 2018 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// FoldExpressions.h: Fold expressions. This may fold expressions so that the qualifier of the
-// folded node differs from the qualifier of the original expression, so it needs to be done after
-// parsing and validation of qualifiers is complete. Expressions that are folded: 1. Ternary ops
-// with a constant condition.
-
-#ifndef COMPILER_TRANSLATOR_FOLDEXPRESSIONS_H_
-#define COMPILER_TRANSLATOR_FOLDEXPRESSIONS_H_
-
-namespace sh
-{
-
-class TIntermBlock;
-class TDiagnostics;
-
-void FoldExpressions(TIntermBlock *root, TDiagnostics *diagnostics);
-
-}  // namespace sh
-
-#endif  // COMPILER_TRANSLATOR_FOLDEXPRESSIONS_H_
--- a/gfx/angle/checkout/src/compiler/translator/ImmutableString.cpp
+++ b/gfx/angle/checkout/src/compiler/translator/ImmutableString.cpp
@@ -30,22 +30,40 @@ const size_t ImmutableString::FowlerNoll
 template <>
 const size_t ImmutableString::FowlerNollVoHash<8>::kFnvPrime =
     static_cast<size_t>(1099511628211ull);
 
 template <>
 const size_t ImmutableString::FowlerNollVoHash<8>::kFnvOffsetBasis =
     static_cast<size_t>(0xcbf29ce484222325ull);
 
-uint32_t ImmutableString::hash32() const
+uint32_t ImmutableString::mangledNameHash() const
 {
-    const char *data_ptr = data();
-    uint32_t hash        = static_cast<uint32_t>(FowlerNollVoHash<4>::kFnvOffsetBasis);
-    while ((*data_ptr) != '\0')
+    const char *dataPtr              = data();
+    uint32_t hash                    = static_cast<uint32_t>(FowlerNollVoHash<4>::kFnvOffsetBasis);
+    const uint32_t kMaxSixBitValue   = (1u << 6) - 1u;
+    uint32_t parenLocation           = kMaxSixBitValue;
+    uint32_t hasArrayOrBlockParamBit = 0u;
+    uint32_t index                   = 0;
+    while (dataPtr[index] != '\0')
     {
-        hash = hash ^ (*data_ptr);
+        hash = hash ^ dataPtr[index];
         hash = hash * static_cast<uint32_t>(FowlerNollVoHash<4>::kFnvPrime);
-        ++data_ptr;
+        if (dataPtr[index] == '(')
+        {
+            // We should only reach here once, since this function should not be called with invalid
+            // mangled names.
+            ASSERT(parenLocation == kMaxSixBitValue);
+            parenLocation = index;
+        }
+        else if (dataPtr[index] == '{' || dataPtr[index] == '[')
+        {
+            hasArrayOrBlockParamBit = 1u;
+        }
+        ++index;
     }
-    return hash;
+    // Should not be called with strings longer than 63 characters.
+    ASSERT(index <= kMaxSixBitValue);
+    return ((hash >> 13) ^ (hash & 0x1fff)) | (index << 19) | (parenLocation << 25) |
+           (hasArrayOrBlockParamBit << 31);
 }
 
 }  // namespace sh
--- a/gfx/angle/checkout/src/compiler/translator/ImmutableString.h
+++ b/gfx/angle/checkout/src/compiler/translator/ImmutableString.h
@@ -123,17 +123,20 @@ class ImmutableString
                 hash = hash ^ (*data);
                 hash = hash * kFnvPrime;
                 ++data;
             }
             return hash;
         }
     };
 
-    uint32_t hash32() const;
+    // This hash encodes the opening parentheses location (if any), name length and whether the name
+    // contains { or [ characters in addition to a 19-bit hash. This way the hash is more useful for
+    // lookups. The string passed in should be at most 63 characters.
+    uint32_t mangledNameHash() const;
 
   private:
     const char *mData;
     size_t mLength;
 };
 
 }  // namespace sh
 
--- a/gfx/angle/checkout/src/compiler/translator/ImmutableStringBuilder.h
+++ b/gfx/angle/checkout/src/compiler/translator/ImmutableStringBuilder.h
@@ -42,17 +42,17 @@ class ImmutableStringBuilder
         while (((number >> (index * 4)) & 0xfu) == 0 && index > 0)
         {
             --index;
         }
         // Write the rest of the hex digits.
         while (index >= 0)
         {
             char digit     = static_cast<char>((number >> (index * 4)) & 0xfu);
-            char digitChar = digit < 10 ? digit + '0' : digit + 'a';
+            char digitChar = (digit < 10) ? (digit + '0') : (digit + ('a' - 10));
             mData[mPos++]  = digitChar;
             --index;
         }
         return;
     }
 
   private:
     inline static char *AllocateEmptyPoolCharArray(size_t strLength)
deleted file mode 100644
--- a/gfx/angle/checkout/src/compiler/translator/InitializeVariables.cpp
+++ /dev/null
@@ -1,311 +0,0 @@
-//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "compiler/translator/InitializeVariables.h"
-
-#include "angle_gl.h"
-#include "common/debug.h"
-#include "compiler/translator/FindMain.h"
-#include "compiler/translator/IntermNode_util.h"
-#include "compiler/translator/IntermTraverse.h"
-#include "compiler/translator/StaticType.h"
-#include "compiler/translator/SymbolTable.h"
-#include "compiler/translator/util.h"
-
-namespace sh
-{
-
-namespace
-{
-
-void AddArrayZeroInitSequence(const TIntermTyped *initializedNode,
-                              bool canUseLoopsToInitialize,
-                              bool highPrecisionSupported,
-                              TIntermSequence *initSequenceOut,
-                              TSymbolTable *symbolTable);
-
-void AddStructZeroInitSequence(const TIntermTyped *initializedNode,
-                               bool canUseLoopsToInitialize,
-                               bool highPrecisionSupported,
-                               TIntermSequence *initSequenceOut,
-                               TSymbolTable *symbolTable);
-
-TIntermBinary *CreateZeroInitAssignment(const TIntermTyped *initializedNode)
-{
-    TIntermTyped *zero = CreateZeroNode(initializedNode->getType());
-    return new TIntermBinary(EOpAssign, initializedNode->deepCopy(), zero);
-}
-
-void AddZeroInitSequence(const TIntermTyped *initializedNode,
-                         bool canUseLoopsToInitialize,
-                         bool highPrecisionSupported,
-                         TIntermSequence *initSequenceOut,
-                         TSymbolTable *symbolTable)
-{
-    if (initializedNode->isArray())
-    {
-        AddArrayZeroInitSequence(initializedNode, canUseLoopsToInitialize, highPrecisionSupported,
-                                 initSequenceOut, symbolTable);
-    }
-    else if (initializedNode->getType().isStructureContainingArrays() ||
-             initializedNode->getType().isNamelessStruct())
-    {
-        AddStructZeroInitSequence(initializedNode, canUseLoopsToInitialize, highPrecisionSupported,
-                                  initSequenceOut, symbolTable);
-    }
-    else
-    {
-        initSequenceOut->push_back(CreateZeroInitAssignment(initializedNode));
-    }
-}
-
-void AddStructZeroInitSequence(const TIntermTyped *initializedNode,
-                               bool canUseLoopsToInitialize,
-                               bool highPrecisionSupported,
-                               TIntermSequence *initSequenceOut,
-                               TSymbolTable *symbolTable)
-{
-    ASSERT(initializedNode->getBasicType() == EbtStruct);
-    const TStructure *structType = initializedNode->getType().getStruct();
-    for (int i = 0; i < static_cast<int>(structType->fields().size()); ++i)
-    {
-        TIntermBinary *element = new TIntermBinary(EOpIndexDirectStruct,
-                                                   initializedNode->deepCopy(), CreateIndexNode(i));
-        // Structs can't be defined inside structs, so the type of a struct field can't be a
-        // nameless struct.
-        ASSERT(!element->getType().isNamelessStruct());
-        AddZeroInitSequence(element, canUseLoopsToInitialize, highPrecisionSupported,
-                            initSequenceOut, symbolTable);
-    }
-}
-
-void AddArrayZeroInitStatementList(const TIntermTyped *initializedNode,
-                                   bool canUseLoopsToInitialize,
-                                   bool highPrecisionSupported,
-                                   TIntermSequence *initSequenceOut,
-                                   TSymbolTable *symbolTable)
-{
-    for (unsigned int i = 0; i < initializedNode->getOutermostArraySize(); ++i)
-    {
-        TIntermBinary *element =
-            new TIntermBinary(EOpIndexDirect, initializedNode->deepCopy(), CreateIndexNode(i));
-        AddZeroInitSequence(element, canUseLoopsToInitialize, highPrecisionSupported,
-                            initSequenceOut, symbolTable);
-    }
-}
-
-void AddArrayZeroInitForLoop(const TIntermTyped *initializedNode,
-                             bool highPrecisionSupported,
-                             TIntermSequence *initSequenceOut,
-                             TSymbolTable *symbolTable)
-{
-    ASSERT(initializedNode->isArray());
-    const TType *mediumpIndexType = StaticType::Get<EbtInt, EbpMedium, EvqTemporary, 1, 1>();
-    const TType *highpIndexType   = StaticType::Get<EbtInt, EbpHigh, EvqTemporary, 1, 1>();
-    TVariable *indexVariable =
-        CreateTempVariable(symbolTable, highPrecisionSupported ? highpIndexType : mediumpIndexType);
-
-    TIntermSymbol *indexSymbolNode = CreateTempSymbolNode(indexVariable);
-    TIntermDeclaration *indexInit =
-        CreateTempInitDeclarationNode(indexVariable, CreateZeroNode(indexVariable->getType()));
-    TIntermConstantUnion *arraySizeNode = CreateIndexNode(initializedNode->getOutermostArraySize());
-    TIntermBinary *indexSmallerThanSize =
-        new TIntermBinary(EOpLessThan, indexSymbolNode->deepCopy(), arraySizeNode);
-    TIntermUnary *indexIncrement = new TIntermUnary(EOpPreIncrement, indexSymbolNode->deepCopy());
-
-    TIntermBlock *forLoopBody       = new TIntermBlock();
-    TIntermSequence *forLoopBodySeq = forLoopBody->getSequence();
-
-    TIntermBinary *element = new TIntermBinary(EOpIndexIndirect, initializedNode->deepCopy(),
-                                               indexSymbolNode->deepCopy());
-    AddZeroInitSequence(element, true, highPrecisionSupported, forLoopBodySeq, symbolTable);
-
-    TIntermLoop *forLoop =
-        new TIntermLoop(ELoopFor, indexInit, indexSmallerThanSize, indexIncrement, forLoopBody);
-    initSequenceOut->push_back(forLoop);
-}
-
-void AddArrayZeroInitSequence(const TIntermTyped *initializedNode,
-                              bool canUseLoopsToInitialize,
-                              bool highPrecisionSupported,
-                              TIntermSequence *initSequenceOut,
-                              TSymbolTable *symbolTable)
-{
-    // The array elements are assigned one by one to keep the AST compatible with ESSL 1.00 which
-    // doesn't have array assignment. We'll do this either with a for loop or just a list of
-    // statements assigning to each array index. Note that it is important to have the array init in
-    // the right order to workaround http://crbug.com/709317
-    bool isSmallArray = initializedNode->getOutermostArraySize() <= 1u ||
-                        (initializedNode->getBasicType() != EbtStruct &&
-                         !initializedNode->getType().isArrayOfArrays() &&
-                         initializedNode->getOutermostArraySize() <= 3u);
-    if (initializedNode->getQualifier() == EvqFragData ||
-        initializedNode->getQualifier() == EvqFragmentOut || isSmallArray ||
-        !canUseLoopsToInitialize)
-    {
-        // Fragment outputs should not be indexed by non-constant indices.
-        // Also it doesn't make sense to use loops to initialize very small arrays.
-        AddArrayZeroInitStatementList(initializedNode, canUseLoopsToInitialize,
-                                      highPrecisionSupported, initSequenceOut, symbolTable);
-    }
-    else
-    {
-        AddArrayZeroInitForLoop(initializedNode, highPrecisionSupported, initSequenceOut,
-                                symbolTable);
-    }
-}
-
-void InsertInitCode(TIntermSequence *mainBody,
-                    const InitVariableList &variables,
-                    TSymbolTable *symbolTable,
-                    int shaderVersion,
-                    const TExtensionBehavior &extensionBehavior,
-                    bool canUseLoopsToInitialize,
-                    bool highPrecisionSupported)
-{
-    for (const auto &var : variables)
-    {
-        // Note that tempVariableName will reference a short-lived char array here - that's fine
-        // since we're only using it to find symbols.
-        ImmutableString tempVariableName(var.name.c_str(), var.name.length());
-
-        TIntermTyped *initializedSymbol = nullptr;
-        if (var.isBuiltIn())
-        {
-            initializedSymbol =
-                ReferenceBuiltInVariable(tempVariableName, *symbolTable, shaderVersion);
-            if (initializedSymbol->getQualifier() == EvqFragData &&
-                !IsExtensionEnabled(extensionBehavior, TExtension::EXT_draw_buffers))
-            {
-                // If GL_EXT_draw_buffers is disabled, only the 0th index of gl_FragData can be
-                // written to.
-                // TODO(oetuaho): This is a bit hacky and would be better to remove, if we came up
-                // with a good way to do it. Right now "gl_FragData" in symbol table is initialized
-                // to have the array size of MaxDrawBuffers, and the initialization happens before
-                // the shader sets the extensions it is using.
-                initializedSymbol =
-                    new TIntermBinary(EOpIndexDirect, initializedSymbol, CreateIndexNode(0));
-            }
-        }
-        else
-        {
-            initializedSymbol = ReferenceGlobalVariable(tempVariableName, *symbolTable);
-        }
-        ASSERT(initializedSymbol != nullptr);
-
-        TIntermSequence *initCode = CreateInitCode(initializedSymbol, canUseLoopsToInitialize,
-                                                   highPrecisionSupported, symbolTable);
-        mainBody->insert(mainBody->begin(), initCode->begin(), initCode->end());
-    }
-}
-
-class InitializeLocalsTraverser : public TIntermTraverser
-{
-  public:
-    InitializeLocalsTraverser(int shaderVersion,
-                              TSymbolTable *symbolTable,
-                              bool canUseLoopsToInitialize,
-                              bool highPrecisionSupported)
-        : TIntermTraverser(true, false, false, symbolTable),
-          mShaderVersion(shaderVersion),
-          mCanUseLoopsToInitialize(canUseLoopsToInitialize),
-          mHighPrecisionSupported(highPrecisionSupported)
-    {
-    }
-
-  protected:
-    bool visitDeclaration(Visit visit, TIntermDeclaration *node) override
-    {
-        for (TIntermNode *declarator : *node->getSequence())
-        {
-            if (!mInGlobalScope && !declarator->getAsBinaryNode())
-            {
-                TIntermSymbol *symbol = declarator->getAsSymbolNode();
-                ASSERT(symbol);
-                if (symbol->variable().symbolType() == SymbolType::Empty)
-                {
-                    continue;
-                }
-
-                // Arrays may need to be initialized one element at a time, since ESSL 1.00 does not
-                // support array constructors or assigning arrays.
-                bool arrayConstructorUnavailable =
-                    (symbol->isArray() || symbol->getType().isStructureContainingArrays()) &&
-                    mShaderVersion == 100;
-                // Nameless struct constructors can't be referred to, so they also need to be
-                // initialized one element at a time.
-                // TODO(oetuaho): Check if it makes sense to initialize using a loop, even if we
-                // could use an initializer. It could at least reduce code size for very large
-                // arrays, but could hurt runtime performance.
-                if (arrayConstructorUnavailable || symbol->getType().isNamelessStruct())
-                {
-                    // SimplifyLoopConditions should have been run so the parent node of this node
-                    // should not be a loop.
-                    ASSERT(getParentNode()->getAsLoopNode() == nullptr);
-                    // SeparateDeclarations should have already been run, so we don't need to worry
-                    // about further declarators in this declaration depending on the effects of
-                    // this declarator.
-                    ASSERT(node->getSequence()->size() == 1);
-                    insertStatementsInParentBlock(
-                        TIntermSequence(), *CreateInitCode(symbol, mCanUseLoopsToInitialize,
-                                                           mHighPrecisionSupported, mSymbolTable));
-                }
-                else
-                {
-                    TIntermBinary *init =
-                        new TIntermBinary(EOpInitialize, symbol, CreateZeroNode(symbol->getType()));
-                    queueReplacementWithParent(node, symbol, init, OriginalNode::BECOMES_CHILD);
-                }
-            }
-        }
-        return false;
-    }
-
-  private:
-    int mShaderVersion;
-    bool mCanUseLoopsToInitialize;
-    bool mHighPrecisionSupported;
-};
-
-}  // namespace anonymous
-
-TIntermSequence *CreateInitCode(const TIntermTyped *initializedSymbol,
-                                bool canUseLoopsToInitialize,
-                                bool highPrecisionSupported,
-                                TSymbolTable *symbolTable)
-{
-    TIntermSequence *initCode = new TIntermSequence();
-    AddZeroInitSequence(initializedSymbol, canUseLoopsToInitialize, highPrecisionSupported,
-                        initCode, symbolTable);
-    return initCode;
-}
-
-void InitializeUninitializedLocals(TIntermBlock *root,
-                                   int shaderVersion,
-                                   bool canUseLoopsToInitialize,
-                                   bool highPrecisionSupported,
-                                   TSymbolTable *symbolTable)
-{
-    InitializeLocalsTraverser traverser(shaderVersion, symbolTable, canUseLoopsToInitialize,
-                                        highPrecisionSupported);
-    root->traverse(&traverser);
-    traverser.updateTree();
-}
-
-void InitializeVariables(TIntermBlock *root,
-                         const InitVariableList &vars,
-                         TSymbolTable *symbolTable,
-                         int shaderVersion,
-                         const TExtensionBehavior &extensionBehavior,
-                         bool canUseLoopsToInitialize,
-                         bool highPrecisionSupported)
-{
-    TIntermBlock *body = FindMainBody(root);
-    InsertInitCode(body->getSequence(), vars, symbolTable, shaderVersion, extensionBehavior,
-                   canUseLoopsToInitialize, highPrecisionSupported);
-}
-
-}  // namespace sh
deleted file mode 100644
--- a/gfx/angle/checkout/src/compiler/translator/InitializeVariables.h
+++ /dev/null
@@ -1,56 +0,0 @@
-//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#ifndef COMPILER_TRANSLATOR_INITIALIZEVARIABLES_H_
-#define COMPILER_TRANSLATOR_INITIALIZEVARIABLES_H_
-
-#include <GLSLANG/ShaderLang.h>
-
-#include "compiler/translator/ExtensionBehavior.h"
-#include "compiler/translator/IntermNode.h"
-
-namespace sh
-{
-class TSymbolTable;
-
-typedef std::vector<sh::ShaderVariable> InitVariableList;
-
-// For all of the functions below: If canUseLoopsToInitialize is set, for loops are used instead of
-// a large number of initializers where it can make sense, such as for initializing large arrays.
-
-// Return a sequence of assignment operations to initialize "initializedSymbol". initializedSymbol
-// may be an array, struct or any combination of these, as long as it contains only basic types.
-TIntermSequence *CreateInitCode(const TIntermTyped *initializedSymbol,
-                                bool canUseLoopsToInitialize,
-                                bool highPrecisionSupported,
-                                TSymbolTable *symbolTable);
-
-// Initialize all uninitialized local variables, so that undefined behavior is avoided.
-void InitializeUninitializedLocals(TIntermBlock *root,
-                                   int shaderVersion,
-                                   bool canUseLoopsToInitialize,
-                                   bool highPrecisionSupported,
-                                   TSymbolTable *symbolTable);
-
-// This function can initialize all the types that CreateInitCode is able to initialize. All
-// variables must be globals which can be found in the symbol table. For now it is used for the
-// following two scenarios:
-//   1. Initializing gl_Position;
-//   2. Initializing output variables referred to in the shader source.
-// Note: The type of each lvalue in an initializer is retrieved from the symbol table. gl_FragData
-// requires special handling because the number of indices which can be initialized is determined by
-// enabled extensions.
-void InitializeVariables(TIntermBlock *root,
-                         const InitVariableList &vars,
-                         TSymbolTable *symbolTable,
-                         int shaderVersion,
-                         const TExtensionBehavior &extensionBehavior,
-                         bool canUseLoopsToInitialize,
-                         bool highPrecisionSupported);
-
-}  // namespace sh
-
-#endif  // COMPILER_TRANSLATOR_INITIALIZEVARIABLES_H_
--- a/gfx/angle/checkout/src/compiler/translator/IntermNode.cpp
+++ b/gfx/angle/checkout/src/compiler/translator/IntermNode.cpp
@@ -259,17 +259,17 @@ bool TIntermAggregate::replaceChildNode(
 
 bool TIntermBlock::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
 {
     return replaceChildNodeInternal(original, replacement);
 }
 
 bool TIntermFunctionPrototype::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
 {
-    return replaceChildNodeInternal(original, replacement);
+    return false;
 }
 
 bool TIntermDeclaration::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
 {
     return replaceChildNodeInternal(original, replacement);
 }
 
 bool TIntermAggregateBase::replaceChildNodeInternal(TIntermNode *original, TIntermNode *replacement)
@@ -684,22 +684,16 @@ void TIntermBlock::appendStatement(TInte
     // need to add the declaration to the AST in that case because it might be relevant to the
     // validity of switch/case.
     if (statement != nullptr)
     {
         mStatements.push_back(statement);
     }
 }
 
-void TIntermFunctionPrototype::appendParameter(TIntermSymbol *parameter)
-{
-    ASSERT(parameter != nullptr);
-    mParameters.push_back(parameter);
-}
-
 void TIntermDeclaration::appendDeclarator(TIntermTyped *declarator)
 {
     ASSERT(declarator != nullptr);
     ASSERT(declarator->getAsSymbolNode() != nullptr ||
            (declarator->getAsBinaryNode() != nullptr &&
             declarator->getAsBinaryNode()->getOp() == EOpInitialize));
     ASSERT(mDeclarators.empty() ||
            declarator->getType().sameNonArrayType(mDeclarators.back()->getAsTyped()->getType()));
@@ -796,30 +790,33 @@ TIntermAggregate *TIntermAggregate::shal
 }
 
 TIntermSwizzle::TIntermSwizzle(const TIntermSwizzle &node) : TIntermExpression(node)
 {
     TIntermTyped *operandCopy = node.mOperand->deepCopy();
     ASSERT(operandCopy != nullptr);
     mOperand = operandCopy;
     mSwizzleOffsets = node.mSwizzleOffsets;
+    mHasFoldedDuplicateOffsets = node.mHasFoldedDuplicateOffsets;
 }
 
 TIntermBinary::TIntermBinary(const TIntermBinary &node)
     : TIntermOperator(node), mAddIndexClamp(node.mAddIndexClamp)
 {
     TIntermTyped *leftCopy  = node.mLeft->deepCopy();
     TIntermTyped *rightCopy = node.mRight->deepCopy();
     ASSERT(leftCopy != nullptr && rightCopy != nullptr);
     mLeft  = leftCopy;
     mRight = rightCopy;
 }
 
 TIntermUnary::TIntermUnary(const TIntermUnary &node)
-    : TIntermOperator(node), mUseEmulatedFunction(node.mUseEmulatedFunction)
+    : TIntermOperator(node),
+      mUseEmulatedFunction(node.mUseEmulatedFunction),
+      mFunction(node.mFunction)
 {
     TIntermTyped *operandCopy = node.mOperand->deepCopy();
     ASSERT(operandCopy != nullptr);
     mOperand = operandCopy;
 }
 
 TIntermTernary::TIntermTernary(const TIntermTernary &node) : TIntermExpression(node)
 {
@@ -1042,24 +1039,25 @@ void TIntermUnary::promote()
             mType.setQualifier(resultQualifier);
             break;
     }
 }
 
 TIntermSwizzle::TIntermSwizzle(TIntermTyped *operand, const TVector<int> &swizzleOffsets)
     : TIntermExpression(TType(EbtFloat, EbpUndefined)),
       mOperand(operand),
-      mSwizzleOffsets(swizzleOffsets)
+      mSwizzleOffsets(swizzleOffsets),
+      mHasFoldedDuplicateOffsets(false)
 {
     ASSERT(mSwizzleOffsets.size() <= 4);
     promote();
 }
 
-TIntermUnary::TIntermUnary(TOperator op, TIntermTyped *operand)
-    : TIntermOperator(op), mOperand(operand), mUseEmulatedFunction(false)
+TIntermUnary::TIntermUnary(TOperator op, TIntermTyped *operand, const TFunction *function)
+    : TIntermOperator(op), mOperand(operand), mUseEmulatedFunction(false), mFunction(function)
 {
     promote();
 }
 
 TIntermBinary::TIntermBinary(TOperator op, TIntermTyped *left, TIntermTyped *right)
     : TIntermOperator(op), mLeft(left), mRight(right), mAddIndexClamp(false)
 {
     promote();
@@ -1168,28 +1166,37 @@ void TIntermSwizzle::promote()
 
     auto numFields = mSwizzleOffsets.size();
     setType(TType(mOperand->getBasicType(), mOperand->getPrecision(), resultQualifier,
                   static_cast<unsigned char>(numFields)));
 }
 
 bool TIntermSwizzle::hasDuplicateOffsets() const
 {
+    if (mHasFoldedDuplicateOffsets)
+    {
+        return true;
+    }
     int offsetCount[4] = {0u, 0u, 0u, 0u};
     for (const auto offset : mSwizzleOffsets)
     {
         offsetCount[offset]++;
         if (offsetCount[offset] > 1)
         {
             return true;
         }
     }
     return false;
 }
 
+void TIntermSwizzle::setHasFoldedDuplicateOffsets(bool hasFoldedDuplicateOffsets)
+{
+    mHasFoldedDuplicateOffsets = hasFoldedDuplicateOffsets;
+}
+
 bool TIntermSwizzle::offsetsMatch(int offset) const
 {
     return mSwizzleOffsets.size() == 1 && mSwizzleOffsets[0] == offset;
 }
 
 void TIntermSwizzle::writeOffsetsAsXYZW(TInfoSinkBase *out) const
 {
     for (const int offset : mSwizzleOffsets)
@@ -1473,16 +1480,34 @@ const TConstantUnion *TIntermConstantUni
     {
         UNREACHABLE();
         return nullptr;
     }
 }
 
 TIntermTyped *TIntermSwizzle::fold(TDiagnostics * /* diagnostics */)
 {
+    TIntermSwizzle *operandSwizzle = mOperand->getAsSwizzleNode();
+    if (operandSwizzle)
+    {
+        // We need to fold the two swizzles into one, so that repeated swizzling can't cause stack
+        // overflow in ParseContext::checkCanBeLValue().
+        bool hadDuplicateOffsets = operandSwizzle->hasDuplicateOffsets();
+        TVector<int> foldedOffsets;
+        for (int offset : mSwizzleOffsets)
+        {
+            // Offset should already be validated.
+            ASSERT(static_cast<size_t>(offset) < operandSwizzle->mSwizzleOffsets.size());
+            foldedOffsets.push_back(operandSwizzle->mSwizzleOffsets[offset]);
+        }
+        operandSwizzle->mSwizzleOffsets = foldedOffsets;
+        operandSwizzle->setType(getType());
+        operandSwizzle->setHasFoldedDuplicateOffsets(hadDuplicateOffsets);
+        return operandSwizzle;
+    }
     TIntermConstantUnion *operandConstant = mOperand->getAsConstantUnion();
     if (operandConstant == nullptr)
     {
         return this;
     }
 
     TConstantUnion *constArray = new TConstantUnion[mSwizzleOffsets.size()];
     for (size_t i = 0; i < mSwizzleOffsets.size(); ++i)
--- a/gfx/angle/checkout/src/compiler/translator/IntermNode.h
+++ b/gfx/angle/checkout/src/compiler/translator/IntermNode.h
@@ -426,23 +426,25 @@ class TIntermSwizzle : public TIntermExp
     bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
 
     bool hasSideEffects() const override { return mOperand->hasSideEffects(); }
 
     TIntermTyped *getOperand() { return mOperand; }
     void writeOffsetsAsXYZW(TInfoSinkBase *out) const;
 
     bool hasDuplicateOffsets() const;
+    void setHasFoldedDuplicateOffsets(bool hasFoldedDuplicateOffsets);
     bool offsetsMatch(int offset) const;
 
     TIntermTyped *fold(TDiagnostics *diagnostics) override;
 
   protected:
     TIntermTyped *mOperand;
     TVector<int> mSwizzleOffsets;
+    bool mHasFoldedDuplicateOffsets;
 
   private:
     void promote();
 
     TIntermSwizzle(const TIntermSwizzle &node);  // Note: not deleted, just private!
 };
 
 //
@@ -498,39 +500,43 @@ class TIntermBinary : public TIntermOper
 };
 
 //
 // Nodes for unary math operators.
 //
 class TIntermUnary : public TIntermOperator
 {
   public:
-    TIntermUnary(TOperator op, TIntermTyped *operand);
+    TIntermUnary(TOperator op, TIntermTyped *operand, const TFunction *function);
 
     TIntermTyped *deepCopy() const override { return new TIntermUnary(*this); }
 
     void traverse(TIntermTraverser *it) override;
     TIntermUnary *getAsUnaryNode() override { return this; }
     bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
 
     bool hasSideEffects() const override { return isAssignment() || mOperand->hasSideEffects(); }
 
     TIntermTyped *getOperand() { return mOperand; }
     TIntermTyped *fold(TDiagnostics *diagnostics) override;
 
+    const TFunction *getFunction() const { return mFunction; }
+
     void setUseEmulatedFunction() { mUseEmulatedFunction = true; }
     bool getUseEmulatedFunction() { return mUseEmulatedFunction; }
 
   protected:
     TIntermTyped *mOperand;
 
     // If set to true, replace the built-in function call with an emulated one
     // to work around driver bugs.
     bool mUseEmulatedFunction;
 
+    const TFunction *const mFunction;
+
   private:
     void promote();
 
     TIntermUnary(const TIntermUnary &node);  // note: not deleted, just private!
 };
 
 typedef TVector<TIntermNode *> TIntermSequence;
 typedef TVector<int> TQualifierList;
@@ -655,17 +661,17 @@ class TIntermBlock : public TIntermNode,
     const TIntermSequence *getSequence() const override { return &mStatements; }
 
   protected:
     TIntermSequence mStatements;
 };
 
 // Function prototype. May be in the AST either as a function prototype declaration or as a part of
 // a function definition. The type of the node is the function return type.
-class TIntermFunctionPrototype : public TIntermTyped, public TIntermAggregateBase
+class TIntermFunctionPrototype : public TIntermTyped
 {
   public:
     TIntermFunctionPrototype(const TFunction *function);
     ~TIntermFunctionPrototype() {}
 
     TIntermFunctionPrototype *getAsFunctionPrototypeNode() override { return this; }
     void traverse(TIntermTraverser *it) override;
     bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
@@ -678,27 +684,19 @@ class TIntermFunctionPrototype : public 
         return nullptr;
     }
     bool hasSideEffects() const override
     {
         UNREACHABLE();
         return true;
     }
 
-    // Only intended for initially building the declaration.
-    void appendParameter(TIntermSymbol *parameter);
-
-    TIntermSequence *getSequence() override { return &mParameters; }
-    const TIntermSequence *getSequence() const override { return &mParameters; }
-
     const TFunction *getFunction() const { return mFunction; }
 
   protected:
-    TIntermSequence mParameters;
-
     const TFunction *const mFunction;
 };
 
 // Node for function definitions. The prototype child node stores the function header including
 // parameters, and the body child node stores the function body.
 class TIntermFunctionDefinition : public TIntermNode
 {
   public:
deleted file mode 100644
--- a/gfx/angle/checkout/src/compiler/translator/IntermNodePatternMatcher.cpp
+++ /dev/null
@@ -1,199 +0,0 @@
-//
-// Copyright (c) 2016 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// IntermNodePatternMatcher is a helper class for matching node trees to given patterns.
-// It can be used whenever the same checks for certain node structures are common to multiple AST
-// traversers.
-//
-
-#include "compiler/translator/IntermNodePatternMatcher.h"
-
-#include "compiler/translator/IntermNode.h"
-#include "compiler/translator/SymbolTable.h"
-
-namespace sh
-{
-
-namespace
-{
-
-bool ContainsMatrixNode(const TIntermSequence &sequence)
-{
-    for (size_t ii = 0; ii < sequence.size(); ++ii)
-    {
-        TIntermTyped *node = sequence[ii]->getAsTyped();
-        if (node && node->isMatrix())
-            return true;
-    }
-    return false;
-}
-
-bool ContainsVectorNode(const TIntermSequence &sequence)
-{
-    for (size_t ii = 0; ii < sequence.size(); ++ii)
-    {
-        TIntermTyped *node = sequence[ii]->getAsTyped();
-        if (node && node->isVector())
-            return true;
-    }
-    return false;
-}
-
-}  // anonymous namespace
-
-IntermNodePatternMatcher::IntermNodePatternMatcher(const unsigned int mask) : mMask(mask)
-{
-}
-
-// static
-bool IntermNodePatternMatcher::IsDynamicIndexingOfVectorOrMatrix(TIntermBinary *node)
-{
-    return node->getOp() == EOpIndexIndirect && !node->getLeft()->isArray() &&
-           node->getLeft()->getBasicType() != EbtStruct;
-}
-
-bool IntermNodePatternMatcher::matchInternal(TIntermBinary *node, TIntermNode *parentNode)
-{
-    if ((mMask & kExpressionReturningArray) != 0)
-    {
-        if (node->isArray() && node->getOp() == EOpAssign && parentNode != nullptr &&
-            !parentNode->getAsBlock())
-        {
-            return true;
-        }
-    }
-
-    if ((mMask & kUnfoldedShortCircuitExpression) != 0)
-    {
-        if (node->getRight()->hasSideEffects() &&
-            (node->getOp() == EOpLogicalOr || node->getOp() == EOpLogicalAnd))
-        {
-            return true;
-        }
-    }
-    return false;
-}
-
-bool IntermNodePatternMatcher::match(TIntermUnary *node)
-{
-    if ((mMask & kArrayLengthMethod) != 0)
-    {
-        if (node->getOp() == EOpArrayLength)
-        {
-            return true;
-        }
-    }
-    return false;
-}
-
-bool IntermNodePatternMatcher::match(TIntermBinary *node, TIntermNode *parentNode)
-{
-    // L-value tracking information is needed to check for dynamic indexing in L-value.
-    // Traversers that don't track l-values can still use this class and match binary nodes with
-    // this variation of this method if they don't need to check for dynamic indexing in l-values.
-    ASSERT((mMask & kDynamicIndexingOfVectorOrMatrixInLValue) == 0);
-    return matchInternal(node, parentNode);
-}
-
-bool IntermNodePatternMatcher::match(TIntermBinary *node,
-                                     TIntermNode *parentNode,
-                                     bool isLValueRequiredHere)
-{
-    if (matchInternal(node, parentNode))
-    {
-        return true;
-    }
-    if ((mMask & kDynamicIndexingOfVectorOrMatrixInLValue) != 0)
-    {
-        if (isLValueRequiredHere && IsDynamicIndexingOfVectorOrMatrix(node))
-        {
-            return true;
-        }
-    }
-    return false;
-}
-
-bool IntermNodePatternMatcher::match(TIntermAggregate *node, TIntermNode *parentNode)
-{
-    if ((mMask & kExpressionReturningArray) != 0)
-    {
-        if (parentNode != nullptr)
-        {
-            TIntermBinary *parentBinary = parentNode->getAsBinaryNode();
-            bool parentIsAssignment =
-                (parentBinary != nullptr &&
-                 (parentBinary->getOp() == EOpAssign || parentBinary->getOp() == EOpInitialize));
-
-            if (node->getType().isArray() && !parentIsAssignment &&
-                (node->isConstructor() || node->isFunctionCall()) && !parentNode->getAsBlock())
-            {
-                return true;
-            }
-        }
-    }
-    if ((mMask & kScalarizedVecOrMatConstructor) != 0)
-    {
-        if (node->getOp() == EOpConstruct)
-        {
-            if (node->getType().isVector() && ContainsMatrixNode(*(node->getSequence())))
-            {
-                return true;
-            }
-            else if (node->getType().isMatrix() && ContainsVectorNode(*(node->getSequence())))
-            {
-                return true;
-            }
-        }
-    }
-    return false;
-}
-
-bool IntermNodePatternMatcher::match(TIntermTernary *node)
-{
-    if ((mMask & kUnfoldedShortCircuitExpression) != 0)
-    {
-        return true;
-    }
-    return false;
-}
-