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