• 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 : uint8_t
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     TESS_CONTROL_EXT,     // GL_TESS_CONTROL_SHADER_EXT
54     TESS_EVALUATION_EXT,  // GL_TESS_EVALUATION_SHADER_EXT
55     NOT_COMPUTE
56 };
57 
58 namespace sh
59 {
60 
61 struct UnmangledBuiltIn
62 {
UnmangledBuiltInUnmangledBuiltIn63     constexpr UnmangledBuiltIn(TExtension extension) : extension(extension) {}
64 
65     TExtension extension;
66 };
67 
68 using VarPointer        = TSymbol *(TSymbolTableBase::*);
69 using ValidateExtension = int ShBuiltInResources::*;
70 
71 enum class Spec : uint8_t
72 {
73     GLSL,
74     ESSL
75 };
76 
77 constexpr uint16_t kESSL1Only = 100;
78 // Some built-ins from backend shader languages are made available internally to ESSL for use in
79 // tree transformations.  This (invalid) shader version is used to select those built-ins.  This
80 // value needs to be larger than all other shader versions.
81 constexpr uint16_t kESSLInternalBackendBuiltIns = 0x3FFF;
82 
83 // The version assigned to |kESSLInternalBackendBuiltIns| should be good until OpenGL 20.0!
84 static_assert(kESSLInternalBackendBuiltIns > 2000,
85               "Accidentally exposing internal backend built-ins in OpenGL");
86 
87 static_assert(offsetof(ShBuiltInResources, OES_standard_derivatives) != 0,
88               "Update SymbolTable extension logic");
89 
90 #define EXT_INDEX(Ext) (offsetof(ShBuiltInResources, Ext) / sizeof(int))
91 
92 class SymbolRule
93 {
94   public:
95     const TSymbol *get(ShShaderSpec shaderSpec,
96                        int shaderVersion,
97                        sh::GLenum shaderType,
98                        const ShBuiltInResources &resources,
99                        const TSymbolTableBase &symbolTable) const;
100 
101     template <Spec spec, int version, Shader shaders, size_t extensionIndex, typename T>
102     constexpr static SymbolRule Get(T value);
103 
104   private:
105     constexpr SymbolRule(Spec spec,
106                          int version,
107                          Shader shaders,
108                          size_t extensionIndex,
109                          const TSymbol *symbol);
110 
111     constexpr SymbolRule(Spec spec,
112                          int version,
113                          Shader shaders,
114                          size_t extensionIndex,
115                          VarPointer resourceVar);
116 
117     union SymbolOrVar
118     {
SymbolOrVar(const TSymbol * symbolIn)119         constexpr SymbolOrVar(const TSymbol *symbolIn) : symbol(symbolIn) {}
SymbolOrVar(VarPointer varIn)120         constexpr SymbolOrVar(VarPointer varIn) : var(varIn) {}
121 
122         const TSymbol *symbol;
123         VarPointer var;
124     };
125 
126     uint16_t mIsDesktop : 1;
127     uint16_t mIsVar : 1;
128     uint16_t mVersion : 14;
129     uint8_t mShaders;
130     uint8_t mExtensionIndex;
131     SymbolOrVar mSymbolOrVar;
132 };
133 
SymbolRule(Spec spec,int version,Shader shaders,size_t extensionIndex,const TSymbol * symbol)134 constexpr SymbolRule::SymbolRule(Spec spec,
135                                  int version,
136                                  Shader shaders,
137                                  size_t extensionIndex,
138                                  const TSymbol *symbol)
139     : mIsDesktop(spec == Spec::GLSL ? 1u : 0u),
140       mIsVar(0u),
141       mVersion(static_cast<uint16_t>(version)),
142       mShaders(static_cast<uint8_t>(shaders)),
143       mExtensionIndex(extensionIndex),
144       mSymbolOrVar(symbol)
145 {}
146 
SymbolRule(Spec spec,int version,Shader shaders,size_t extensionIndex,VarPointer resourceVar)147 constexpr SymbolRule::SymbolRule(Spec spec,
148                                  int version,
149                                  Shader shaders,
150                                  size_t extensionIndex,
151                                  VarPointer resourceVar)
152     : mIsDesktop(spec == Spec::GLSL ? 1u : 0u),
153       mIsVar(1u),
154       mVersion(static_cast<uint16_t>(version)),
155       mShaders(static_cast<uint8_t>(shaders)),
156       mExtensionIndex(extensionIndex),
157       mSymbolOrVar(resourceVar)
158 {}
159 
160 template <Spec spec, int version, Shader shaders, size_t extensionIndex, typename T>
161 // static
Get(T value)162 constexpr SymbolRule SymbolRule::Get(T value)
163 {
164     static_assert(version < 0x4000u, "version OOR");
165     static_assert(static_cast<uint8_t>(shaders) < 0xFFu, "shaders OOR");
166     static_assert(static_cast<uint8_t>(extensionIndex) < 0xFF, "extensionIndex OOR");
167     return SymbolRule(spec, version, shaders, extensionIndex, value);
168 }
169 
170 const TSymbol *FindMangledBuiltIn(ShShaderSpec shaderSpec,
171                                   int shaderVersion,
172                                   sh::GLenum shaderType,
173                                   const ShBuiltInResources &resources,
174                                   const TSymbolTableBase &symbolTable,
175                                   const SymbolRule *rules,
176                                   uint16_t startIndex,
177                                   uint16_t endIndex);
178 
179 class UnmangledEntry
180 {
181   public:
182     template <size_t ESSLExtCount>
183     constexpr UnmangledEntry(const char *name,
184                              const std::array<TExtension, ESSLExtCount> &esslExtensions,
185                              TExtension glslExtension,
186                              int esslVersion,
187                              int glslVersion,
188                              Shader shaderType);
189 
190     bool matches(const ImmutableString &name,
191                  ShShaderSpec shaderSpec,
192                  int shaderVersion,
193                  sh::GLenum shaderType,
194                  const TExtensionBehavior &extensions) const;
195 
196   private:
197     const char *mName;
198     std::array<TExtension, 2u> mESSLExtensions;
199     TExtension mGLSLExtension;
200     uint8_t mShaderType;
201     uint16_t mESSLVersion;
202     uint16_t mGLSLVersion;
203 };
204 
205 template <size_t ESSLExtCount>
UnmangledEntry(const char * name,const std::array<TExtension,ESSLExtCount> & esslExtensions,TExtension glslExtension,int esslVersion,int glslVersion,Shader shaderType)206 constexpr UnmangledEntry::UnmangledEntry(const char *name,
207                                          const std::array<TExtension, ESSLExtCount> &esslExtensions,
208                                          TExtension glslExtension,
209                                          int esslVersion,
210                                          int glslVersion,
211                                          Shader shaderType)
212     : mName(name),
213       mESSLExtensions{(ESSLExtCount >= 1) ? esslExtensions[0] : TExtension::UNDEFINED,
214                       (ESSLExtCount >= 2) ? esslExtensions[1] : TExtension::UNDEFINED},
215       mGLSLExtension(glslExtension),
216       mShaderType(static_cast<uint8_t>(shaderType)),
217       mESSLVersion(esslVersion < 0 ? std::numeric_limits<uint16_t>::max()
218                                    : static_cast<uint16_t>(esslVersion)),
219       mGLSLVersion(glslVersion < 0 ? std::numeric_limits<uint16_t>::max()
220                                    : static_cast<uint16_t>(glslVersion))
221 {}
222 
223 class TSymbolTable : angle::NonCopyable, TSymbolTableBase
224 {
225   public:
226     TSymbolTable();
227     // To start using the symbol table after construction:
228     // * initializeBuiltIns() needs to be called.
229     // * push() needs to be called to push the global level.
230 
231     ~TSymbolTable();
232 
233     bool isEmpty() const;
234     bool atGlobalLevel() const;
235 
236     void push();
237     void pop();
238 
239     // Declare a non-function symbol at the current scope. Return true in case the declaration was
240     // successful, and false if the declaration failed due to redefinition.
241     bool declare(TSymbol *symbol);
242 
243     // Only used to declare internal variables.
244     bool declareInternal(TSymbol *symbol);
245 
246     // Functions are always declared at global scope.
247     void declareUserDefinedFunction(TFunction *function, bool insertUnmangledName);
248 
249     // These return the TFunction pointer to keep using to refer to this function.
250     const TFunction *markFunctionHasPrototypeDeclaration(const ImmutableString &mangledName,
251                                                          bool *hadPrototypeDeclarationOut) const;
252     const TFunction *setFunctionParameterNamesFromDefinition(const TFunction *function,
253                                                              bool *wasDefinedOut) const;
254 
255     // Return false if the gl_in array size has already been initialized with a mismatching value.
256     bool setGlInArraySize(unsigned int inputArraySize);
257     TVariable *getGlInVariableWithArraySize() const;
258 
259     const TVariable *gl_FragData() const;
260     const TVariable *gl_SecondaryFragDataEXT() const;
261 
262     void markStaticRead(const TVariable &variable);
263     void markStaticWrite(const TVariable &variable);
264 
265     // Note: Should not call this for constant variables.
266     bool isStaticallyUsed(const TVariable &variable) const;
267 
268     // find() is guaranteed not to retain a reference to the ImmutableString, so an ImmutableString
269     // with a reference to a short-lived char * is fine to pass here.
270     const TSymbol *find(const ImmutableString &name, int shaderVersion) const;
271 
272     const TSymbol *findUserDefined(const ImmutableString &name) const;
273 
274     TFunction *findUserDefinedFunction(const ImmutableString &name) const;
275 
276     const TSymbol *findGlobal(const ImmutableString &name) const;
277     const TSymbol *findGlobalWithConversion(const std::vector<ImmutableString> &names) const;
278 
279     const TSymbol *findBuiltIn(const ImmutableString &name, int shaderVersion) const;
280     const TSymbol *findBuiltInWithConversion(const std::vector<ImmutableString> &names,
281                                              int shaderVersion) const;
282 
283     void setDefaultPrecision(TBasicType type, TPrecision prec);
284 
285     // Searches down the precisionStack for a precision qualifier
286     // for the specified TBasicType
287     TPrecision getDefaultPrecision(TBasicType type) const;
288 
289     // This records invariant varyings declared through "invariant varying_name;".
290     void addInvariantVarying(const TVariable &variable);
291 
292     // If this returns false, the varying could still be invariant if it is set as invariant during
293     // the varying variable declaration - this piece of information is stored in the variable's
294     // type, not here.
295     bool isVaryingInvariant(const TVariable &variable) const;
296 
297     void setGlobalInvariant(bool invariant);
298 
nextUniqueId()299     const TSymbolUniqueId nextUniqueId() { return TSymbolUniqueId(this); }
300 
301     // Gets the built-in accessible by a shader with the specified version, if any.
302     bool isUnmangledBuiltInName(const ImmutableString &name,
303                                 int shaderVersion,
304                                 const TExtensionBehavior &extensions) const;
305 
306     void initializeBuiltIns(sh::GLenum type,
307                             ShShaderSpec spec,
308                             const ShBuiltInResources &resources);
309     void clearCompilationResults();
310 
getShaderSpec()311     ShShaderSpec getShaderSpec() const { return mShaderSpec; }
312 
313   private:
314     friend class TSymbolUniqueId;
315 
316     struct VariableMetadata
317     {
318         VariableMetadata();
319         bool staticRead;
320         bool staticWrite;
321         bool invariant;
322     };
323 
324     int nextUniqueIdValue();
325 
326     class TSymbolTableLevel;
327 
328     void initSamplerDefaultPrecision(TBasicType samplerType);
329 
330     void initializeBuiltInVariables(sh::GLenum shaderType,
331                                     ShShaderSpec spec,
332                                     const ShBuiltInResources &resources);
333 
334     VariableMetadata *getOrCreateVariableMetadata(const TVariable &variable);
335 
336     std::vector<std::unique_ptr<TSymbolTableLevel>> mTable;
337 
338     // There's one precision stack level for predefined precisions and then one level for each scope
339     // in table.
340     typedef TMap<TBasicType, TPrecision> PrecisionStackLevel;
341     std::vector<std::unique_ptr<PrecisionStackLevel>> mPrecisionStack;
342 
343     bool mGlobalInvariant;
344 
345     int mUniqueIdCounter;
346 
347     static const int kLastBuiltInId;
348 
349     sh::GLenum mShaderType;
350     ShShaderSpec mShaderSpec;
351     ShBuiltInResources mResources;
352 
353     // Indexed by unique id. Map instead of vector since the variables are fairly sparse.
354     std::map<int, VariableMetadata> mVariableMetadata;
355 
356     // Store gl_in variable with its array size once the array size can be determined. The array
357     // size can also be checked against latter input primitive type declaration.
358     TVariable *mGlInVariableWithArraySize;
359 };
360 
361 }  // namespace sh
362 
363 #endif  // COMPILER_TRANSLATOR_SYMBOLTABLE_H_
364