Add a fBuiltin flag to FunctionDefinition.

This is useful because we can clone FunctionDefinitions without cloning
the matching FunctionDeclaration. The FunctionDeclaration will remain a
builtin, but the definition should be a malleable clone.

Change-Id: Icfc1e0855fb8fcd6914a5d657f5098986fcf19ea
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/328396
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
Auto-Submit: John Stiles <johnstiles@google.com>
diff --git a/src/sksl/SkSLIRGenerator.cpp b/src/sksl/SkSLIRGenerator.cpp
index ae1190f..ee06d8f 100644
--- a/src/sksl/SkSLIRGenerator.cpp
+++ b/src/sksl/SkSLIRGenerator.cpp
@@ -728,7 +728,7 @@
                                                                 fContext.fVoid_Type.get(),
                                                                 fIsBuiltinCode));
     fProgramElements->push_back(std::make_unique<FunctionDefinition>(/*offset=*/-1,
-                                                                     invokeDecl,
+                                                                     invokeDecl, fIsBuiltinCode,
                                                                      std::move(main)));
 
     std::vector<std::unique_ptr<VarDeclaration>> variables;
@@ -1062,8 +1062,8 @@
         if (Program::kVertex_Kind == fKind && funcData.fName == "main" && fRTAdjust) {
             body->children().push_back(this->getNormalizeSkPositionCode());
         }
-        auto result = std::make_unique<FunctionDefinition>(f.fOffset, decl, std::move(body),
-                                                           std::move(fReferencedIntrinsics));
+        auto result = std::make_unique<FunctionDefinition>(
+                f.fOffset, decl, fIsBuiltinCode, std::move(body), std::move(fReferencedIntrinsics));
         decl->setDefinition(result.get());
         result->setSource(&f);
         fProgramElements->push_back(std::move(result));
@@ -2020,7 +2020,11 @@
         for (const FunctionDeclaration* f : intrinsics) {
             this->copyIntrinsicIfNeeded(*f);
         }
-        fProgramElements->push_back(original.clone());
+
+        // Unmark the function as a built-in when cloning it, so that it is eligible for alteration.
+        std::unique_ptr<ProgramElement> clonedIntrinsicFn = original.clone();
+        clonedIntrinsicFn->as<FunctionDefinition>().setBuiltin(false);
+        fProgramElements->push_back(std::move(clonedIntrinsicFn));
     }
 }
 
diff --git a/src/sksl/SkSLInliner.cpp b/src/sksl/SkSLInliner.cpp
index ce4e61e..dfd7342 100644
--- a/src/sksl/SkSLInliner.cpp
+++ b/src/sksl/SkSLInliner.cpp
@@ -822,8 +822,10 @@
         switch (pe->kind()) {
             case ProgramElement::Kind::kFunction: {
                 FunctionDefinition& funcDef = pe->as<FunctionDefinition>();
-                fEnclosingFunction = &funcDef;
-                this->visitStatement(&funcDef.body());
+                if (!funcDef.isBuiltin()) {
+                    fEnclosingFunction = &funcDef;
+                    this->visitStatement(&funcDef.body());
+                }
                 break;
             }
             default:
diff --git a/src/sksl/SkSLRehydrator.cpp b/src/sksl/SkSLRehydrator.cpp
index eedb979..2a5646e 100644
--- a/src/sksl/SkSLRehydrator.cpp
+++ b/src/sksl/SkSLRehydrator.cpp
@@ -316,10 +316,11 @@
                 refs.insert(this->symbolRef<FunctionDeclaration>(
                                                                Symbol::Kind::kFunctionDeclaration));
             }
-            FunctionDefinition* result = new FunctionDefinition(-1, decl, std::move(body),
-                                                                std::move(refs));
-            decl->setDefinition(result);
-            return std::unique_ptr<ProgramElement>(result);
+            auto result = std::make_unique<FunctionDefinition>(/*offset=*/-1, decl,
+                                                               /*builtin=*/true, std::move(body),
+                                                               std::move(refs));
+            decl->setDefinition(result.get());
+            return std::move(result);
         }
         case Rehydrator::kInterfaceBlock_Command: {
             const Symbol* var = this->symbol();
diff --git a/src/sksl/ir/SkSLFunctionDefinition.h b/src/sksl/ir/SkSLFunctionDefinition.h
index 304aee1..fa69bc5 100644
--- a/src/sksl/ir/SkSLFunctionDefinition.h
+++ b/src/sksl/ir/SkSLFunctionDefinition.h
@@ -23,11 +23,12 @@
     static constexpr Kind kProgramElementKind = Kind::kFunction;
 
     FunctionDefinition(int offset,
-                       const FunctionDeclaration* declaration,
+                       const FunctionDeclaration* declaration, bool builtin,
                        std::unique_ptr<Statement> body,
                        std::unordered_set<const FunctionDeclaration*> referencedIntrinsics = {})
-        : INHERITED(offset, FunctionDefinitionData{declaration, std::move(referencedIntrinsics),
-                                                   nullptr}) {
+        : INHERITED(offset,
+                    FunctionDefinitionData{declaration, builtin, std::move(referencedIntrinsics),
+                                           /*fSource=*/nullptr}) {
         fStatementChildren.push_back(std::move(body));
     }
 
@@ -35,6 +36,14 @@
         return *this->functionDefinitionData().fDeclaration;
     }
 
+    bool isBuiltin() const {
+        return this->functionDefinitionData().fBuiltin;
+    }
+
+    void setBuiltin(bool builtin) {
+        this->functionDefinitionData().fBuiltin = builtin;
+    }
+
     std::unique_ptr<Statement>& body() {
         return this->fStatementChildren[0];
     }
@@ -57,7 +66,7 @@
 
     std::unique_ptr<ProgramElement> clone() const override {
         return std::make_unique<FunctionDefinition>(fOffset, &this->declaration(),
-                                                    this->body()->clone(),
+                                                    this->isBuiltin(), this->body()->clone(),
                                                     this->referencedIntrinsics());
     }
 
diff --git a/src/sksl/ir/SkSLIRNode.h b/src/sksl/ir/SkSLIRNode.h
index c98a23d..d31f94a 100644
--- a/src/sksl/ir/SkSLIRNode.h
+++ b/src/sksl/ir/SkSLIRNode.h
@@ -139,6 +139,7 @@
 
     struct FunctionDefinitionData {
         const FunctionDeclaration* fDeclaration;
+        bool fBuiltin;
         // We track intrinsic functions we reference so that we can ensure that all of them end up
         // copied into the final output.
         std::unordered_set<const FunctionDeclaration*> fReferencedIntrinsics;