Revert "Child fragment processors are now written as separate functions"

This reverts commit 0364bde2c49616bc9d2f68742d36bfedbeb7e950.

Reason for revert: bot breakage, e.g. https://chromium-swarm.appspot.com/task?id=44942724fab4b710 and https://chromium-swarm.appspot.com/task?id=44938767e5fbb810
Original change's description:
> Child fragment processors are now written as separate functions
> instead of inline
> 
> Bug: skia:
> Change-Id: I3c6c876fea9cfcc311fc09c0fdf0375b776004aa
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/210632
> Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
> Reviewed-by: Michael Ludwig <michaelludwig@google.com>

TBR=ethannicholas@google.com,michaelludwig@google.com

Change-Id: If33c1f554a090cd7541878e77712d5ce968ec70a
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: skia:
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/211943
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
diff --git a/src/core/SkNormalMapSource.cpp b/src/core/SkNormalMapSource.cpp
index d99bd9a..fab80a3 100644
--- a/src/core/SkNormalMapSource.cpp
+++ b/src/core/SkNormalMapSource.cpp
@@ -49,11 +49,10 @@
             fXformUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kFloat2x2_GrSLType,
                                                    "Xform", &xformUniName);
 
-            const char* dstNormalColorName = "dstNormalColor";
-            fragBuilder->codeAppendf("half4 %s;\n", dstNormalColorName);
-            this->invokeChild(0, dstNormalColorName, args);
+            SkString dstNormalColorName("dstNormalColor");
+            this->emitChild(0, &dstNormalColorName, args);
             fragBuilder->codeAppendf("float3 normal = normalize(%s.rgb - float3(0.5));",
-                                     dstNormalColorName);
+                                     dstNormalColorName.c_str());
 
             // If there's no x & y components, return (0, 0, +/- 1) instead to avoid division by 0
             fragBuilder->codeAppend( "if (abs(normal.z) > 0.999) {");
diff --git a/src/gpu/GrColorSpaceXform.cpp b/src/gpu/GrColorSpaceXform.cpp
index 187e582..39118a6 100644
--- a/src/gpu/GrColorSpaceXform.cpp
+++ b/src/gpu/GrColorSpaceXform.cpp
@@ -65,12 +65,11 @@
         fColorSpaceHelper.emitCode(uniformHandler, csxe.colorXform());
 
         if (this->numChildProcessors()) {
-            const char* childColor = "src_color";
-            fragBuilder->codeAppendf("half4 %s;\n", childColor);
-            this->invokeChild(0, childColor, args);
+            SkString childColor("src_color");
+            this->emitChild(0, &childColor, args);
 
             SkString xformedColor;
-            fragBuilder->appendColorGamutXform(&xformedColor, childColor, &fColorSpaceHelper);
+            fragBuilder->appendColorGamutXform(&xformedColor, childColor.c_str(), &fColorSpaceHelper);
             fragBuilder->codeAppendf("%s = %s * %s;", args.fOutputColor, xformedColor.c_str(),
                                      args.fInputColor);
         } else {
diff --git a/src/gpu/GrFragmentProcessor.cpp b/src/gpu/GrFragmentProcessor.cpp
index 1cc5e71..7205f08 100644
--- a/src/gpu/GrFragmentProcessor.cpp
+++ b/src/gpu/GrFragmentProcessor.cpp
@@ -241,7 +241,7 @@
             public:
                 void emitCode(EmitArgs& args) override {
                     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
-                    this->invokeChild(0, args);
+                    this->emitChild(0, args);
                     fragBuilder->codeAppendf("%s.rgb *= %s.rgb;", args.fOutputColor,
                                                                 args.fInputColor);
                     fragBuilder->codeAppendf("%s *= %s.a;", args.fOutputColor, args.fInputColor);
@@ -318,19 +318,15 @@
                 void emitCode(EmitArgs& args) override {
                     // First guy's input might be nil.
                     SkString temp("out0");
-                    GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
-                    fragBuilder->codeAppendf("half4 %s;\n", temp.c_str());
-                    this->invokeChild(0, args.fInputColor, temp.c_str(), args);
+                    this->emitChild(0, args.fInputColor, &temp, args);
                     SkString input = temp;
                     for (int i = 1; i < this->numChildProcessors() - 1; ++i) {
                         temp.printf("out%d", i);
-                        fragBuilder->codeAppendf("half4 %s;\n", temp.c_str());
-                        this->invokeChild(i, input.c_str(), temp.c_str(), args);
+                        this->emitChild(i, input.c_str(), &temp, args);
                         input = temp;
                     }
                     // Last guy writes to our output variable.
-                    this->invokeChild(this->numChildProcessors() - 1, input.c_str(),
-                                      args.fOutputColor, args);
+                    this->emitChild(this->numChildProcessors() - 1, input.c_str(), args);
                 }
             };
             return new GLFP;
diff --git a/src/gpu/effects/GrSkSLFP.cpp b/src/gpu/effects/GrSkSLFP.cpp
index cece9c1..f8fe85d 100644
--- a/src/gpu/effects/GrSkSLFP.cpp
+++ b/src/gpu/effects/GrSkSLFP.cpp
@@ -159,14 +159,12 @@
                                                                    SkSL::String(v->fName).c_str()));
             }
         }
