Moved SkSL intrinsics from IRGenerator to Context

Moving stuff out of IRGenerator in preparation for its eventual
deletion.

Change-Id: Ib4290158670fecbca02bc71452b9bf4691094fe3
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/453943
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
Reviewed-by: John Stiles <johnstiles@google.com>
diff --git a/src/sksl/SkSLCompiler.cpp b/src/sksl/SkSLCompiler.cpp
index 4ccbbc6..d1cffda 100644
--- a/src/sksl/SkSLCompiler.cpp
+++ b/src/sksl/SkSLCompiler.cpp
@@ -16,6 +16,7 @@
 #include "src/sksl/SkSLConstantFolder.h"
 #include "src/sksl/SkSLDSLParser.h"
 #include "src/sksl/SkSLIRGenerator.h"
+#include "src/sksl/SkSLIntrinsicMap.h"
 #include "src/sksl/SkSLOperators.h"
 #include "src/sksl/SkSLProgramSettings.h"
 #include "src/sksl/SkSLRehydrator.h"
@@ -346,7 +347,7 @@
         return ParsedModule{module.fSymbols, base.fIntrinsics};
     }
 
-    auto intrinsics = std::make_shared<IRIntrinsicMap>(base.fIntrinsics.get());
+    auto intrinsics = std::make_shared<IntrinsicMap>(base.fIntrinsics.get());
 
     // Now, transfer all of the program elements to an intrinsic map. This maps certain types of
     // global objects to the declaring ProgramElement.
diff --git a/src/sksl/SkSLCompiler.h b/src/sksl/SkSLCompiler.h
index b68cf9b..124bc3b 100644
--- a/src/sksl/SkSLCompiler.h
+++ b/src/sksl/SkSLCompiler.h
@@ -46,7 +46,6 @@
 class ExternalFunction;
 class FunctionDeclaration;
 class IRGenerator;
-class IRIntrinsicMap;
 class ProgramUsage;
 
 struct LoadedModule {
diff --git a/src/sksl/SkSLContext.h b/src/sksl/SkSLContext.h
index 3284230..088c483 100644
--- a/src/sksl/SkSLContext.h
+++ b/src/sksl/SkSLContext.h
@@ -17,6 +17,7 @@
 namespace SkSL {
 
 class ErrorReporter;
+class IntrinsicMap;
 class Mangler;
 class ModifiersPool;
 struct ProgramConfig;
@@ -46,6 +47,9 @@
 
     // The Context holds a pointer to the shared name-mangler.
     Mangler* fMangler = nullptr;
+
+    // Symbols which have definitions in the include files.
+    IntrinsicMap* fIntrinsics = nullptr;
 };
 
 }  // namespace SkSL
diff --git a/src/sksl/SkSLIRGenerator.cpp b/src/sksl/SkSLIRGenerator.cpp
index e5a3d57..0b713e1 100644
--- a/src/sksl/SkSLIRGenerator.cpp
+++ b/src/sksl/SkSLIRGenerator.cpp
@@ -19,6 +19,7 @@
 #include "src/sksl/SkSLAnalysis.h"
 #include "src/sksl/SkSLCompiler.h"
 #include "src/sksl/SkSLConstantFolder.h"
+#include "src/sksl/SkSLIntrinsicMap.h"
 #include "src/sksl/SkSLOperators.h"
 #include "src/sksl/SkSLUtil.h"
 #include "src/sksl/ir/SkSLBinaryExpression.h"
