• 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 // Symbol table for parsing. The design principles and most of the functionality are documented in
7 // the header file.
8 //
9 
10 #if defined(_MSC_VER)
11 #    pragma warning(disable : 4718)
12 #endif
13 
14 #include "compiler/translator/SymbolTable.h"
15 
16 #include "angle_gl.h"
17 #include "compiler/translator/ImmutableString.h"
18 #include "compiler/translator/IntermNode.h"
19 #include "compiler/translator/StaticType.h"
20 #include "compiler/translator/util.h"
21 
22 namespace sh
23 {
24 namespace
25 {
CheckShaderType(Shader expected,GLenum actual)26 bool CheckShaderType(Shader expected, GLenum actual)
27 {
28     switch (expected)
29     {
30         case Shader::ALL:
31             return true;
32         case Shader::FRAGMENT:
33             return actual == GL_FRAGMENT_SHADER;
34         case Shader::VERTEX:
35             return actual == GL_VERTEX_SHADER;
36         case Shader::COMPUTE:
37             return actual == GL_COMPUTE_SHADER;
38         case Shader::GEOMETRY:
39             return actual == GL_GEOMETRY_SHADER;
40         case Shader::GEOMETRY_EXT:
41             return actual == GL_GEOMETRY_SHADER_EXT;
42         case Shader::TESS_CONTROL_EXT:
43             return actual == GL_TESS_CONTROL_SHADER_EXT;
44         case Shader::TESS_EVALUATION_EXT:
45             return actual == GL_TESS_EVALUATION_SHADER_EXT;
46         case Shader::NOT_COMPUTE:
47             return actual != GL_COMPUTE_SHADER;
48         default:
49             UNREACHABLE();
50             return false;
51     }
52 }
53 
CheckExtension(uint32_t extensionIndex,const ShBuiltInResources & resources)54 bool CheckExtension(uint32_t extensionIndex, const ShBuiltInResources &resources)
55 {
56     const int *resourcePtr = reinterpret_cast<const int *>(&resources);
57     return resourcePtr[extensionIndex] > 0;
58 }
59 }  // namespace
60 
61 class TSymbolTable::TSymbolTableLevel
62 {
63   public:
64     TSymbolTableLevel() = default;
65 
66     bool insert(TSymbol *symbol);
67 
68     // Insert a function using its unmangled name as the key.
69     void insertUnmangled(TFunction *function);
70 
71     TSymbol *find(const ImmutableString &name) const;
72 
73   private:
74     using tLevel        = TUnorderedMap<ImmutableString,
75                                  TSymbol *,
76                                  ImmutableString::FowlerNollVoHash<sizeof(size_t)>>;
77     using tLevelPair    = const tLevel::value_type;
78     using tInsertResult = std::pair<tLevel::iterator, bool>;
79 
80     tLevel level;
81 };
82 
insert(TSymbol * symbol)83 bool TSymbolTable::TSymbolTableLevel::insert(TSymbol *symbol)
84 {
85     // returning true means symbol was added to the table
86     tInsertResult result = level.insert(tLevelPair(symbol->getMangledName(), symbol));
87     return result.second;
88 }
89 
insertUnmangled(TFunction * function)90 void TSymbolTable::TSymbolTableLevel::insertUnmangled(TFunction *function)
91 {
92     level.insert(tLevelPair(function->name(), function));
93 }
94 
find(const ImmutableString & name) const95 TSymbol *TSymbolTable::TSymbolTableLevel::find(const ImmutableString &name) const
96 {
97     tLevel::const_iterator it = level.find(name);
98     if (it == level.end())
99         return nullptr;
100     else
101         return (*it).second;
102 }
103 
TSymbolTable()104 TSymbolTable::TSymbolTable()
105     : mGlobalInvariant(false),
106       mUniqueIdCounter(0),
107       mShaderType(GL_FRAGMENT_SHADER),
108       mShaderSpec(SH_GLES2_SPEC),
109       mGlInVariableWithArraySize(nullptr)
110 {}
111 
112 TSymbolTable::~TSymbolTable() = default;
113 
isEmpty() const114 bool TSymbolTable::isEmpty() const
115 {
116     return mTable.empty();
117 }
118 
atGlobalLevel() const119 bool TSymbolTable::atGlobalLevel() const
120 {
121     return mTable.size() == 1u;
122 }
123 
push()124 void TSymbolTable::push()
125 {
126     mTable.emplace_back(new TSymbolTableLevel);
127     mPrecisionStack.emplace_back(new PrecisionStackLevel);
128 }
129 
pop()130 void TSymbolTable::pop()
131 {
132     mTable.pop_back();
133     mPrecisionStack.pop_back();
134 }
135 
markFunctionHasPrototypeDeclaration(const ImmutableString & mangledName,bool * hadPrototypeDeclarationOut) const136 const TFunction *TSymbolTable::markFunctionHasPrototypeDeclaration(
137     const ImmutableString &mangledName,
138     bool *hadPrototypeDeclarationOut) const
139 {
140     TFunction *function         = findUserDefinedFunction(mangledName);
141     *hadPrototypeDeclarationOut = function->hasPrototypeDeclaration();
142     function->setHasPrototypeDeclaration();
143     return function;
144 }
145 
setFunctionParameterNamesFromDefinition(const TFunction * function,bool * wasDefinedOut) const146 const TFunction *TSymbolTable::setFunctionParameterNamesFromDefinition(const TFunction *function,
147                                                                        bool *wasDefinedOut) const
148 {
149     TFunction *firstDeclaration = findUserDefinedFunction(function->getMangledName());
150     ASSERT(firstDeclaration);
151     // Note: 'firstDeclaration' could be 'function' if this is the first time we've seen function as
152     // it would have just been put in the symbol table. Otherwise, we're looking up an earlier
153     // occurance.
154     if (function != firstDeclaration)
155     {
156         // The previous declaration should have the same parameters as the function definition
157         // (parameter names may differ).
158         firstDeclaration->shareParameters(*function);
159     }
160 
161     *wasDefinedOut = firstDeclaration->isDefined();
162     firstDeclaration->setDefined();
163     return firstDeclaration;
164 }
165 
setGlInArraySize(unsigned int inputArraySize)166 bool TSymbolTable::setGlInArraySize(unsigned int inputArraySize)
167 {
168     if (mGlInVariableWithArraySize)
169     {
170         return mGlInVariableWithArraySize->getType().getOutermostArraySize() == inputArraySize;
171     }
172     const TInterfaceBlock *glPerVertex = static_cast<const TInterfaceBlock *>(m_gl_PerVertex);
173     TType *glInType = new TType(glPerVertex, EvqPerVertexIn, TLayoutQualifier::Create());
174     glInType->makeArray(inputArraySize);
175     mGlInVariableWithArraySize =
176         new TVariable(this, ImmutableString("gl_in"), glInType, SymbolType::BuiltIn,
177                       TExtension::EXT_geometry_shader);
178     return true;
179 }
180 
getGlInVariableWithArraySize() const181 TVariable *TSymbolTable::getGlInVariableWithArraySize() const
182 {
183     return mGlInVariableWithArraySize;
184 }
185 
gl_FragData() const186 const TVariable *TSymbolTable::gl_FragData() const
187 {
188     return static_cast<const TVariable *>(m_gl_FragData);
189 }
190 
gl_SecondaryFragDataEXT() const191 const TVariable *TSymbolTable::gl_SecondaryFragDataEXT() const
192 {
193     return static_cast<const TVariable *>(m_gl_SecondaryFragDataEXT);
194 }
195 
getOrCreateVariableMetadata(const TVariable & variable)196 TSymbolTable::VariableMetadata *TSymbolTable::getOrCreateVariableMetadata(const TVariable &variable)
197 {
198     int id    = variable.uniqueId().get();
199     auto iter = mVariableMetadata.find(id);
200     if (iter == mVariableMetadata.end())
201     {
202         iter = mVariableMetadata.insert(std::make_pair(id, VariableMetadata())).first;
203     }
204     return &iter->second;
205 }
206 
markStaticWrite(const TVariable & variable)207 void TSymbolTable::markStaticWrite(const TVariable &variable)
208 {
209     auto metadata         = getOrCreateVariableMetadata(variable);
210     metadata->staticWrite = true;
211 }
212 
markStaticRead(const TVariable & variable)213 void TSymbolTable::markStaticRead(const TVariable &variable)
214 {
215     auto metadata        = getOrCreateVariableMetadata(variable);
216     metadata->staticRead = true;
217 }
218 
isStaticallyUsed(const TVariable & variable) const219 bool TSymbolTable::isStaticallyUsed(const TVariable &variable) const
220 {
221     ASSERT(!variable.getConstPointer());
222     int id    = variable.uniqueId().get();
223     auto iter = mVariableMetadata.find(id);
224     return iter != mVariableMetadata.end() && (iter->second.staticRead || iter->second.staticWrite);
225 }
226 
addInvariantVarying(const TVariable & variable)227 void TSymbolTable::addInvariantVarying(const TVariable &variable)
228 {
229     ASSERT(atGlobalLevel());
230     auto metadata       = getOrCreateVariableMetadata(variable);
231     metadata->invariant = true;
232 }
233 
isVaryingInvariant(const TVariable & variable) const234 bool TSymbolTable::isVaryingInvariant(const TVariable &variable) const
235 {
236     ASSERT(atGlobalLevel());
237     if (mGlobalInvariant && (IsShaderOutput(variable.getType().getQualifier())))
238     {
239         return true;
240     }
241     int id    = variable.uniqueId().get();
242     auto iter = mVariableMetadata.find(id);
243     return iter != mVariableMetadata.end() && iter->second.invariant;
244 }
245 
setGlobalInvariant(bool invariant)246 void TSymbolTable::setGlobalInvariant(bool invariant)
247 {
248     ASSERT(atGlobalLevel());
249     mGlobalInvariant = invariant;
250 }
251 
find(const ImmutableString & name,int shaderVersion) const252 const TSymbol *TSymbolTable::find(const ImmutableString &name, int shaderVersion) const
253 {
254     const TSymbol *userSymbol = findUserDefined(name);
255     if (userSymbol)
256     {
257         return userSymbol;
258     }
259 
260     return findBuiltIn(name, shaderVersion);
261 }
262 
findUserDefined(const ImmutableString & name) const263 const TSymbol *TSymbolTable::findUserDefined(const ImmutableString &name) const
264 {
265     int userDefinedLevel = static_cast<int>(mTable.size()) - 1;
266     while (userDefinedLevel >= 0)
267     {
268         const TSymbol *symbol = mTable[userDefinedLevel]->find(name);
269         if (symbol)
270         {
271             return symbol;
272         }
273         userDefinedLevel--;
274     }
275 
276     return nullptr;
277 }
278 
findUserDefinedFunction(const ImmutableString & name) const279 TFunction *TSymbolTable::findUserDefinedFunction(const ImmutableString &name) const
280 {
281     // User-defined functions are always declared at the global level.
282     ASSERT(!mTable.empty());
283     return static_cast<TFunction *>(mTable[0]->find(name));
284 }
285 
findGlobal(const ImmutableString & name) const286 const TSymbol *TSymbolTable::findGlobal(const ImmutableString &name) const
287 {
288     ASSERT(!mTable.empty());
289     return mTable[0]->find(name);
290 }
291 
findGlobalWithConversion(const std::vector<ImmutableString> & names) const292 const TSymbol *TSymbolTable::findGlobalWithConversion(
293     const std::vector<ImmutableString> &names) const
294 {
295     for (const ImmutableString &name : names)
296     {
297         const TSymbol *target = findGlobal(name);
298         if (target != nullptr)
299             return target;
300     }
301     return nullptr;
302 }
303 
findBuiltInWithConversion(const std::vector<ImmutableString> & names,int shaderVersion) const304 const TSymbol *TSymbolTable::findBuiltInWithConversion(const std::vector<ImmutableString> &names,
305                                                        int shaderVersion) const
306 {
307     for (const ImmutableString &name : names)
308     {
309         const TSymbol *target = findBuiltIn(name, shaderVersion);
310         if (target != nullptr)
311             return target;
312     }
313     return nullptr;
314 }
315 
declare(TSymbol * symbol)316 bool TSymbolTable::declare(TSymbol *symbol)
317 {
318     ASSERT(!mTable.empty());
319     ASSERT(symbol->symbolType() == SymbolType::UserDefined);
320     ASSERT(!symbol->isFunction());
321     return mTable.back()->insert(symbol);
322 }
323 
declareInternal(TSymbol * symbol)324 bool TSymbolTable::declareInternal(TSymbol *symbol)
325 {
326     ASSERT(!mTable.empty());
327     ASSERT(symbol->symbolType() == SymbolType::AngleInternal);
328     ASSERT(!symbol->isFunction());
329     return mTable.back()->insert(symbol);
330 }
331 
declareUserDefinedFunction(TFunction * function,bool insertUnmangledName)332 void TSymbolTable::declareUserDefinedFunction(TFunction *function, bool insertUnmangledName)
333 {
334     ASSERT(!mTable.empty());
335     if (insertUnmangledName)
336     {
337         // Insert the unmangled name to detect potential future redefinition as a variable.
338         mTable[0]->insertUnmangled(function);
339     }
340     mTable[0]->insert(function);
341 }
342 
setDefaultPrecision(TBasicType type,TPrecision prec)343 void TSymbolTable::setDefaultPrecision(TBasicType type, TPrecision prec)
344 {
345     int indexOfLastElement = static_cast<int>(mPrecisionStack.size()) - 1;
346     // Uses map operator [], overwrites the current value
347     (*mPrecisionStack[indexOfLastElement])[type] = prec;
348 }
349 
getDefaultPrecision(TBasicType type) const350 TPrecision TSymbolTable::getDefaultPrecision(TBasicType type) const
351 {
352     if (!SupportsPrecision(type))
353         return EbpUndefined;
354 
355     // unsigned integers use the same precision as signed
356     TBasicType baseType = (type == EbtUInt) ? EbtInt : type;
357 
358     int level = static_cast<int>(mPrecisionStack.size()) - 1;
359     ASSERT(level >= 0);  // Just to be safe. Should not happen.
360     // If we dont find anything we return this. Some types don't have predefined default precision.
361     TPrecision prec = EbpUndefined;
362     while (level >= 0)
363     {
364         PrecisionStackLevel::iterator it = mPrecisionStack[level]->find(baseType);
365         if (it != mPrecisionStack[level]->end())
366         {
367             prec = (*it).second;
368             break;
369         }
370         level--;
371     }
372     return prec;
373 }
374 
clearCompilationResults()375 void TSymbolTable::clearCompilationResults()
376 {
377     mGlobalInvariant = false;
378     mUniqueIdCounter = kLastBuiltInId + 1;
379     mVariableMetadata.clear();
380     mGlInVariableWithArraySize = nullptr;
381 
382     // User-defined scopes should have already been cleared when the compilation finished.
383     ASSERT(mTable.empty());
384 }
385 
nextUniqueIdValue()386 int TSymbolTable::nextUniqueIdValue()
387 {
388     ASSERT(mUniqueIdCounter < std::numeric_limits<int>::max());
389     return ++mUniqueIdCounter;
390 }
391 
initializeBuiltIns(sh::GLenum type,ShShaderSpec spec,const ShBuiltInResources & resources)392 void TSymbolTable::initializeBuiltIns(sh::GLenum type,
393                                       ShShaderSpec spec,
394                                       const ShBuiltInResources &resources)
395 {
396     mShaderType = type;
397     mShaderSpec = spec;
398     mResources  = resources;
399 
400     // We need just one precision stack level for predefined precisions.
401     mPrecisionStack.emplace_back(new PrecisionStackLevel);
402 
403     if (IsDesktopGLSpec(spec))
404     {
405         setDefaultPrecision(EbtInt, EbpUndefined);
406         setDefaultPrecision(EbtFloat, EbpUndefined);
407     }
408     else
409     {
410         switch (type)
411         {
412             case GL_FRAGMENT_SHADER:
413                 setDefaultPrecision(EbtInt, EbpMedium);
414                 break;
415             case GL_VERTEX_SHADER:
416             case GL_COMPUTE_SHADER:
417             case GL_GEOMETRY_SHADER_EXT:
418             case GL_TESS_CONTROL_SHADER_EXT:
419             case GL_TESS_EVALUATION_SHADER_EXT:
420                 setDefaultPrecision(EbtInt, EbpHigh);
421                 setDefaultPrecision(EbtFloat, EbpHigh);
422                 break;
423             default:
424                 UNREACHABLE();
425         }
426     }
427 
428     // Set defaults for sampler types that have default precision, even those that are
429     // only available if an extension exists.
430     // New sampler types in ESSL3 don't have default precision. ESSL1 types do.
431     initSamplerDefaultPrecision(EbtSampler2D);
432     initSamplerDefaultPrecision(EbtSamplerCube);
433     // SamplerExternalOES is specified in the extension to have default precision.
434     initSamplerDefaultPrecision(EbtSamplerExternalOES);
435     // SamplerExternal2DY2YEXT is specified in the extension to have default precision.
436     initSamplerDefaultPrecision(EbtSamplerExternal2DY2YEXT);
437     // It isn't specified whether Sampler2DRect has default precision.
438     initSamplerDefaultPrecision(EbtSampler2DRect);
439 
440     if (spec < SH_GLES3_SPEC)
441     {
442         // Only set the default precision of shadow samplers in ESLL1. They become core in ESSL3
443         // where they do not have a defalut precision.
444         initSamplerDefaultPrecision(EbtSampler2DShadow);
445     }
446 
447     setDefaultPrecision(EbtAtomicCounter, EbpHigh);
448 
449     initializeBuiltInVariables(type, spec, resources);
450     mUniqueIdCounter = kLastBuiltInId + 1;
451 }
452 
initSamplerDefaultPrecision(TBasicType samplerType)453 void TSymbolTable::initSamplerDefaultPrecision(TBasicType samplerType)
454 {
455     ASSERT(samplerType >= EbtGuardSamplerBegin && samplerType <= EbtGuardSamplerEnd);
456     setDefaultPrecision(samplerType, EbpLow);
457 }
458 
VariableMetadata()459 TSymbolTable::VariableMetadata::VariableMetadata()
460     : staticRead(false), staticWrite(false), invariant(false)
461 {}
462 
get(ShShaderSpec shaderSpec,int shaderVersion,sh::GLenum shaderType,const ShBuiltInResources & resources,const TSymbolTableBase & symbolTable) const463 const TSymbol *SymbolRule::get(ShShaderSpec shaderSpec,
464                                int shaderVersion,
465                                sh::GLenum shaderType,
466                                const ShBuiltInResources &resources,
467                                const TSymbolTableBase &symbolTable) const
468 {
469     if (IsDesktopGLSpec(shaderSpec) != (mIsDesktop == 1))
470         return nullptr;
471 
472     if (mVersion == kESSL1Only && shaderVersion != static_cast<int>(kESSL1Only))
473         return nullptr;
474 
475     if (mVersion > shaderVersion)
476         return nullptr;
477 
478     if (!CheckShaderType(static_cast<Shader>(mShaders), shaderType))
479         return nullptr;
480 
481     if (mExtensionIndex != 0 && !CheckExtension(mExtensionIndex, resources))
482         return nullptr;
483 
484     return mIsVar > 0 ? symbolTable.*(mSymbolOrVar.var) : mSymbolOrVar.symbol;
485 }
486 
FindMangledBuiltIn(ShShaderSpec shaderSpec,int shaderVersion,sh::GLenum shaderType,const ShBuiltInResources & resources,const TSymbolTableBase & symbolTable,const SymbolRule * rules,uint16_t startIndex,uint16_t endIndex)487 const TSymbol *FindMangledBuiltIn(ShShaderSpec shaderSpec,
488                                   int shaderVersion,
489                                   sh::GLenum shaderType,
490                                   const ShBuiltInResources &resources,
491                                   const TSymbolTableBase &symbolTable,
492                                   const SymbolRule *rules,
493                                   uint16_t startIndex,
494                                   uint16_t endIndex)
495 {
496     for (uint32_t ruleIndex = startIndex; ruleIndex < endIndex; ++ruleIndex)
497     {
498         const TSymbol *symbol =
499             rules[ruleIndex].get(shaderSpec, shaderVersion, shaderType, resources, symbolTable);
500         if (symbol)
501         {
502             return symbol;
503         }
504     }
505 
506     return nullptr;
507 }
508 
matches(const ImmutableString & name,ShShaderSpec shaderSpec,int shaderVersion,sh::GLenum shaderType,const TExtensionBehavior & extensions) const509 bool UnmangledEntry::matches(const ImmutableString &name,
510                              ShShaderSpec shaderSpec,
511                              int shaderVersion,
512                              sh::GLenum shaderType,
513                              const TExtensionBehavior &extensions) const
514 {
515     if (name != mName)
516         return false;
517 
518     if (!CheckShaderType(static_cast<Shader>(mShaderType), shaderType))
519         return false;
520 
521     if (IsDesktopGLSpec(shaderSpec))
522     {
523         if (mGLSLVersion > shaderVersion)
524             return false;
525 
526         if (mGLSLExtension == TExtension::UNDEFINED)
527             return true;
528 
529         return IsExtensionEnabled(extensions, mGLSLExtension);
530     }
531     else
532     {
533         if (mESSLVersion == kESSL1Only && shaderVersion != static_cast<int>(kESSL1Only))
534             return false;
535 
536         if (mESSLVersion > shaderVersion)
537             return false;
538 
539         bool anyExtension        = false;
540         bool anyExtensionEnabled = false;
541         for (TExtension ext : mESSLExtensions)
542         {
543             if (ext != TExtension::UNDEFINED)
544             {
545                 anyExtension        = true;
546                 anyExtensionEnabled = anyExtensionEnabled || IsExtensionEnabled(extensions, ext);
547             }
548         }
549 
550         if (!anyExtension)
551             return true;
552 
553         return anyExtensionEnabled;
554     }
555 }
556 }  // namespace sh
557