-        GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
         std::vector<SkString> childNames;
         for (int i = 0; i < this->numChildProcessors(); ++i) {
-            SkString name = SkStringPrintf("_child%d", i);
-            fragBuilder->codeAppendf("half4 %s;\n", name.c_str());
-            childNames.push_back(std::move(name));
-            this->invokeChild(i, childNames[i].c_str(), args);
+            childNames.push_back(SkStringPrintf("_child%d", i));
+            this->emitChild(i, &childNames[i], args);
         }
+        GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
         int substringStartIndex = 0;
         int formatArgIndex = 0;
         for (size_t i = 0; i < fGLSL.length(); ++i) {
diff --git a/src/gpu/effects/GrXfermodeFragmentProcessor.cpp b/src/gpu/effects/GrXfermodeFragmentProcessor.cpp
index e4f4c0b..1424939 100644
--- a/src/gpu/effects/GrXfermodeFragmentProcessor.cpp
+++ b/src/gpu/effects/GrXfermodeFragmentProcessor.cpp
@@ -220,18 +220,20 @@
     }
 
     // declare outputColor and emit the code for each of the two children
-    const char* srcColor = "xfer_src";
-    fragBuilder->codeAppendf("half4 %s;\n", srcColor);
-    this->invokeChild(0, inputColor, srcColor, args);
+    SkString srcColor("xfer_src");
+    this->emitChild(0, inputColor, &srcColor, args);
 
-    const char* dstColor = "xfer_dst";
-    fragBuilder->codeAppendf("half4 %s;\n", dstColor);
-    this->invokeChild(1, inputColor, dstColor, args);
+    SkString dstColor("xfer_dst");
+    this->emitChild(1, inputColor, &dstColor, args);
 
     // emit blend code
     SkBlendMode mode = cs.getMode();
     fragBuilder->codeAppendf("// Compose Xfer Mode: %s\n", SkBlendMode_Name(mode));
-    GrGLSLBlend::AppendMode(fragBuilder, srcColor, dstColor, args.fOutputColor, mode);
+    GrGLSLBlend::AppendMode(fragBuilder,
+                            srcColor.c_str(),
+                            dstColor.c_str(),
+                            args.fOutputColor,
+                            mode);
 
     // re-multiply the output color by the input color's alpha
     if (args.fInputColor) {
@@ -436,18 +438,16 @@
         SkBlendMode mode = args.fFp.cast<ComposeOneFragmentProcessor>().mode();
         ComposeOneFragmentProcessor::Child child =
             args.fFp.cast<ComposeOneFragmentProcessor>().child();
-        const char* childColor = "child";
-        fragBuilder->codeAppendf("half4 %s;\n", childColor);
-        this->invokeChild(0, childColor, args);
+        SkString childColor("child");
+        this->emitChild(0, &childColor, args);
 
         // emit blend code
         fragBuilder->codeAppendf("// Compose Xfer Mode: %s\n", SkBlendMode_Name(mode));
+        const char* childStr = childColor.c_str();
         if (ComposeOneFragmentProcessor::kDst_Child == child) {
-            GrGLSLBlend::AppendMode(fragBuilder, args.fInputColor, childColor, args.fOutputColor,
-                                    mode);
+            GrGLSLBlend::AppendMode(fragBuilder, args.fInputColor, childStr, args.fOutputColor, mode);
         } else {
-            GrGLSLBlend::AppendMode(fragBuilder, childColor, args.fInputColor, args.fOutputColor,
-                                    mode);
+            GrGLSLBlend::AppendMode(fragBuilder, childStr, args.fInputColor, args.fOutputColor, mode);
         }
     }
 
diff --git a/src/gpu/effects/generated/GrComposeLerpEffect.cpp b/src/gpu/effects/generated/GrComposeLerpEffect.cpp
index 72a46d2..c9b4d3b 100644
--- a/src/gpu/effects/generated/GrComposeLerpEffect.cpp
+++ b/src/gpu/effects/generated/GrComposeLerpEffect.cpp
@@ -27,19 +27,23 @@
         (void)weight;
         weightVar =
                 args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kFloat_GrSLType, "weight");
-        fragBuilder->codeAppendf("half4 _process284;");
+        SkString _child0("_child0");
         if (_outer.child1_index >= 0) {
-            this->invokeChild(_outer.child1_index, "_process284", args);
+            this->emitChild(_outer.child1_index, &_child0, args);
+        } else {
+            fragBuilder->codeAppendf("half4 %s;", _child0.c_str());
         }
-        fragBuilder->codeAppendf("half4 _process353;");
+        SkString _child1("_child1");
         if (_outer.child2_index >= 0) {
-            this->invokeChild(_outer.child2_index, "_process353", args);
+            this->emitChild(_outer.child2_index, &_child1, args);
+        } else {
+            fragBuilder->codeAppendf("half4 %s;", _child1.c_str());
         }
