Fix nondeterminism when copying intrinsic functions.

Previously, we copied intrinsic functions in a totally arbitrary order;
it used an unordered_set of pointers, so it could be affected by
switching standard libraries OR by malloc nondeterminism. (Surprisingly,
it was fairly consistent in practice on OS X/Linux.) This CL sorts the
intrinsic functions into a consistent order before copying them.

Change-Id: If90342bb77a9ae237a3ce91be3a9847311a722c4
Bug: skia:10749
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/318700
Commit-Queue: John Stiles <johnstiles@google.com>
Auto-Submit: John Stiles <johnstiles@google.com>
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
diff --git a/src/sksl/SkSLIRGenerator.cpp b/src/sksl/SkSLIRGenerator.cpp
index 5281c3f..a0f395d 100644
--- a/src/sksl/SkSLIRGenerator.cpp
+++ b/src/sksl/SkSLIRGenerator.cpp
@@ -2032,7 +2032,25 @@
     if (found != fIntrinsics->end() && !found->second.fAlreadyIncluded) {
         found->second.fAlreadyIncluded = true;
         FunctionDefinition& original = found->second.fIntrinsic->as<FunctionDefinition>();
-        for (const FunctionDeclaration* f : original.fReferencedIntrinsics) {
+
+        // Sort the referenced intrinsics into a consistent order; otherwise our output will become
+        // non-deterministic.
+        std::vector<const FunctionDeclaration*> intrinsics(original.fReferencedIntrinsics.begin(),
+                                                           original.fReferencedIntrinsics.end());
+        std::sort(intrinsics.begin(), intrinsics.end(),
+                  [](const FunctionDeclaration* a, const FunctionDeclaration* b) {
+                      if (a->fBuiltin != b->fBuiltin) {
+                          return a->fBuiltin < b->fBuiltin;
+                      }
+                      if (a->fOffset != b->fOffset) {
+                          return a->fOffset < b->fOffset;
+                      }
+                      if (a->fName != b->fName) {
+                          return a->fName < b->fName;
+                      }
+                      return a->description() < b->description();
+                  });
+        for (const FunctionDeclaration* f : intrinsics) {
             this->copyIntrinsicIfNeeded(*f);
         }
         fProgramElements->push_back(original.clone());
diff --git a/tests/sksl/blend/golden/BlendHue.glsl b/tests/sksl/blend/golden/BlendHue.glsl
index e054369..73db773 100644
--- a/tests/sksl/blend/golden/BlendHue.glsl
+++ b/tests/sksl/blend/golden/BlendHue.glsl
@@ -23,12 +23,12 @@
     }
     return maxComp > alpha && maxComp != lum ? lum + ((result - lum) * (alpha - lum)) / (maxComp - lum) : result;
 }
-vec3 _blend_set_color_saturation_helper(vec3 minMidMax, float sat) {
-    return minMidMax.x < minMidMax.z ? vec3(0.0, (sat * (minMidMax.y - minMidMax.x)) / (minMidMax.z - minMidMax.x), sat) : vec3(0.0);
-}
 float _blend_color_saturation(vec3 color) {
     return max(max(color.x, color.y), color.z) - min(min(color.x, color.y), color.z);
 }
+vec3 _blend_set_color_saturation_helper(vec3 minMidMax, float sat) {
+    return minMidMax.x < minMidMax.z ? vec3(0.0, (sat * (minMidMax.y - minMidMax.x)) / (minMidMax.z - minMidMax.x), sat) : vec3(0.0);
+}
 vec3 _blend_set_color_saturation(vec3 hueLumColor, vec3 satColor) {
     float _2_blend_color_saturation;
     {
diff --git a/tests/sksl/blend/golden/BlendHueStandaloneSettings.glsl b/tests/sksl/blend/golden/BlendHueStandaloneSettings.glsl
index a7da024..cb3bcd3 100644
--- a/tests/sksl/blend/golden/BlendHueStandaloneSettings.glsl
+++ b/tests/sksl/blend/golden/BlendHueStandaloneSettings.glsl
@@ -23,12 +23,12 @@
     }
     return maxComp > alpha && maxComp != lum ? lum + ((result - lum) * (alpha - lum)) / (maxComp - lum) : result;
 }
