• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2002 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 #ifndef COMPILER_TRANSLATOR_SYMBOLTABLE_H_
8 #define COMPILER_TRANSLATOR_SYMBOLTABLE_H_
9 
10 //
11 // Symbol table for parsing.  Has these design characteristics:
12 //
13 // * Same symbol table can be used to compile many shaders, to preserve
14 //   effort of creating and loading with the large numbers of built-in
15 //   symbols.
16 //
17 // * Name mangling will be used to give each function a unique name
18 //   so that symbol table lookups are never ambiguous.  This allows
19 //   a simpler symbol table structure.
20 //
21 // * Pushing and popping of scope, so symbol table will really be a stack
22 //   of symbol tables.  Searched from the top, with new inserts going into
23 //   the top.
24 //
25 // * Constants:  Compile time constant symbols will keep their values
26 //   in the symbol table.  The parser can substitute constants at parse
27 //   time, including doing constant folding and constant propagation.
28 //
29 // * No temporaries:  Temporaries made from operations (+, --, .xy, etc.)
30 //   are tracked in the intermediate representation, not the symbol table.
31 //
32 
33 #include <limits>
34 #include <memory>
35 #include <set>
36 
37 #include "common/angleutils.h"
38 #include "compiler/translator/ExtensionBehavior.h"
39 #include "compiler/translator/ImmutableString.h"
40 #include "compiler/translator/InfoSink.h"
41 #include "compiler/translator/IntermNode.h"
42 #include "compiler/translator/Symbol.h"
43 #include "compiler/translator/SymbolTable_autogen.h"
44 
45 enum class Shader
46 {
47     ALL,
48     FRAGMENT,      // GL_FRAGMENT_SHADER
49     VERTEX,        // GL_VERTEX_SHADER
50     COMPUTE,       // GL_COMPUTE_SHADER
51     GEOMETRY,      // GL_GEOMETRY_SHADER
52     GEOMETRY_EXT,  // GL_GEOMETRY_SHADER_EXT
53     NOT_COMPUTE
54 };
55 
56 namespace sh
57 {
58 
59 struct UnmangledBuiltIn
60 {
UnmangledBuiltInUnmangledBuiltIn61     constexpr UnmangledBuiltIn(TExtension extension) : extension(extension) {}
62 
63     TExtension extension;
64 };
65 
66 using VarPointer        = TSymbol *(TSymbolTableBase::*);
67 using ValidateExtension = int ShBuiltInResources::*;
68 
69 enum class Spec
70 {
71     GLSL,
72     ESSL
73 };
74 
75 constexpr uint16_t kESSL1Only = 100;
76 
77 static_assert(offsetof(ShBuiltInResources, OES_standard_derivatives) != 0,
78               "Update SymbolTable extension logic");
79 
80 #define EXT_INDEX(Ext) (offsetof(ShBuiltInResources, Ext) / sizeof(int))
81 
82 class SymbolRule
83 {
84   public:
85     const TSymbol *get(ShShaderSpec shaderSpec,
86                        int shaderVersion,
87                        sh::GLenum shaderType,
88                        const ShBuiltInResources &resources,
89                        const TSymbolTableBase &symbolTable) const;
90 
91     template <Spec spec, int version, Shader shaders, size_t extensionIndex, typename T>
92     constexpr static SymbolRule Get(T value);
93 
94   private:
95     constexpr SymbolRule(Spec spec,
96                          int version,
97                          Shader shaders,
98                          size_t extensionIndex,
99                          const TSymbol *symbol);
100 
101     constexpr SymbolRule(Spec spec,
102                          int version,
103                          Shader shaders,
104                          size_t extensionIndex,
105                          VarPointer resourceVar);
106 
107     union SymbolOrVar
108     {
SymbolOrVar(const TSymbol * symbolIn)109         constexpr SymbolOrVar(const TSymbol *symbolIn) : symbol(symbolIn) {}
SymbolOrVar(VarPointer varIn)110         constexpr SymbolOrVar(VarPointer varIn) : var(varIn) {}
111 
112         const TSymbol *symbol;
113         VarPointer var;
114     };
115 
116     uint16_t mIsDesktop : 1;
117     uint16_t mIsVar : 1;
118     uint16_t mVersion : 14;
119     uint8_t mShaders;
120     uint8_t mExtensionIndex;
121     SymbolOrVar mSymbolOrVar;
122 };
123 
SymbolRule(Spec spec,int version,Shader shaders,size_t extensionIndex,const TSymbol * symbol)124 constexpr SymbolRule::SymbolRule(Spec spec,
125                                  int version,
126                                  Shader shaders,
127                                  size_t extensionIndex,
128                                  const TSymbol *symbol)
129     : mIsDesktop(spec == Spec::GLSL ? 1u : 0u),
130       mIsVar(0u),
131       mVersion(static_cast<uint16_t>(version)),
132       mShaders(static_cast<uint8_t>(shaders)),
133       mExtensionIndex(extensionIndex),
134       mSymbolOrVar(symbol)
135 {}
136 
SymbolRule(Spec spec,int version,Shader shaders,size_t extensionIndex,VarPointer resourceVar)137 constexpr SymbolRule::SymbolRule(Spec spec,
138                                  int version,
139                                  Shader shaders,
140                                  size_t extensionIndex,
141                                  VarPointer resourceVar)
142     : mIsDesktop(spec == Spec::GLSL ? 1u : 0u),
143       mIsVar(1u),
144       mVersion(static_cast<uint16_t>(version)),
145       mShaders(static_cast<uint8_t>(shaders)),
146       mExtensionIndex(extensionIndex),
147       mSymbolOrVar(resourceVar)
148 {}
149 
150 template <Spec spec, int version, Shader shaders, size_t extensionIndex, typename T>
151 // static
Get(T value)152 constexpr SymbolRule SymbolRule::Get(T value)
153 {
154     static_assert(version < 0x4000u, "version OOR");
155     static_assert(static_cast<uint8_t>(shaders) < 0xFFu, "shaders OOR");
156     static_assert(static_cast<uint8_t>(extensionIndex) < 0xFF, "extensionIndex OOR");
157     return SymbolRule(spec, version, shaders, extensionIndex, value);
158 }
159 
160 const TSymbol *FindMangledBuiltIn(ShShaderSpec shaderSpec,
161                                   int shaderVersion,
162                                   sh::GLenum shaderType,
163                                   const ShBuiltInResources &resources,
164                                   const TSymbolTableBase &symbolTable,
165                                   const SymbolRule *rules,
166                                   uint16_t startIndex,
167                                   uint16_t endIndex);
168 
169 class UnmangledEntry
170 {
171   public:
172     constexpr UnmangledEntry(const char *name,
173                              TExtension esslExtension,
174                              TExtension glslExtension,
175                              int esslVersion,
176                              int glslVersion,
177                              Shader shaderType);
178 
179     bool matches(const ImmutableString &name,
180                  ShShaderSpec shaderSpec,
181                  int shaderVersion,
182                  sh::GLenum shaderType,
183                  const TExtensionBehavior &extensions) const;
184 
185   private:
186     const char *mName;
187     uint8_t mESSLExtension;
188     uint8_t mGLSLExtension;
189     uint8_t mShaderType;
190     uint16_t mESSLVersion;
191     uint16_t mGLSLVersion;
192 };
193 
UnmangledEntry(const char * name,TExtension esslExtension,TExtension glslExtension,int esslVersion,int glslVersion,Shader shaderType)194 constexpr UnmangledEntry::UnmangledEntry(const char *name,
195                                          TExtension esslExtension,
196                                          TExtension glslExtension,
197                                          int esslVersion,
198                                          int glslVersion,
199                                          Shader shaderType)
200     : mName(name),
201       mESSLExtension(static_cast<uint8_t>(esslExtension)),
202       mGLSLExtension(static_cast<uint8_t>(glslExtension)),
203       mShaderType(static_cast<uint8_t>(shaderType)),
204       mESSLVersion(esslVersion < 0 ? std::numeric_limits<uint16_t>::max()
205                                    : static_cast<uint16_t>(esslVersion)),
206       mGLSLVersion(glslVersion < 0 ? std::numeric_limits<uint16_t>::max()
207                                    : static_cast<uint16_t>(glslVersion))
208 {}
209 
210 class TSymbolTable : angle::NonCopyable, TSymbolTableBase
211 {
212   public:
213     TSymbolTable();
214     // To start using the symbol table after construction:
215     // * initializeBuiltIns() needs to be called.
216     // * push() needs to be called to push the global level.
217 
218     ~TSymbolTable();
219 
220     bool isEmpty() const;
221     bool atGlobalLevel() const;
222 
223     void push();
224     void pop();
225 
226     // Declare a non-function symbol at the current scope. Return true in case the declaration was
227     // successful, and false if the declaration failed due to redefinition.
228     bool declare(TSymbol *symbol);
229 
230     // Only used to declare internal variables.
231     bool declareInternal(TSymbol *symbol);
232 
233     // Functions are always declared at global scope.
234     void declareUserDefinedFunction(TFunction *function, bool insertUnmangledName);
235 
236     // These return the TFunction pointer to keep using to refer to this function.
237     const TFunction *markFunctionHasPrototypeDeclaration(const ImmutableString &mangledName,
238                                                          bool *hadPrototypeDeclarationOut) const;
239     const TFunction *setFunctionParameterNamesFromDefinition(const TFunction *function,
240                                                              bool *wasDefinedOut) const;
241 
242     // Return false if the gl_in array size has already been initialized with a mismatching value.
243     bool setGlInArraySize(unsigned int inputArraySize);
244     TVariable *getGlInVariableWithArraySize() const;
245 
246     const TVariable *gl_FragData() const;
247     const TVariable *gl_SecondaryFragDataEXT() const;
248 
249     void markStaticRead(const TVariable &variable);
250     void markStaticWrite(const TVariable &variable);
251 
252     // Note: Should not call this for constant variables.
253     bool isStaticallyUsed(const TVariable &variable) const;
254 
255     // find() is guaranteed not to retain a reference to the ImmutableString, so an ImmutableString
256     // with a reference to a short-lived char * is fine to pass here.
257     const TSymbol *find(const ImmutableString &name, int shaderVersion) const;
258 
259     const TSymbol *findUserDefined(const ImmutableString &name) const;
260 
261     TFunction *findUserDefinedFunction(const ImmutableString &name) const;
262 
263     const TSymbol *findGlobal(const ImmutableString &name) const;
264     const TSymbol *findGlobalWithConversion(const std::vector<ImmutableString> &names) const;
265 
266     const TSymbol *findBuiltIn(const ImmutableString &name, int shaderVersion) const;
267     const TSymbol *findBuiltInWithConversion(const std::vector<ImmutableString> &names,
268                                              int shaderVersion) const;
269 
270     void setDefaultPrecision(TBasicType type, TPrecision prec);
271 
272     // Searches down the precisionStack for a precision qualifier
273     // for the specified TBasicType
274     TPrecision getDefaultPrecision(TBasicType type) const;
275 
276     // This records invariant varyings declared through "invariant varying_name;".
277     void addInvariantVarying(const TVariable &variable);
278 
279     // If this returns false, the varying could still be invariant if it is set as invariant during
280     // the varying variable declaration - this piece of information is stored in the variable's
281     // type, not here.
282     bool isVaryingInvariant(const TVariable &variable) const;
283 
284     void setGlobalInvariant(bool invariant);
285 
nextUniqueId()286     const TSymbolUniqueId nextUniqueId() { return TSymbolUniqueId(this); }
287 
288     // Gets the built-in accessible by a shader with the specified version, if any.
289     bool isUnmangledBuiltInName(const ImmutableString &name,
290                                 int shaderVersion,
291                                 const TExtensionBehavior &extensions) const;
292 
293     void initializeBuiltIns(sh::GLenum type,
294                             ShShaderSpec spec,
295                             const ShBuiltInResources &resources);
296     void clearCompilationResults();
297 
298   private:
299     friend class TSymbolUniqueId;
300 
301     struct VariableMetadata
302     {
303         VariableMetadata();
304         bool staticRead;
305         bool staticWrite;
306         bool invariant;
307     };
308 
309     int nextUniqueIdValue();
310 
311     class TSymbolTableLevel;
312 
313     void initSamplerDefaultPrecision(TBasicType samplerType);
314 
315     void initializeBuiltInVariables(sh::GLenum shaderType,
316                                     ShShaderSpec spec,
317                                     const ShBuiltInResources &resources);
318 
319     VariableMetadata *getOrCreateVariableMetadata(const TVariable &variable);
320 
321     std::vector<std::unique_ptr<TSymbolTableLevel>> mTable;
322 
323     // There's one precision stack level for predefined precisions and then one level for each scope
324     // in table.
325     typedef TMap<TBasicType, TPrecision> PrecisionStackLevel;
326     std::vector<std::unique_ptr<PrecisionStackLevel>> mPrecisionStack;
327 
328     bool mGlobalInvariant;
329 
330     int mUniqueIdCounter;
331 
332     static const int kLastBuiltInId;
333 
334     sh::GLenum mShaderType;
335     ShShaderSpec mShaderSpec;
336     ShBuiltInResources mResources;
337 
338     // Indexed by unique id. Map instead of vector since the variables are fairly sparse.
339     std::map<int, VariableMetadata> mVariableMetadata;
340 
341     // Store gl_in variable with its array size once the array size can be determined. The array
342     // size can also be checked against latter input primitive type declaration.
343     TVariable *mGlInVariableWithArraySize;
344 };
345 
346 }  // namespace sh
347 
348 #endif  // COMPILER_TRANSLATOR_SYMBOLTABLE_H_
349