-        fragBuilder->codeAppendf(
-                "%s = mix(%s ? _process284 : %s, %s ? _process353 : %s, half(%s));\n",
-                args.fOutputColor, _outer.child1_index >= 0 ? "true" : "false", args.fInputColor,
-                _outer.child2_index >= 0 ? "true" : "false", args.fInputColor,
-                args.fUniformHandler->getUniformCStr(weightVar));
+        fragBuilder->codeAppendf("%s = mix(%s ? %s : %s, %s ? %s : %s, half(%s));\n",
+                                 args.fOutputColor, _outer.child1_index >= 0 ? "true" : "false",
+                                 _child0.c_str(), args.fInputColor,
+                                 _outer.child2_index >= 0 ? "true" : "false", _child1.c_str(),
+                                 args.fInputColor, args.fUniformHandler->getUniformCStr(weightVar));
     }
 
 private:
diff --git a/src/gpu/effects/generated/GrComposeLerpRedEffect.cpp b/src/gpu/effects/generated/GrComposeLerpRedEffect.cpp
index a2f051b..d75b411 100644
--- a/src/gpu/effects/generated/GrComposeLerpRedEffect.cpp
+++ b/src/gpu/effects/generated/GrComposeLerpRedEffect.cpp
@@ -23,20 +23,24 @@
         GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
         const GrComposeLerpRedEffect& _outer = args.fFp.cast<GrComposeLerpRedEffect>();
         (void)_outer;
-        fragBuilder->codeAppendf("half4 _process286;");
+        SkString _child0("_child0");
         if (_outer.child1_index >= 0) {
-            this->invokeChild(_outer.child1_index, "_process286", args);
+            this->emitChild(_outer.child1_index, &_child0, args);
+        } else {
+            fragBuilder->codeAppendf("half4 %s;", _child0.c_str());
         }
-        fragBuilder->codeAppendf("half4 _process355;");
+        SkString _child1("_child1");
         if (_outer.child2_index >= 0) {
-            this->invokeChild(_outer.child2_index, "_process355", args);
+            this->emitChild(_outer.child2_index, &_child1, args);
+        } else {
+            fragBuilder->codeAppendf("half4 %s;", _child1.c_str());
         }
-        fragBuilder->codeAppendf("half4 _process407;");
-        this->invokeChild(_outer.lerp_index, "_process407", args);
-        fragBuilder->codeAppendf(
-                "%s = mix(%s ? _process286 : %s, %s ? _process355 : %s, _process407.x);\n",
-                args.fOutputColor, _outer.child1_index >= 0 ? "true" : "false", args.fInputColor,
-                _outer.child2_index >= 0 ? "true" : "false", args.fInputColor);
+        SkString _child2("_child2");
+        this->emitChild(_outer.lerp_index, &_child2, args);
+        fragBuilder->codeAppendf("%s = mix(%s ? %s : %s, %s ? %s : %s, %s.x);\n", args.fOutputColor,
+                                 _outer.child1_index >= 0 ? "true" : "false", _child0.c_str(),
+                                 args.fInputColor, _outer.child2_index >= 0 ? "true" : "false",
+                                 _child1.c_str(), args.fInputColor, _child2.c_str());
     }
 
 private:
diff --git a/src/gpu/effects/generated/GrMixerEffect.cpp b/src/gpu/effects/generated/GrMixerEffect.cpp
index 4ffa89c..af5a7af 100644
--- a/src/gpu/effects/generated/GrMixerEffect.cpp
+++ b/src/gpu/effects/generated/GrMixerEffect.cpp
@@ -28,17 +28,19 @@
         weightVar =
                 args.fUniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType, "weight");
         SkString _input0 = SkStringPrintf("%s", args.fInputColor);
-        fragBuilder->codeAppendf("half4 _process1272;");
-        this->invokeChild(_outer.fp0_index, _input0.c_str(), "_process1272", args);
-        fragBuilder->codeAppendf("half4 in0 = _process1272;");
+        SkString _child0("_child0");
+        this->emitChild(_outer.fp0_index, _input0.c_str(), &_child0, args);
+        fragBuilder->codeAppendf("half4 in0 = %s;", _child0.c_str());
         SkString _input1 = SkStringPrintf("%s", args.fInputColor);
-        fragBuilder->codeAppendf("half4 _process1330;");
+        SkString _child1("_child1");
         if (_outer.fp1_index >= 0) {
-            this->invokeChild(_outer.fp1_index, _input1.c_str(), "_process1330", args);
+            this->emitChild(_outer.fp1_index, _input1.c_str(), &_child1, args);
+        } else {
+            fragBuilder->codeAppendf("half4 %s;", _child1.c_str());
         }
