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