xref: /aosp_15_r20/external/skia/src/sksl/ir/SkSLSymbolTable.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2016 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker  *
4*c8dee2aaSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker  * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker  */
7*c8dee2aaSAndroid Build Coastguard Worker 
8*c8dee2aaSAndroid Build Coastguard Worker #ifndef SKSL_SYMBOLTABLE
9*c8dee2aaSAndroid Build Coastguard Worker #define SKSL_SYMBOLTABLE
10*c8dee2aaSAndroid Build Coastguard Worker 
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypes.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkChecksum.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkTHash.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "src/sksl/ir/SkSLSymbol.h"
15*c8dee2aaSAndroid Build Coastguard Worker 
16*c8dee2aaSAndroid Build Coastguard Worker #include <cstddef>
17*c8dee2aaSAndroid Build Coastguard Worker #include <cstdint>
18*c8dee2aaSAndroid Build Coastguard Worker #include <forward_list>
19*c8dee2aaSAndroid Build Coastguard Worker #include <memory>
20*c8dee2aaSAndroid Build Coastguard Worker #include <string>
21*c8dee2aaSAndroid Build Coastguard Worker #include <string_view>
22*c8dee2aaSAndroid Build Coastguard Worker #include <utility>
23*c8dee2aaSAndroid Build Coastguard Worker #include <vector>
24*c8dee2aaSAndroid Build Coastguard Worker 
25*c8dee2aaSAndroid Build Coastguard Worker namespace SkSL {
26*c8dee2aaSAndroid Build Coastguard Worker 
27*c8dee2aaSAndroid Build Coastguard Worker class Context;
28*c8dee2aaSAndroid Build Coastguard Worker class Expression;
29*c8dee2aaSAndroid Build Coastguard Worker class Position;
30*c8dee2aaSAndroid Build Coastguard Worker class Type;
31*c8dee2aaSAndroid Build Coastguard Worker 
32*c8dee2aaSAndroid Build Coastguard Worker /**
33*c8dee2aaSAndroid Build Coastguard Worker  * Maps identifiers to symbols.
34*c8dee2aaSAndroid Build Coastguard Worker  */
35*c8dee2aaSAndroid Build Coastguard Worker class SymbolTable {
36*c8dee2aaSAndroid Build Coastguard Worker public:
SymbolTable(bool builtin)37*c8dee2aaSAndroid Build Coastguard Worker     explicit SymbolTable(bool builtin)
38*c8dee2aaSAndroid Build Coastguard Worker             : fBuiltin(builtin) {}
39*c8dee2aaSAndroid Build Coastguard Worker 
SymbolTable(SymbolTable * parent,bool builtin)40*c8dee2aaSAndroid Build Coastguard Worker     explicit SymbolTable(SymbolTable* parent, bool builtin)
41*c8dee2aaSAndroid Build Coastguard Worker             : fParent(parent)
42*c8dee2aaSAndroid Build Coastguard Worker             , fBuiltin(builtin) {}
43*c8dee2aaSAndroid Build Coastguard Worker 
44*c8dee2aaSAndroid Build Coastguard Worker     /**
45*c8dee2aaSAndroid Build Coastguard Worker      * Creates a new, empty SymbolTable between this SymbolTable and its current parent.
46*c8dee2aaSAndroid Build Coastguard Worker      * The new symbol table is returned, and is also accessible as `this->fParent`.
47*c8dee2aaSAndroid Build Coastguard Worker      * The original parent is accessible as `this->fParent->fParent`.
48*c8dee2aaSAndroid Build Coastguard Worker      */
49*c8dee2aaSAndroid Build Coastguard Worker     std::unique_ptr<SymbolTable> insertNewParent();
50*c8dee2aaSAndroid Build Coastguard Worker 
51*c8dee2aaSAndroid Build Coastguard Worker     /**
52*c8dee2aaSAndroid Build Coastguard Worker      * Looks up the requested symbol and returns a const pointer.
53*c8dee2aaSAndroid Build Coastguard Worker      */
find(std::string_view name)54*c8dee2aaSAndroid Build Coastguard Worker     const Symbol* find(std::string_view name) const {
55*c8dee2aaSAndroid Build Coastguard Worker         return this->lookup(MakeSymbolKey(name));
56*c8dee2aaSAndroid Build Coastguard Worker     }
57*c8dee2aaSAndroid Build Coastguard Worker 
58*c8dee2aaSAndroid Build Coastguard Worker     /**
59*c8dee2aaSAndroid Build Coastguard Worker      * Looks up the requested symbol, only searching the built-in symbol tables. Always const.
60*c8dee2aaSAndroid Build Coastguard Worker      */
61*c8dee2aaSAndroid Build Coastguard Worker     const Symbol* findBuiltinSymbol(std::string_view name) const;
62*c8dee2aaSAndroid Build Coastguard Worker 
63*c8dee2aaSAndroid Build Coastguard Worker     /**
64*c8dee2aaSAndroid Build Coastguard Worker      * Looks up the requested symbol and returns a mutable pointer. Use caution--mutating a symbol
65*c8dee2aaSAndroid Build Coastguard Worker      * will have program-wide impact, and built-in symbol tables must never be mutated.
66*c8dee2aaSAndroid Build Coastguard Worker      */
findMutable(std::string_view name)67*c8dee2aaSAndroid Build Coastguard Worker     Symbol* findMutable(std::string_view name) const {
68*c8dee2aaSAndroid Build Coastguard Worker         return this->lookup(MakeSymbolKey(name));
69*c8dee2aaSAndroid Build Coastguard Worker     }
70*c8dee2aaSAndroid Build Coastguard Worker 
71*c8dee2aaSAndroid Build Coastguard Worker     /**
72*c8dee2aaSAndroid Build Coastguard Worker      * Looks up the requested symbol and instantiates an Expression reference to it; will return a
73*c8dee2aaSAndroid Build Coastguard Worker      * VariableReference, TypeReference, FunctionReference, FieldAccess, or nullptr.
74*c8dee2aaSAndroid Build Coastguard Worker      */
75*c8dee2aaSAndroid Build Coastguard Worker     std::unique_ptr<Expression> instantiateSymbolRef(const Context& context,
76*c8dee2aaSAndroid Build Coastguard Worker                                                      std::string_view name,
77*c8dee2aaSAndroid Build Coastguard Worker                                                      Position pos);
78*c8dee2aaSAndroid Build Coastguard Worker 
79*c8dee2aaSAndroid Build Coastguard Worker     /**
80*c8dee2aaSAndroid Build Coastguard Worker      * Assigns a new name to the passed-in symbol. The old name will continue to exist in the symbol
81*c8dee2aaSAndroid Build Coastguard Worker      * table and point to the symbol.
82*c8dee2aaSAndroid Build Coastguard Worker      */
83*c8dee2aaSAndroid Build Coastguard Worker     void renameSymbol(const Context& context, Symbol* symbol, std::string_view newName);
84*c8dee2aaSAndroid Build Coastguard Worker 
85*c8dee2aaSAndroid Build Coastguard Worker     /**
86*c8dee2aaSAndroid Build Coastguard Worker      * Removes a symbol from the symbol table. If this symbol table had ownership of the symbol, the
87*c8dee2aaSAndroid Build Coastguard Worker      * symbol is returned (and can be deleted or reinserted as desired); if not, null is returned.
88*c8dee2aaSAndroid Build Coastguard Worker      * In either event, the name will no longer correspond to the symbol.
89*c8dee2aaSAndroid Build Coastguard Worker      */
90*c8dee2aaSAndroid Build Coastguard Worker     std::unique_ptr<Symbol> removeSymbol(const Symbol* symbol);
91*c8dee2aaSAndroid Build Coastguard Worker 
92*c8dee2aaSAndroid Build Coastguard Worker     /**
93*c8dee2aaSAndroid Build Coastguard Worker      * Moves a symbol from this symbol table to another one. If this symbol table had ownership of
94*c8dee2aaSAndroid Build Coastguard Worker      * the symbol, the ownership will be transferred as well. (If the symbol does not actually exist
95*c8dee2aaSAndroid Build Coastguard Worker      * in this table at all, it will still be added to the other table.)
96*c8dee2aaSAndroid Build Coastguard Worker      */
97*c8dee2aaSAndroid Build Coastguard Worker     void moveSymbolTo(SymbolTable* otherTable, Symbol* sym, const Context& context);
98*c8dee2aaSAndroid Build Coastguard Worker 
99*c8dee2aaSAndroid Build Coastguard Worker     /**
100*c8dee2aaSAndroid Build Coastguard Worker      * Returns true if the name refers to a type (user or built-in) in the current symbol table.
101*c8dee2aaSAndroid Build Coastguard Worker      */
102*c8dee2aaSAndroid Build Coastguard Worker     bool isType(std::string_view name) const;
103*c8dee2aaSAndroid Build Coastguard Worker 
104*c8dee2aaSAndroid Build Coastguard Worker     /**
105*c8dee2aaSAndroid Build Coastguard Worker      * Returns true if the name refers to a builtin type.
106*c8dee2aaSAndroid Build Coastguard Worker      */
107*c8dee2aaSAndroid Build Coastguard Worker     bool isBuiltinType(std::string_view name) const;
108*c8dee2aaSAndroid Build Coastguard Worker 
109*c8dee2aaSAndroid Build Coastguard Worker     /**
110*c8dee2aaSAndroid Build Coastguard Worker      * Adds a symbol to this symbol table, without conferring ownership. The caller is responsible
111*c8dee2aaSAndroid Build Coastguard Worker      * for keeping the Symbol alive throughout the lifetime of the program/module.
112*c8dee2aaSAndroid Build Coastguard Worker      */
113*c8dee2aaSAndroid Build Coastguard Worker     void addWithoutOwnershipOrDie(Symbol* symbol);
114*c8dee2aaSAndroid Build Coastguard Worker     void addWithoutOwnership(const Context& context, Symbol* symbol);
115*c8dee2aaSAndroid Build Coastguard Worker 
116*c8dee2aaSAndroid Build Coastguard Worker     /**
117*c8dee2aaSAndroid Build Coastguard Worker      * Adds a symbol to this symbol table, conferring ownership. The symbol table will always be
118*c8dee2aaSAndroid Build Coastguard Worker      * updated to reference the new symbol. If the symbol already exists, an error will be reported.
119*c8dee2aaSAndroid Build Coastguard Worker      */
120*c8dee2aaSAndroid Build Coastguard Worker     template <typename T>
add(const Context & context,std::unique_ptr<T> symbol)121*c8dee2aaSAndroid Build Coastguard Worker     T* add(const Context& context, std::unique_ptr<T> symbol) {
122*c8dee2aaSAndroid Build Coastguard Worker         T* ptr = symbol.get();
123*c8dee2aaSAndroid Build Coastguard Worker         this->addWithoutOwnership(context, this->takeOwnershipOfSymbol(std::move(symbol)));
124*c8dee2aaSAndroid Build Coastguard Worker         return ptr;
125*c8dee2aaSAndroid Build Coastguard Worker     }
126*c8dee2aaSAndroid Build Coastguard Worker 
127*c8dee2aaSAndroid Build Coastguard Worker     /**
128*c8dee2aaSAndroid Build Coastguard Worker      * Adds a symbol to this symbol table, conferring ownership. The symbol table will always be
129*c8dee2aaSAndroid Build Coastguard Worker      * updated to reference the new symbol. If the symbol already exists, abort.
130*c8dee2aaSAndroid Build Coastguard Worker      */
131*c8dee2aaSAndroid Build Coastguard Worker     template <typename T>
addOrDie(std::unique_ptr<T> symbol)132*c8dee2aaSAndroid Build Coastguard Worker     T* addOrDie(std::unique_ptr<T> symbol) {
133*c8dee2aaSAndroid Build Coastguard Worker         T* ptr = symbol.get();
134*c8dee2aaSAndroid Build Coastguard Worker         this->addWithoutOwnershipOrDie(this->takeOwnershipOfSymbol(std::move(symbol)));
135*c8dee2aaSAndroid Build Coastguard Worker         return ptr;
136*c8dee2aaSAndroid Build Coastguard Worker     }
137*c8dee2aaSAndroid Build Coastguard Worker 
138*c8dee2aaSAndroid Build Coastguard Worker     /**
139*c8dee2aaSAndroid Build Coastguard Worker      * Forces a symbol into this symbol table, without conferring ownership. Replaces any existing
140*c8dee2aaSAndroid Build Coastguard Worker      * symbol with the same name, if one exists.
141*c8dee2aaSAndroid Build Coastguard Worker      */
142*c8dee2aaSAndroid Build Coastguard Worker     void injectWithoutOwnership(Symbol* symbol);
143*c8dee2aaSAndroid Build Coastguard Worker 
144*c8dee2aaSAndroid Build Coastguard Worker     /**
145*c8dee2aaSAndroid Build Coastguard Worker      * Forces a symbol into this symbol table, conferring ownership. Replaces any existing symbol
146*c8dee2aaSAndroid Build Coastguard Worker      * with the same name, if one exists.
147*c8dee2aaSAndroid Build Coastguard Worker      */
148*c8dee2aaSAndroid Build Coastguard Worker     template <typename T>
inject(std::unique_ptr<T> symbol)149*c8dee2aaSAndroid Build Coastguard Worker     T* inject(std::unique_ptr<T> symbol) {
150*c8dee2aaSAndroid Build Coastguard Worker         T* ptr = symbol.get();
151*c8dee2aaSAndroid Build Coastguard Worker         this->injectWithoutOwnership(this->takeOwnershipOfSymbol(std::move(symbol)));
152*c8dee2aaSAndroid Build Coastguard Worker         return ptr;
153*c8dee2aaSAndroid Build Coastguard Worker     }
154*c8dee2aaSAndroid Build Coastguard Worker 
155*c8dee2aaSAndroid Build Coastguard Worker     /**
156*c8dee2aaSAndroid Build Coastguard Worker      * Confers ownership of a symbol without adding its name to the lookup table.
157*c8dee2aaSAndroid Build Coastguard Worker      */
158*c8dee2aaSAndroid Build Coastguard Worker     template <typename T>
takeOwnershipOfSymbol(std::unique_ptr<T> symbol)159*c8dee2aaSAndroid Build Coastguard Worker     T* takeOwnershipOfSymbol(std::unique_ptr<T> symbol) {
160*c8dee2aaSAndroid Build Coastguard Worker         T* ptr = symbol.get();
161*c8dee2aaSAndroid Build Coastguard Worker         fOwnedSymbols.push_back(std::move(symbol));
162*c8dee2aaSAndroid Build Coastguard Worker         return ptr;
163*c8dee2aaSAndroid Build Coastguard Worker     }
164*c8dee2aaSAndroid Build Coastguard Worker 
165*c8dee2aaSAndroid Build Coastguard Worker     /**
166*c8dee2aaSAndroid Build Coastguard Worker      * Given type = `float` and arraySize = 5, creates the array type `float[5]` in the symbol
167*c8dee2aaSAndroid Build Coastguard Worker      * table. The created array type is returned. If zero is passed, the base type is returned
168*c8dee2aaSAndroid Build Coastguard Worker      * unchanged.
169*c8dee2aaSAndroid Build Coastguard Worker      */
170*c8dee2aaSAndroid Build Coastguard Worker     const Type* addArrayDimension(const Context& context, const Type* type, int arraySize);
171*c8dee2aaSAndroid Build Coastguard Worker 
172*c8dee2aaSAndroid Build Coastguard Worker     // Call fn for every symbol in the table. You may not mutate anything.
173*c8dee2aaSAndroid Build Coastguard Worker     template <typename Fn>
foreach(Fn && fn)174*c8dee2aaSAndroid Build Coastguard Worker     void foreach(Fn&& fn) const {
175*c8dee2aaSAndroid Build Coastguard Worker         fSymbols.foreach(
176*c8dee2aaSAndroid Build Coastguard Worker                 [&fn](const SymbolKey& key, const Symbol* symbol) { fn(key.fName, symbol); });
177*c8dee2aaSAndroid Build Coastguard Worker     }
178*c8dee2aaSAndroid Build Coastguard Worker 
179*c8dee2aaSAndroid Build Coastguard Worker     // Checks `this` directly against `other` to see if the two symbol tables have any names in
180*c8dee2aaSAndroid Build Coastguard Worker     // common. Parent tables are not considered.
181*c8dee2aaSAndroid Build Coastguard Worker     bool wouldShadowSymbolsFrom(const SymbolTable* other) const;
182*c8dee2aaSAndroid Build Coastguard Worker 
count()183*c8dee2aaSAndroid Build Coastguard Worker     size_t count() const {
184*c8dee2aaSAndroid Build Coastguard Worker         return fSymbols.count();
185*c8dee2aaSAndroid Build Coastguard Worker     }
186*c8dee2aaSAndroid Build Coastguard Worker 
187*c8dee2aaSAndroid Build Coastguard Worker     /** Returns true if this is a built-in SymbolTable. */
isBuiltin()188*c8dee2aaSAndroid Build Coastguard Worker     bool isBuiltin() const {
189*c8dee2aaSAndroid Build Coastguard Worker         return fBuiltin;
190*c8dee2aaSAndroid Build Coastguard Worker     }
191*c8dee2aaSAndroid Build Coastguard Worker 
192*c8dee2aaSAndroid Build Coastguard Worker     const std::string* takeOwnershipOfString(std::string n);
193*c8dee2aaSAndroid Build Coastguard Worker 
194*c8dee2aaSAndroid Build Coastguard Worker     /**
195*c8dee2aaSAndroid Build Coastguard Worker      * Indicates that this symbol table's parent is in a different module than this one.
196*c8dee2aaSAndroid Build Coastguard Worker      */
markModuleBoundary()197*c8dee2aaSAndroid Build Coastguard Worker     void markModuleBoundary() {
198*c8dee2aaSAndroid Build Coastguard Worker         fAtModuleBoundary = true;
199*c8dee2aaSAndroid Build Coastguard Worker     }
200*c8dee2aaSAndroid Build Coastguard Worker 
201*c8dee2aaSAndroid Build Coastguard Worker     SymbolTable* fParent = nullptr;
202*c8dee2aaSAndroid Build Coastguard Worker 
203*c8dee2aaSAndroid Build Coastguard Worker     std::vector<std::unique_ptr<Symbol>> fOwnedSymbols;
204*c8dee2aaSAndroid Build Coastguard Worker 
205*c8dee2aaSAndroid Build Coastguard Worker private:
206*c8dee2aaSAndroid Build Coastguard Worker     struct SymbolKey {
207*c8dee2aaSAndroid Build Coastguard Worker         std::string_view fName;
208*c8dee2aaSAndroid Build Coastguard Worker         uint32_t         fHash;
209*c8dee2aaSAndroid Build Coastguard Worker 
210*c8dee2aaSAndroid Build Coastguard Worker         bool operator==(const SymbolKey& that) const { return fName == that.fName; }
211*c8dee2aaSAndroid Build Coastguard Worker         bool operator!=(const SymbolKey& that) const { return fName != that.fName; }
212*c8dee2aaSAndroid Build Coastguard Worker         struct Hash {
operatorSymbolKey::Hash213*c8dee2aaSAndroid Build Coastguard Worker             uint32_t operator()(const SymbolKey& key) const { return key.fHash; }
214*c8dee2aaSAndroid Build Coastguard Worker         };
215*c8dee2aaSAndroid Build Coastguard Worker     };
216*c8dee2aaSAndroid Build Coastguard Worker 
MakeSymbolKey(std::string_view name)217*c8dee2aaSAndroid Build Coastguard Worker     static SymbolKey MakeSymbolKey(std::string_view name) {
218*c8dee2aaSAndroid Build Coastguard Worker         return SymbolKey{name, SkChecksum::Hash32(name.data(), name.size())};
219*c8dee2aaSAndroid Build Coastguard Worker     }
220*c8dee2aaSAndroid Build Coastguard Worker 
221*c8dee2aaSAndroid Build Coastguard Worker     Symbol* lookup(const SymbolKey& key) const;
222*c8dee2aaSAndroid Build Coastguard Worker     bool addWithoutOwnership(Symbol* symbol);
223*c8dee2aaSAndroid Build Coastguard Worker 
224*c8dee2aaSAndroid Build Coastguard Worker     bool fBuiltin = false;
225*c8dee2aaSAndroid Build Coastguard Worker     bool fAtModuleBoundary = false;
226*c8dee2aaSAndroid Build Coastguard Worker     std::forward_list<std::string> fOwnedStrings;
227*c8dee2aaSAndroid Build Coastguard Worker     skia_private::THashMap<SymbolKey, Symbol*, SymbolKey::Hash> fSymbols;
228*c8dee2aaSAndroid Build Coastguard Worker };
229*c8dee2aaSAndroid Build Coastguard Worker 
230*c8dee2aaSAndroid Build Coastguard Worker }  // namespace SkSL
231*c8dee2aaSAndroid Build Coastguard Worker 
232*c8dee2aaSAndroid Build Coastguard Worker #endif
233