-        fragBuilder->codeAppendf("\nhalf4 in1 = %s ? _process1330 : %s;\n%s = mix(in0, in1, %s);\n",
-                                 _outer.fp1_index >= 0 ? "true" : "false", args.fInputColor,
-                                 args.fOutputColor,
+        fragBuilder->codeAppendf("\nhalf4 in1 = %s ? %s : %s;\n%s = mix(in0, in1, %s);\n",
+                                 _outer.fp1_index >= 0 ? "true" : "false", _child1.c_str(),
+                                 args.fInputColor, args.fOutputColor,
                                  args.fUniformHandler->getUniformCStr(weightVar));
     }
 
diff --git a/src/gpu/effects/generated/GrOverrideInputFragmentProcessor.cpp b/src/gpu/effects/generated/GrOverrideInputFragmentProcessor.cpp
index b2f8339..9d7934e 100644
--- a/src/gpu/effects/generated/GrOverrideInputFragmentProcessor.cpp
+++ b/src/gpu/effects/generated/GrOverrideInputFragmentProcessor.cpp
@@ -43,9 +43,9 @@
                 _outer.literalColor.fR, _outer.literalColor.fG, _outer.literalColor.fB,
                 _outer.literalColor.fA);
         SkString _input0("constColor");
-        fragBuilder->codeAppendf("half4 _process1986;");
-        this->invokeChild(_outer.fp_index, _input0.c_str(), "_process1986", args);
-        fragBuilder->codeAppendf("\n%s = _process1986;\n", args.fOutputColor);
+        SkString _child0("_child0");
+        this->emitChild(_outer.fp_index, _input0.c_str(), &_child0, args);
+        fragBuilder->codeAppendf("\n%s = %s;\n", args.fOutputColor, _child0.c_str());
     }
 
 private:
diff --git a/src/gpu/glsl/GrGLSLFragmentProcessor.cpp b/src/gpu/glsl/GrGLSLFragmentProcessor.cpp
index d0ae1d6..4101860 100644
--- a/src/gpu/glsl/GrGLSLFragmentProcessor.cpp
+++ b/src/gpu/glsl/GrGLSLFragmentProcessor.cpp
@@ -16,27 +16,42 @@
     this->onSetData(pdman, processor);
 }
 
-void GrGLSLFragmentProcessor::invokeChild(int childIndex, const char* inputColor,
-                                          const char* outputColor, EmitArgs& args) {
-    SkASSERT(outputColor);
-    GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
-    while (childIndex >= (int) fFunctionNames.size()) {
-        fFunctionNames.emplace_back();
-    }
-    if (fFunctionNames[childIndex].size() == 0) {
-        this->internalEmitChild(childIndex, outputColor, args);
-    }
-    fragBuilder->codeAppendf("%s = %s(%s);", outputColor, fFunctionNames[childIndex].c_str(),
-                             inputColor ? inputColor : "half4(1)");
+void GrGLSLFragmentProcessor::emitChild(int childIndex, const char* inputColor, EmitArgs& args) {
+    this->internalEmitChild(childIndex, inputColor, args.fOutputColor, args);
 }
 
-void GrGLSLFragmentProcessor::internalEmitChild(int childIndex, const char* outputColor,
-                                                EmitArgs& args) {
+void GrGLSLFragmentProcessor::emitChild(int childIndex, const char* inputColor,
+                                        SkString* outputColor, EmitArgs& args) {
+    SkASSERT(outputColor);
     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
+    outputColor->append(fragBuilder->getMangleString());
+    fragBuilder->codeAppendf("half4 %s;", outputColor->c_str());
+    this->internalEmitChild(childIndex, inputColor, outputColor->c_str(), args);
+}
+
+void GrGLSLFragmentProcessor::internalEmitChild(int childIndex, const char* inputColor,
+                                                const char* outputColor, EmitArgs& args) {
+    GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
+
+    fragBuilder->onBeforeChildProcEmitCode();  // call first so mangleString is updated
+
+    // Prepare a mangled input color variable if the default is not used,
+    // inputName remains the empty string if no variable is needed.
+    SkString inputName;
+    if (inputColor&& strcmp("half4(1.0)", inputColor) != 0 && strcmp("half4(1)", inputColor) != 0) {
+        // The input name is based off of the current mangle string, and
+        // since this is called after onBeforeChildProcEmitCode(), it will be
+        // unique to the child processor (exactly what we want for its input).
+        inputName.appendf("_childInput%s", fragBuilder->getMangleString().c_str());
+        fragBuilder->codeAppendf("half4 %s = %s;", inputName.c_str(), inputColor);
+    }
 
     const GrFragmentProcessor& childProc = args.fFp.childProcessor(childIndex);
 
-    // emit the code for the child in its own function
+    // emit the code for the child in its own scope
+    fragBuilder->codeAppend("{\n");
+    fragBuilder->codeAppendf("// Child Index %d (mangle: %s): %s\n", childIndex,
+                             fragBuilder->getMangleString().c_str(), childProc.name());
     TransformedCoordVars coordVars = args.fTransformedCoords.childInputs(childIndex);
     TextureSamplers textureSamplers = args.fTexSamplers.childInputs(childIndex);
 
@@ -45,13 +60,14 @@
                        args.fUniformHandler,
                        args.fShaderCaps,
                        childProc,
-                       "_result",
-                       "_input",
+                       outputColor,
+                       inputName.size() > 0 ? inputName.c_str() : nullptr,
                        coordVars,
                        textureSamplers);
-    fFunctionNames[childIndex] = fragBuilder->writeProcessorFunction(
-                                                                   this->childProcessor(childIndex),
-                                                                   childArgs);
+    this->childProcessor(childIndex)->emitCode(childArgs);
+    fragBuilder->codeAppend("}\n");
+
+    fragBuilder->onAfterChildProcEmitCode();
 }
 
 //////////////////////////////////////////////////////////////////////////////
diff --git a/src/gpu/glsl/GrGLSLFragmentProcessor.h b/src/gpu/glsl/GrGLSLFragmentProcessor.h
index 3a1e645..4a8ce70 100644
--- a/src/gpu/glsl/GrGLSLFragmentProcessor.h
+++ b/src/gpu/glsl/GrGLSLFragmentProcessor.h
@@ -136,29 +136,32 @@
         return fChildProcessors[index];
     }
 