-vec3 _blend_set_color_saturation_helper(vec3 minMidMax, float sat) {
-    return minMidMax.x < minMidMax.z ? vec3(0.0, (sat * (minMidMax.y - minMidMax.x)) / (minMidMax.z - minMidMax.x), sat) : vec3(0.0);
-}
 float _blend_color_saturation(vec3 color) {
     return max(max(color.x, color.y), color.z) - min(min(color.x, color.y), color.z);
 }
+vec3 _blend_set_color_saturation_helper(vec3 minMidMax, float sat) {
+    return minMidMax.x < minMidMax.z ? vec3(0.0, (sat * (minMidMax.y - minMidMax.x)) / (minMidMax.z - minMidMax.x), sat) : vec3(0.0);
+}
 vec3 _blend_set_color_saturation(vec3 hueLumColor, vec3 satColor) {
     float _2_blend_color_saturation;
     {
diff --git a/tests/sksl/blend/golden/BlendSaturation.glsl b/tests/sksl/blend/golden/BlendSaturation.glsl
index 217d9a2..228c99d 100644
--- a/tests/sksl/blend/golden/BlendSaturation.glsl
+++ b/tests/sksl/blend/golden/BlendSaturation.glsl
@@ -23,12 +23,12 @@
     }
     return maxComp > alpha && maxComp != lum ? lum + ((result - lum) * (alpha - lum)) / (maxComp - lum) : result;
 }
-vec3 _blend_set_color_saturation_helper(vec3 minMidMax, float sat) {
-    return minMidMax.x < minMidMax.z ? vec3(0.0, (sat * (minMidMax.y - minMidMax.x)) / (minMidMax.z - minMidMax.x), sat) : vec3(0.0);
-}
 float _blend_color_saturation(vec3 color) {
     return max(max(color.x, color.y), color.z) - min(min(color.x, color.y), color.z);
 }
+vec3 _blend_set_color_saturation_helper(vec3 minMidMax, float sat) {
+    return minMidMax.x < minMidMax.z ? vec3(0.0, (sat * (minMidMax.y - minMidMax.x)) / (minMidMax.z - minMidMax.x), sat) : vec3(0.0);
+}
 vec3 _blend_set_color_saturation(vec3 hueLumColor, vec3 satColor) {
     float _2_blend_color_saturation;
     {
diff --git a/tests/sksl/blend/golden/BlendSaturationStandaloneSettings.glsl b/tests/sksl/blend/golden/BlendSaturationStandaloneSettings.glsl
index 2541a03..01dbff6 100644
--- a/tests/sksl/blend/golden/BlendSaturationStandaloneSettings.glsl
+++ b/tests/sksl/blend/golden/BlendSaturationStandaloneSettings.glsl
@@ -23,12 +23,12 @@
     }
     return maxComp > alpha && maxComp != lum ? lum + ((result - lum) * (alpha - lum)) / (maxComp - lum) : result;
 }
-vec3 _blend_set_color_saturation_helper(vec3 minMidMax, float sat) {
-    return minMidMax.x < minMidMax.z ? vec3(0.0, (sat * (minMidMax.y - minMidMax.x)) / (minMidMax.z - minMidMax.x), sat) : vec3(0.0);
-}
 float _blend_color_saturation(vec3 color) {
     return max(max(color.x, color.y), color.z) - min(min(color.x, color.y), color.z);
 }
+vec3 _blend_set_color_saturation_helper(vec3 minMidMax, float sat) {
+    return minMidMax.x < minMidMax.z ? vec3(0.0, (sat * (minMidMax.y - minMidMax.x)) / (minMidMax.z - minMidMax.x), sat) : vec3(0.0);
+}
 vec3 _blend_set_color_saturation(vec3 hueLumColor, vec3 satColor) {
     float _2_blend_color_saturation;
     {