@@ -225,7 +226,8 @@
         ProgramKind::kVertex == this->programKind()) {
         // ... append a line to the end of the function body which fixes up sk_Position.
         const Variable* skPerVertex = nullptr;
-        if (const ProgramElement* perVertexDecl = fIntrinsics->find(Compiler::PERVERTEX_NAME)) {
+        if (const ProgramElement* perVertexDecl =
+                fContext.fIntrinsics->find(Compiler::PERVERTEX_NAME)) {
             SkASSERT(perVertexDecl->is<SkSL::InterfaceBlock>());
             skPerVertex = &perVertexDecl->as<SkSL::InterfaceBlock>().variable();
         }
@@ -386,7 +388,8 @@
 }
 
 void IRGenerator::copyIntrinsicIfNeeded(const FunctionDeclaration& function) {
-    if (const ProgramElement* found = fIntrinsics->findAndInclude(function.description())) {
+    if (const ProgramElement* found =
+            fContext.fIntrinsics->findAndInclude(function.description())) {
         const FunctionDefinition& original = found->as<FunctionDefinition>();
 
         // Sort the referenced intrinsics into a consistent order; otherwise our output will become
@@ -421,7 +424,7 @@
         if (function.intrinsicKind() == k_dFdy_IntrinsicKind) {
             fInputs.fUseFlipRTUniform = true;
         }
-        if (!fIsBuiltinCode && fIntrinsics) {
+        if (!fIsBuiltinCode && fContext.fIntrinsics) {
             this->copyIntrinsicIfNeeded(function);
         }
     }
@@ -562,7 +565,8 @@
         void addDeclaringElement(const String& name) {
             // If this is the *first* time we've seen this builtin, findAndInclude will return
             // the corresponding ProgramElement.
-            if (const ProgramElement* decl = fGenerator->fIntrinsics->findAndInclude(name)) {
+            if (const ProgramElement* decl =
+                    fGenerator->fContext.fIntrinsics->findAndInclude(name)) {
                 SkASSERT(decl->is<GlobalVarDeclaration>() || decl->is<SkSL::InterfaceBlock>());
                 fNewElements.push_back(decl);
             }
@@ -629,10 +633,6 @@
     fProgramElements = elements;
     fSharedElements = sharedElements;
     fSymbolTable = base.fSymbols;
-    fIntrinsics = base.fIntrinsics.get();
-    if (fIntrinsics) {
-        fIntrinsics->resetAlreadyIncluded();
-    }
     fIsBuiltinCode = isBuiltinCode;
 
     fInputs = {};
@@ -694,7 +694,7 @@
 
 IRGenerator::IRBundle IRGenerator::finish() {
     // Variables defined in the pre-includes need their declaring elements added to the program
-    if (!fIsBuiltinCode && fIntrinsics) {
+    if (!fIsBuiltinCode && fContext.fIntrinsics) {
         this->findAndDeclareBuiltinVariables();
     }
 
diff --git a/src/sksl/SkSLIRGenerator.h b/src/sksl/SkSLIRGenerator.h
index eeefc17..2b20bcc 100644
--- a/src/sksl/SkSLIRGenerator.h
+++ b/src/sksl/SkSLIRGenerator.h
@@ -43,58 +43,6 @@
 struct Swizzle;
 
 /**
- * Intrinsics are passed between the Compiler and the IRGenerator using IRIntrinsicMaps.
- */
-class IRIntrinsicMap {
-public:
-    IRIntrinsicMap(IRIntrinsicMap* parent) : fParent(parent) {}
-
-    void insertOrDie(String key, std::unique_ptr<ProgramElement> element) {
-        SkASSERT(fIntrinsics.find(key) == fIntrinsics.end());
-        fIntrinsics[key] = Intrinsic{std::move(element), false};
-    }
-
-    const ProgramElement* find(const String& key) {
-        auto iter = fIntrinsics.find(key);
-        if (iter == fIntrinsics.end()) {
-            return fParent ? fParent->find(key) : nullptr;
-        }
-        return iter->second.fIntrinsic.get();
-    }
-
-    // Only returns an intrinsic that isn't already marked as included, and then marks it.
-    const ProgramElement* findAndInclude(const String& key) {
-        auto iter = fIntrinsics.find(key);
-        if (iter == fIntrinsics.end()) {
-            return fParent ? fParent->findAndInclude(key) : nullptr;
-        }
-        if (iter->second.fAlreadyIncluded) {
-            return nullptr;
-        }
-        iter->second.fAlreadyIncluded = true;
-        return iter->second.fIntrinsic.get();
-    }
-
-    void resetAlreadyIncluded() {
-        for (auto& pair : fIntrinsics) {
-            pair.second.fAlreadyIncluded = false;
-        }
-        if (fParent) {
-            fParent->resetAlreadyIncluded();
-        }
-    }
-
-private:
-    struct Intrinsic {
-        std::unique_ptr<ProgramElement> fIntrinsic;
-        bool fAlreadyIncluded = false;
-    };
-
-    std::unordered_map<String, Intrinsic> fIntrinsics;
-    IRIntrinsicMap* fParent = nullptr;
-};
-
-/**
  * Performs semantic analysis on an abstract syntax tree (AST) and produces the corresponding
  * (unoptimized) intermediate representation (IR).
  */
@@ -221,8 +169,6 @@
     Program::Inputs fInputs;
 
     std::shared_ptr<SymbolTable> fSymbolTable = nullptr;
-    // Symbols which have definitions in the include files.
-    IRIntrinsicMap* fIntrinsics = nullptr;
     std::unordered_set<const Type*> fDefinedStructs;
     std::vector<std::unique_ptr<ProgramElement>>* fProgramElements = nullptr;
     std::vector<const ProgramElement*>*           fSharedElements = nullptr;
diff --git a/src/sksl/SkSLIntrinsicMap.cpp b/src/sksl/SkSLIntrinsicMap.cpp
new file mode 100644
index 0000000..21ce474
--- /dev/null
+++ b/src/sksl/SkSLIntrinsicMap.cpp
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2020 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "include/private/SkSLProgramElement.h"
+#include "include/private/SkSLString.h"
+#include "src/sksl/SkSLIntrinsicMap.h"
+
+namespace SkSL {
+
+void IntrinsicMap::insertOrDie(String key, std::unique_ptr<ProgramElement> element) {
+    SkASSERT(fIntrinsics.find(key) == fIntrinsics.end());
+    fIntrinsics[key] = Intrinsic{std::move(element), false};
+}
+
+const ProgramElement* IntrinsicMap::find(const String& key) {
+    auto iter = fIntrinsics.find(key);
+    if (iter == fIntrinsics.end()) {
+        return fParent ? fParent->find(key) : nullptr;
+    }
+    return iter->second.fIntrinsic.get();
+}
+
+// Only returns an intrinsic that isn't already marked as included, and then marks it.
+const ProgramElement* IntrinsicMap::findAndInclude(const String& key) {
+    auto iter = fIntrinsics.find(key);
+    if (iter == fIntrinsics.end()) {
+        return fParent ? fParent->findAndInclude(key) : nullptr;
+    }
+    if (iter->second.fAlreadyIncluded) {
+        return nullptr;
+    }
+    iter->second.fAlreadyIncluded = true;
+    return iter->second.fIntrinsic.get();
+}
+
+void IntrinsicMap::resetAlreadyIncluded() {
+    for (auto& pair : fIntrinsics) {
+        pair.second.fAlreadyIncluded = false;
+    }
+    if (fParent) {
+        fParent->resetAlreadyIncluded();
+    }
+}
+
+} // namespace SkSL
diff --git a/src/sksl/SkSLIntrinsicMap.h b/src/sksl/SkSLIntrinsicMap.h
new file mode 100644
index 0000000..dc7701c
--- /dev/null
+++ b/src/sksl/SkSLIntrinsicMap.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2020 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SKSL_INTRINSICMAP
+#define SKSL_INTRINSICMAP
+
+#include <memory>
+#include <unordered_map>
+
+namespace SkSL {
+
+class ProgramElement;
+class String;
+
+/**
+ * Represents the intrinsics in the Context.
+ */
+class IntrinsicMap {
+public:
+    IntrinsicMap(IntrinsicMap* parent) : fParent(parent) {}
+
+    void insertOrDie(String key, std::unique_ptr<ProgramElement> element);
+
+    const ProgramElement* find(const String& key);
+
+    const ProgramElement* findAndInclude(const String& key);
+
+    void resetAlreadyIncluded();
+
+private:
+    struct Intrinsic {
+        std::unique_ptr<ProgramElement> fIntrinsic;
+        bool fAlreadyIncluded = false;
+    };
+
+    std::unordered_map<String, Intrinsic> fIntrinsics;
+    IntrinsicMap* fParent = nullptr;
+};
+
+} // namespace SkSL
+
+#endif
diff --git a/src/sksl/SkSLParsedModule.h b/src/sksl/SkSLParsedModule.h
index c27fdd9..7e24c5c 100644
--- a/src/sksl/SkSLParsedModule.h
+++ b/src/sksl/SkSLParsedModule.h
@@ -13,11 +13,11 @@
 namespace SkSL {
 
 class SymbolTable;
-class IRIntrinsicMap;
+class IntrinsicMap;
 
 struct ParsedModule {
-    std::shared_ptr<SymbolTable>    fSymbols;
-    std::shared_ptr<IRIntrinsicMap> fIntrinsics;
+    std::shared_ptr<SymbolTable>  fSymbols;
+    std::shared_ptr<IntrinsicMap> fIntrinsics;
 };
 
 } //namespace SkSL
diff --git a/src/sksl/dsl/priv/DSLWriter.cpp b/src/sksl/dsl/priv/DSLWriter.cpp
index 73b7f3c..a26d36a 100644
--- a/src/sksl/dsl/priv/DSLWriter.cpp
+++ b/src/sksl/dsl/priv/DSLWriter.cpp
@@ -17,6 +17,7 @@
 #endif // !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
 #include "src/sksl/SkSLCompiler.h"
 #include "src/sksl/SkSLIRGenerator.h"
+#include "src/sksl/SkSLIntrinsicMap.h"
 #include "src/sksl/ir/SkSLBinaryExpression.h"
 #include "src/sksl/ir/SkSLBlock.h"
 #include "src/sksl/ir/SkSLConstructor.h"
@@ -54,6 +55,10 @@
     fConfig->fSettings = settings;
     fCompiler->fContext->fConfig = fConfig.get();
     fCompiler->fContext->fErrors = &fDefaultErrorReporter;
+    fCompiler->fContext->fIntrinsics = module.fIntrinsics.get();
+    if (fCompiler->fContext->fIntrinsics) {
+        fCompiler->fContext->fIntrinsics->resetAlreadyIncluded();
+    }
 
     fCompiler->fIRGenerator->start(module, isModule, &fProgramElements, &fSharedElements);
 }