-    // Invoke the child with the default input color (solid white)
-    inline void invokeChild(int childIndex, const char* outputColor, EmitArgs& parentArgs) {
-        this->invokeChild(childIndex, nullptr, outputColor, parentArgs);
+    // Emit the child with the default input color (solid white)
+    inline void emitChild(int childIndex, SkString* outputColor, EmitArgs& parentArgs) {
+        this->emitChild(childIndex, nullptr, outputColor, parentArgs);
     }
 
     /** Will emit the code of a child proc in its own scope. Pass in the parent's EmitArgs and
-     *  invokeChild will automatically extract the coords and samplers of that child and pass them
+     *  emitChild will automatically extract the coords and samplers of that child and pass them
      *  on to the child's emitCode(). Also, any uniforms or functions emitted by the child will
-     *  have their names mangled to prevent redefinitions. The outputColor is the name of a
-     *  variable in which to store the resulting color. It is assumed to have already been declared
-     *  and is not declared by invokeChild. It is legal to pass nullptr as inputColor, since all
-     *  fragment processors are required to work without an input color.
+     *  have their names mangled to prevent redefinitions. The output color name is also mangled
+     *  therefore in an in/out param. It will be declared in mangled form by emitChild(). It is
+     *  legal to pass nullptr as inputColor, since all fragment processors are required to work
+     *  without an input color.
      */
-    void invokeChild(int childIndex, const char* inputColor, const char* outputColor,
-                     EmitArgs& parentArgs);
+    void emitChild(int childIndex, const char* inputColor, SkString* outputColor,
+                   EmitArgs& parentArgs);
 
     // Use the parent's output color to hold child's output, and use the
     // default input color of solid white
-    inline void invokeChild(int childIndex, EmitArgs& args) {
+    inline void emitChild(int childIndex, EmitArgs& args) {
         // null pointer cast required to disambiguate the function call
-        this->invokeChild(childIndex, args.fOutputColor, args);
+        this->emitChild(childIndex, (const char*) nullptr, args);
     }
 
+    /** Variation that uses the parent's output color variable to hold the child's output.*/
+    void emitChild(int childIndex, const char* inputColor, EmitArgs& parentArgs);
+
     /**
      * Pre-order traversal of a GLSLFP hierarchy, or of multiple trees with roots in an array of
      * GLSLFPS. This agrees with the traversal order of GrFragmentProcessor::Iter
@@ -186,10 +189,7 @@
     virtual void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) {}
 
 private:
-    void internalEmitChild(int, const char*, EmitArgs&);
-
-    // one per child; either not present or empty string if not yet emitted
-    SkTArray<SkString> fFunctionNames;
+    void internalEmitChild(int, const char*, const char*, EmitArgs&);
 
     SkTArray<GrGLSLFragmentProcessor*, true> fChildProcessors;
 
diff --git a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp
index 53aa098..f41f0f1 100644
--- a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp
+++ b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp
@@ -156,26 +156,6 @@
     this->codeAppendf("}");
 }
 
-SkString GrGLSLFPFragmentBuilder::writeProcessorFunction(GrGLSLFragmentProcessor* fp,
-                                                         GrGLSLFragmentProcessor::EmitArgs& args) {
-    this->onBeforeChildProcEmitCode();
-    this->nextStage();
-    this->codeAppendf("half4 %s;\n", args.fOutputColor);
-    fp->emitCode(args);
-    this->codeAppendf("return %s;", args.fOutputColor);
-    GrShaderVar inColor(args.fInputColor, kHalf4_GrSLType);
-    SkString result;
-    this->emitFunction(kHalf4_GrSLType,
-                       "stage",
-                       1,
-                       &inColor,
-                       this->code().c_str(),
-                       &result);
-    this->deleteStage();
-    this->onAfterChildProcEmitCode();
-    return result;
-}
-
 const char* GrGLSLFragmentShaderBuilder::dstColor() {
     SkDEBUGCODE(fHasReadDstColorThisStage_DebugOnly = true;)
 
diff --git a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.h b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.h
index 7e48b7c..050029c 100644
--- a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.h
+++ b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.h
@@ -11,7 +11,6 @@
 #include "include/gpu/GrBlend.h"
 #include "src/gpu/GrProcessor.h"
 #include "src/gpu/glsl/GrGLSLShaderBuilder.h"
-#include "GrGLSLFragmentProcessor.h"
 
 class GrRenderTarget;
 class GrGLSLVarying;
@@ -98,9 +97,6 @@
     virtual void onBeforeChildProcEmitCode() = 0;
     virtual void onAfterChildProcEmitCode() = 0;
 
-    virtual SkString writeProcessorFunction(GrGLSLFragmentProcessor* fp,
-                                            GrGLSLFragmentProcessor::EmitArgs& args);
-
     virtual const SkString& getMangleString() const = 0;
 
     virtual void forceHighPrecision() = 0;
diff --git a/src/gpu/glsl/GrGLSLProgramBuilder.cpp b/src/gpu/glsl/GrGLSLProgramBuilder.cpp
index 7e6f2a5..d1b5bac 100644
--- a/src/gpu/glsl/GrGLSLProgramBuilder.cpp
+++ b/src/gpu/glsl/GrGLSLProgramBuilder.cpp
@@ -206,8 +206,8 @@
                                            input.c_str(),
                                            coords,
                                            textureSamplers);
-    SkString funcName = fFS.writeProcessorFunction(fragProc, args);
-    fFS.codeAppendf("%s = %s(%s);", output.c_str(), funcName.c_str(), input.c_str());
+
+    fragProc->emitCode(args);
 
     // We have to check that effects and the code they emit are consistent, ie if an effect
     // asks for dst color, then the emit code needs to follow suit
diff --git a/src/gpu/glsl/GrGLSLShaderBuilder.h b/src/gpu/glsl/GrGLSLShaderBuilder.h
index 2e1c0ca..a203d3a 100644
--- a/src/gpu/glsl/GrGLSLShaderBuilder.h
+++ b/src/gpu/glsl/GrGLSLShaderBuilder.h
@@ -152,18 +152,6 @@
         GrGLSLShaderBuilder* fBuilder;
     };
 
-    void nextStage() {
-        fShaderStrings.push_back();
-        fCodeIndex++;
-    }
-
-    void deleteStage() {
-        fShaderStrings.pop_back();
-        fCodeIndex--;
-    }
-
-    SkString& code() { return fShaderStrings[fCodeIndex]; }
-
 protected:
     typedef GrTAllocator<GrShaderVar> VarArray;
     void appendDecls(const VarArray& vars, SkString* out) const;
@@ -205,6 +193,11 @@
 
     void compileAndAppendLayoutQualifiers();
 
+    void nextStage() {
+        fShaderStrings.push_back();
+        fCodeIndex++;
+    }
+
     SkString& versionDecl() { return fShaderStrings[kVersionDecl]; }
     SkString& extensions() { return fShaderStrings[kExtensions]; }
     SkString& definitions() { return fShaderStrings[kDefinitions]; }
@@ -215,6 +208,7 @@
     SkString& outputs() { return fShaderStrings[kOutputs]; }
     SkString& functions() { return fShaderStrings[kFunctions]; }
     SkString& main() { return fShaderStrings[kMain]; }
+    SkString& code() { return fShaderStrings[fCodeIndex]; }
 
     virtual void onFinalize() = 0;
 
@@ -237,6 +231,9 @@
     GrGLSLProgramBuilder* fProgramBuilder;
     SkSL::String fCompilerString;
     SkSTArray<kPrealloc, SkString> fShaderStrings;
+    SkString fCode;
+    SkString fFunctions;
+    SkString fExtensions;
 
     VarArray fInputs;
     VarArray fOutputs;
diff --git a/src/gpu/gradients/generated/GrClampedGradientEffect.cpp b/src/gpu/gradients/generated/GrClampedGradientEffect.cpp
index d88c4b9..7bb2452 100644
--- a/src/gpu/gradients/generated/GrClampedGradientEffect.cpp
+++ b/src/gpu/gradients/generated/GrClampedGradientEffect.cpp
@@ -35,23 +35,24 @@
                                                               kHalf4_GrSLType, "leftBorderColor");
         rightBorderColorVar = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
                                                                kHalf4_GrSLType, "rightBorderColor");
-        fragBuilder->codeAppendf("half4 _process1093;");
-        this->invokeChild(_outer.gradLayout_index, "_process1093", args);
+        SkString _child1("_child1");
+        this->emitChild(_outer.gradLayout_index, &_child1, args);
         fragBuilder->codeAppendf(
-                "half4 t = _process1093;\nif (!%s && t.y < 0.0) {\n    %s = half4(0.0);\n} else if "
-                "(t.x < 0.0) {\n    %s = %s;\n} else if (t.x > 1.0) {\n    %s = %s;\n} else {",
+                "half4 t = %s;\nif (!%s && t.y < 0.0) {\n    %s = half4(0.0);\n} else if (t.x < "
+                "0.0) {\n    %s = %s;\n} else if (t.x > 1.0) {\n    %s = %s;\n} else {",
+                _child1.c_str(),
                 (_outer.childProcessor(_outer.gradLayout_index).preservesOpaqueInput() ? "true"
                                                                                        : "false"),
                 args.fOutputColor, args.fOutputColor,
                 args.fUniformHandler->getUniformCStr(leftBorderColorVar), args.fOutputColor,
                 args.fUniformHandler->getUniformCStr(rightBorderColorVar));
         SkString _input0("t");
-        fragBuilder->codeAppendf("half4 _process1762;");
-        this->invokeChild(_outer.colorizer_index, _input0.c_str(), "_process1762", args);
-        fragBuilder->codeAppendf(
-                "\n    %s = _process1762;\n}\n@if (%s) {\n    %s.xyz *= %s.w;\n}\n",
-                args.fOutputColor, (_outer.makePremul ? "true" : "false"), args.fOutputColor,
-                args.fOutputColor);
+        SkString _child0("_child0");
+        this->emitChild(_outer.colorizer_index, _input0.c_str(), &_child0, args);
+        fragBuilder->codeAppendf("\n    %s = %s;\n}\n@if (%s) {\n    %s.xyz *= %s.w;\n}\n",
+                                 args.fOutputColor, _child0.c_str(),
+                                 (_outer.makePremul ? "true" : "false"), args.fOutputColor,
+                                 args.fOutputColor);
     }
 
 private:
diff --git a/src/gpu/gradients/generated/GrTiledGradientEffect.cpp b/src/gpu/gradients/generated/GrTiledGradientEffect.cpp
index 28a0832..cf5d583 100644
--- a/src/gpu/gradients/generated/GrTiledGradientEffect.cpp
+++ b/src/gpu/gradients/generated/GrTiledGradientEffect.cpp
@@ -29,24 +29,25 @@
         (void)makePremul;
         auto colorsAreOpaque = _outer.colorsAreOpaque;
         (void)colorsAreOpaque;
-        fragBuilder->codeAppendf("half4 _process447;");
-        this->invokeChild(_outer.gradLayout_index, "_process447", args);
+        SkString _child1("_child1");
+        this->emitChild(_outer.gradLayout_index, &_child1, args);
         fragBuilder->codeAppendf(
-                "half4 t = _process447;\nif (!%s && t.y < 0.0) {\n    %s = half4(0.0);\n} else {\n "
-                "   @if (%s) {\n        half t_1 = t.x - 1.0;\n        half tiled_t = (t_1 - 2.0 * "
+                "half4 t = %s;\nif (!%s && t.y < 0.0) {\n    %s = half4(0.0);\n} else {\n    @if "
+                "(%s) {\n        half t_1 = t.x - 1.0;\n        half tiled_t = (t_1 - 2.0 * "
                 "floor(t_1 * 0.5)) - 1.0;\n        if (sk_Caps.mustDoOpBetweenFloorAndAbs) {\n     "
                 "       tiled_t = clamp(tiled_t, -1.0, 1.0);\n        }\n        t.x = "
                 "abs(tiled_t);\n    } else {\n        t.x = fract(t.x);\n    }",
+                _child1.c_str(),
                 (_outer.childProcessor(_outer.gradLayout_index).preservesOpaqueInput() ? "true"
                                                                                        : "false"),
                 args.fOutputColor, (_outer.mirror ? "true" : "false"));
         SkString _input0("t");
-        fragBuilder->codeAppendf("half4 _process1459;");
-        this->invokeChild(_outer.colorizer_index, _input0.c_str(), "_process1459", args);
-        fragBuilder->codeAppendf(
-                "\n    %s = _process1459;\n}\n@if (%s) {\n    %s.xyz *= %s.w;\n}\n",
-                args.fOutputColor, (_outer.makePremul ? "true" : "false"), args.fOutputColor,
-                args.fOutputColor);
+        SkString _child0("_child0");
+        this->emitChild(_outer.colorizer_index, _input0.c_str(), &_child0, args);
+        fragBuilder->codeAppendf("\n    %s = %s;\n}\n@if (%s) {\n    %s.xyz *= %s.w;\n}\n",
+                                 args.fOutputColor, _child0.c_str(),
+                                 (_outer.makePremul ? "true" : "false"), args.fOutputColor,
+                                 args.fOutputColor);
     }
 
 private:
diff --git a/src/shaders/SkLightingShader.cpp b/src/shaders/SkLightingShader.cpp
index 2ff162f..bc4e631 100644
--- a/src/shaders/SkLightingShader.cpp
+++ b/src/shaders/SkLightingShader.cpp
@@ -165,11 +165,10 @@
 
             fragBuilder->codeAppendf("half4 diffuseColor = %s;", args.fInputColor);
 
-            const char* dstNormalName = "dstNormal";
-            fragBuilder->codeAppendf("half4 dstNormal;\n");
-            this->invokeChild(0, dstNormalName, args);
+            SkString dstNormalName("dstNormal");
+            this->emitChild(0, &dstNormalName, args);
 
-            fragBuilder->codeAppendf("float3 normal = %s.xyz;", dstNormalName);
+            fragBuilder->codeAppendf("float3 normal = %s.xyz;", dstNormalName.c_str());
 
             fragBuilder->codeAppend( "half3 result = half3(0.0);");
 
diff --git a/src/sksl/SkSLCPPCodeGenerator.cpp b/src/sksl/SkSLCPPCodeGenerator.cpp
index b6c1136..1ef7c43 100644
--- a/src/sksl/SkSLCPPCodeGenerator.cpp
+++ b/src/sksl/SkSLCPPCodeGenerator.cpp
@@ -425,31 +425,40 @@
 
         // Set to the empty string when no input color parameter should be emitted, which means this
         // must be properly formatted with a prefixed comma when the parameter should be inserted
-        // into the invokeChild() parameter list.
+        // into the emitChild() parameter list.
         String inputArg;
         if (c.fArguments.size() > 1) {
             SkASSERT(c.fArguments.size() == 2);
-            // Use the invokeChild() variant that accepts an input color, so convert the 2nd
+            // Use the emitChild() variant that accepts an input color, so convert the 2nd
             // argument's expression into C++ code that produces sksl stored in an SkString.
             String inputName = "_input" + to_string(index);
             addExtraEmitCodeLine(convertSKSLExpressionToCPP(*c.fArguments[1], inputName));
 
-            // invokeChild() needs a char*
+            // emitChild() needs a char*
             inputArg = ", " + inputName + ".c_str()";
         }
 
         // Write the output handling after the possible input handling
-        String childName = "_process" + to_string(c.fOffset);
-        addExtraEmitCodeLine("fragBuilder->codeAppendf(\"half4 " + childName + ";\");");
+        String childName = "_child" + to_string(index);
+        addExtraEmitCodeLine("SkString " + childName + "(\"" + childName + "\");");
         if (c.fArguments[0]->fType.kind() == Type::kNullable_Kind) {
             addExtraEmitCodeLine("if (_outer." + String(child.fName) + "_index >= 0) {\n    ");
         }
-        addExtraEmitCodeLine("this->invokeChild(_outer." + String(child.fName) + "_index" +
-                             inputArg + ", \"" + childName + "\", args);");
+        addExtraEmitCodeLine("this->emitChild(_outer." + String(child.fName) + "_index" +
+                             inputArg + ", &" + childName + ", args);");
         if (c.fArguments[0]->fType.kind() == Type::kNullable_Kind) {
-            addExtraEmitCodeLine("}");
+            // Null FPs are not emitted, but their output can still be referenced in dependent
+            // expressions - thus we always declare the variable.
+            // Note: this is essentially dead code required to satisfy the compiler, because
+            // 'process' function calls should always be guarded at a higher level, in the .fp
+            // source.
+            addExtraEmitCodeLine(
+                "} else {"
+                "   fragBuilder->codeAppendf(\"half4 %s;\", " + childName + ".c_str());"
+                "}");
         }
-        this->write(childName);
+        this->write("%s");
+        fFormatArgs.push_back(childName + ".c_str()");
         return;
     }
     INHERITED::writeFunctionCall(c);
diff --git a/src/sksl/SkSLGLSLCodeGenerator.cpp b/src/sksl/SkSLGLSLCodeGenerator.cpp
index d29dec3..0882023 100644
--- a/src/sksl/SkSLGLSLCodeGenerator.cpp
+++ b/src/sksl/SkSLGLSLCodeGenerator.cpp
@@ -1035,8 +1035,6 @@
 }
 
 void GLSLCodeGenerator::writeFunction(const FunctionDefinition& f) {
-    fSetupFragPositionLocal = false;
-    fSetupFragCoordWorkaround = false;
     if (fProgramKind != Program::kPipelineStage_Kind) {
         this->writeTypePrecision(f.fDeclaration.fReturnType);
         this->writeType(f.fDeclaration.fReturnType);
diff --git a/src/sksl/SkSLPipelineStageCodeGenerator.cpp b/src/sksl/SkSLPipelineStageCodeGenerator.cpp
index 424dff6..113cee6 100644
--- a/src/sksl/SkSLPipelineStageCodeGenerator.cpp
+++ b/src/sksl/SkSLPipelineStageCodeGenerator.cpp
@@ -100,7 +100,7 @@
             }
         }
         SkASSERT(found);
-        fExtraEmitCodeCode += "        this->invokeChild(" + to_string(index) + ", fChildren[" +
+        fExtraEmitCodeCode += "        this->emitChild(" + to_string(index) + ", fChildren[" +
                               to_string(index) + "], args);\n";
         this->write("%s");
         fFormatArgs->push_back(Compiler::FormatArg(Compiler::FormatArg::Kind::kChildProcessor,