• 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 
25 class TSymbolTable::TSymbolTableLevel
26 {
27   public:
28     TSymbolTableLevel() = default;
29 
30     bool insert(TSymbol *symbol);
31 
32     // Insert a function using its unmangled name as the key.
33     void insertUnmangled(TFunction *function);
34 
35     TSymbol *find(const ImmutableString &name) const;
36 
37   private:
38     using tLevel        = TUnorderedMap<ImmutableString,
39                                  TSymbol *,
40                                  ImmutableString::FowlerNollVoHash<sizeof(size_t)>>;
41     using tLevelPair    = const tLevel::value_type;
42     using tInsertResult = std::pair<tLevel::iterator, bool>;
43 
44     tLevel level;
45 };
46 
insert(TSymbol * symbol)47 bool TSymbolTable::TSymbolTableLevel::insert(TSymbol *symbol)
48 {
49     // returning true means symbol was added to the table
50     tInsertResult result = level.insert(tLevelPair(symbol->getMangledName(), symbol));
51     return result.second;
52 }
53 
insertUnmangled(TFunction * function)54 void TSymbolTable::TSymbolTableLevel::insertUnmangled(TFunction *function)
55 {
56     level.insert(tLevelPair(function->name(), function));
57 }
58 
find(const ImmutableString & name) const59 TSymbol *TSymbolTable::TSymbolTableLevel::find(const ImmutableString &name) const
60 {
61     tLevel::const_iterator it = level.find(name);
62     if (it == level.end())
63         return nullptr;
64     else
65         return (*it).second;
66 }
67 
TSymbolTable()68 TSymbolTable::TSymbolTable()
69     : mGlobalInvariant(false),
70       mUniqueIdCounter(0),
71       mShaderType(GL_FRAGMENT_SHADER),
72       mGlInVariableWithArraySize(nullptr)
73 {}
74 
75 TSymbolTable::~TSymbolTable() = default;
76 
isEmpty() const77 bool TSymbolTable::isEmpty() const
78 {
79     return mTable.empty();
80 }
81 
atGlobalLevel() const82 bool TSymbolTable::atGlobalLevel() const
83 {
84     return mTable.size() == 1u;
85 }
86 
push()87 void TSymbolTable::push()
88 {
89     mTable.emplace_back(new TSymbolTableLevel);
90     mPrecisionStack.emplace_back(new PrecisionStackLevel);
91 }
92 
pop()93 void TSymbolTable::pop()
94 {
95     mTable.pop_back();
96     mPrecisionStack.pop_back();
97 }
98 
markFunctionHasPrototypeDeclaration(const ImmutableString & mangledName,bool * hadPrototypeDeclarationOut) const99 const TFunction *TSymbolTable::markFunctionHasPrototypeDeclaration(
100     const ImmutableString &mangledName,
101     bool *hadPrototypeDeclarationOut) const
102 {
103     TFunction *function         = findUserDefinedFunction(mangledName);
104     *hadPrototypeDeclarationOut = function->hasPrototypeDeclaration();
105     function->setHasPrototypeDeclaration();
106     return function;
107 }
108 
setFunctionParameterNamesFromDefinition(const TFunction * function,bool * wasDefinedOut) const109 const TFunction *TSymbolTable::setFunctionParameterNamesFromDefinition(const TFunction *function,
110                                                                        bool *wasDefinedOut) const
111 {
112     TFunction *firstDeclaration = findUserDefinedFunction(function->getMangledName());
113     ASSERT(firstDeclaration);
114     // Note: 'firstDeclaration' could be 'function' if this is the first time we've seen function as
115     // it would have just been put in the symbol table. Otherwise, we're looking up an earlier
116     // occurance.
117     if (function != firstDeclaration)
118     {
119         // The previous declaration should have the same parameters as the function definition
120         // (parameter names may differ).
121         firstDeclaration->shareParameters(*function);
122     }
123 
124     *wasDefinedOut = firstDeclaration->isDefined();
125     firstDeclaration->setDefined();
126     return firstDeclaration;
127 }
128 
setGlInArraySize(unsigned int inputArraySize)129 bool TSymbolTable::setGlInArraySize(unsigned int inputArraySize)
130 {
131     if (mGlInVariableWithArraySize)
132     {
133         return mGlInVariableWithArraySize->getType().getOutermostArraySize() == inputArraySize;
134     }
135     const TInterfaceBlock *glPerVertex = mVar_gl_PerVertex;
136     TType *glInType = new TType(glPerVertex, EvqPerVertexIn, TLayoutQualifier::Create());
137     glInType->makeArray(inputArraySize);
138     mGlInVariableWithArraySize =
139         new TVariable(this, ImmutableString("gl_in"), glInType, SymbolType::BuiltIn,
140                       TExtension::EXT_geometry_shader);
141     return true;
142 }
143 
getGlInVariableWithArraySize() const144 TVariable *TSymbolTable::getGlInVariableWithArraySize() const
145 {
146     return mGlInVariableWithArraySize;
147 }
148 
gl_FragData() const149 const TVariable *TSymbolTable::gl_FragData() const
150 {
151     return mVar_gl_FragData;
152 }
153 
gl_SecondaryFragDataEXT() const154 const TVariable *TSymbolTable::gl_SecondaryFragDataEXT() const
155 {
156     return mVar_gl_SecondaryFragDataEXT;
157 }
158 
getOrCreateVariableMetadata(const TVariable & variable)159 TSymbolTable::VariableMetadata *TSymbolTable::getOrCreateVariableMetadata(const TVariable &variable)
160 {
161     int id    = variable.uniqueId().get();
162     auto iter = mVariableMetadata.find(id);
163     if (iter == mVariableMetadata.end())
164     {
165         iter = mVariableMetadata.insert(std::make_pair(id, VariableMetadata())).first;
166     }
167     return &iter->second;
168 }
169 
markStaticWrite(const TVariable & variable)170 void TSymbolTable::markStaticWrite(const TVariable &variable)
171 {
172     auto metadata         = getOrCreateVariableMetadata(variable);
173     metadata->staticWrite = true;
174 }
175 
markStaticRead(const TVariable & variable)176 void TSymbolTable::markStaticRead(const TVariable &variable)
177 {
178     auto metadata        = getOrCreateVariableMetadata(variable);
179     metadata->staticRead = true;
180 }
181 
isStaticallyUsed(const TVariable & variable) const182 bool TSymbolTable::isStaticallyUsed(const TVariable &variable) const
183 {
184     ASSERT(!variable.getConstPointer());
185     int id    = variable.uniqueId().get();
186     auto iter = mVariableMetadata.find(id);
187     return iter != mVariableMetadata.end() && (iter->second.staticRead || iter->second.staticWrite);
188 }
189 
addInvariantVarying(const TVariable & variable)190 void TSymbolTable::addInvariantVarying(const TVariable &variable)
191 {
192     ASSERT(atGlobalLevel());
193     auto metadata       = getOrCreateVariableMetadata(variable);
194     metadata->invariant = true;
195 }
196 
isVaryingInvariant(const TVariable & variable) const197 bool TSymbolTable::isVaryingInvariant(const TVariable &variable) const
198 {
199     ASSERT(atGlobalLevel());
200     if (mGlobalInvariant && (IsShaderOutput(variable.getType().getQualifier())))
201     {
202         return true;
203     }
204     int id    = variable.uniqueId().get();
205     auto iter = mVariableMetadata.find(id);
206     return iter != mVariableMetadata.end() && iter->second.invariant;
207 }
208 
setGlobalInvariant(bool invariant)209 void TSymbolTable::setGlobalInvariant(bool invariant)
210 {
211     ASSERT(atGlobalLevel());
212     mGlobalInvariant = invariant;
213 }
214 
find(const ImmutableString & name,int shaderVersion) const215 const TSymbol *TSymbolTable::find(const ImmutableString &name, int shaderVersion) const
216 {
217     const TSymbol *userSymbol = findUserDefined(name);
218     if (userSymbol)
219     {
220         return userSymbol;
221     }
222 
223     return findBuiltIn(name, shaderVersion);
224 }
225 
findUserDefined(const ImmutableString & name) const226 const TSymbol *TSymbolTable::findUserDefined(const ImmutableString &name) const
227 {
228     int userDefinedLevel = static_cast<int>(mTable.size()) - 1;
229     while (userDefinedLevel >= 0)
230     {
231         const TSymbol *symbol = mTable[userDefinedLevel]->find(name);
232         if (symbol)
233         {
234             return symbol;
235         }
236         userDefinedLevel--;
237     }
238 
239     return nullptr;
240 }
241 
findUserDefinedFunction(const ImmutableString & name) const242 TFunction *TSymbolTable::findUserDefinedFunction(const ImmutableString &name) const
243 {
244     // User-defined functions are always declared at the global level.
245     ASSERT(!mTable.empty());
246     return static_cast<TFunction *>(mTable[0]->find(name));
247 }
248 
findGlobal(const ImmutableString & name) const249 const TSymbol *TSymbolTable::findGlobal(const ImmutableString &name) const
250 {
251     ASSERT(!mTable.empty());
252     return mTable[0]->find(name);
253 }
254 
findGlobalWithConversion(const std::vector<ImmutableString> & names) const255 const TSymbol *TSymbolTable::findGlobalWithConversion(
256     const std::vector<ImmutableString> &names) const
257 {
258     const TSymbol *target;
259     for (ImmutableString name : names)
260     {
261         target = findGlobal(name);
262         if (target != nullptr)
263             break;
264     }
265     return target;
266 }
267 
findBuiltInWithConversion(const std::vector<ImmutableString> & names,int shaderVersion) const268 const TSymbol *TSymbolTable::findBuiltInWithConversion(const std::vector<ImmutableString> &names,
269                                                        int shaderVersion) const
270 {
271     const TSymbol *target;
272     for (ImmutableString name : names)
273     {
274         target = findBuiltIn(name, shaderVersion);
275         if (target != nullptr)
276             break;
277     }
278     return target;
279 }
280 
declare(TSymbol * symbol)281 bool TSymbolTable::declare(TSymbol *symbol)
282 {
283     ASSERT(!mTable.empty());
284     ASSERT(symbol->symbolType() == SymbolType::UserDefined);
285     ASSERT(!symbol->isFunction());
286     return mTable.back()->insert(symbol);
287 }
288 
declareInternal(TSymbol * symbol)289 bool TSymbolTable::declareInternal(TSymbol *symbol)
290 {
291     ASSERT(!mTable.empty());
292     ASSERT(symbol->symbolType() == SymbolType::AngleInternal);
293     ASSERT(!symbol->isFunction());
294     return mTable.back()->insert(symbol);
295 }
296 
declareUserDefinedFunction(TFunction * function,bool insertUnmangledName)297 void TSymbolTable::declareUserDefinedFunction(TFunction *function, bool insertUnmangledName)
298 {
299     ASSERT(!mTable.empty());
300     if (insertUnmangledName)
301     {
302         // Insert the unmangled name to detect potential future redefinition as a variable.
303         mTable[0]->insertUnmangled(function);
304     }
305     mTable[0]->insert(function);
306 }
307 
setDefaultPrecision(TBasicType type,TPrecision prec)308 void TSymbolTable::setDefaultPrecision(TBasicType type, TPrecision prec)
309 {
310     int indexOfLastElement = static_cast<int>(mPrecisionStack.size()) - 1;
311     // Uses map operator [], overwrites the current value
312     (*mPrecisionStack[indexOfLastElement])[type] = prec;
313 }
314 
getDefaultPrecision(TBasicType type) const315 TPrecision TSymbolTable::getDefaultPrecision(TBasicType type) const
316 {
317     if (!SupportsPrecision(type))
318         return EbpUndefined;
319 
320     // unsigned integers use the same precision as signed
321     TBasicType baseType = (type == EbtUInt) ? EbtInt : type;
322 
323     int level = static_cast<int>(mPrecisionStack.size()) - 1;
324     ASSERT(level >= 0);  // Just to be safe. Should not happen.
325     // If we dont find anything we return this. Some types don't have predefined default precision.
326     TPrecision prec = EbpUndefined;
327     while (level >= 0)
328     {
329         PrecisionStackLevel::iterator it = mPrecisionStack[level]->find(baseType);
330         if (it != mPrecisionStack[level]->end())
331         {
332             prec = (*it).second;
333             break;
334         }
335         level--;
336     }
337     return prec;
338 }
339 
clearCompilationResults()340 void TSymbolTable::clearCompilationResults()
341 {
342     mGlobalInvariant = false;
343     mUniqueIdCounter = kLastBuiltInId + 1;
344     mVariableMetadata.clear();
345     mGlInVariableWithArraySize = nullptr;
346 
347     // User-defined scopes should have already been cleared when the compilation finished.
348     ASSERT(mTable.empty());
349 }
350 
nextUniqueIdValue()351 int TSymbolTable::nextUniqueIdValue()
352 {
353     ASSERT(mUniqueIdCounter < std::numeric_limits<int>::max());
354     return ++mUniqueIdCounter;
355 }
356 
initializeBuiltIns(sh::GLenum type,ShShaderSpec spec,const ShBuiltInResources & resources)357 void TSymbolTable::initializeBuiltIns(sh::GLenum type,
358                                       ShShaderSpec spec,
359                                       const ShBuiltInResources &resources)
360 {
361     mShaderType = type;
362     mResources  = resources;
363 
364     // We need just one precision stack level for predefined precisions.
365     mPrecisionStack.emplace_back(new PrecisionStackLevel);
366 
367     if (IsDesktopGLSpec(spec))
368     {
369         setDefaultPrecision(EbtInt, EbpUndefined);
370         setDefaultPrecision(EbtFloat, EbpUndefined);
371     }
372     else
373     {
374         switch (type)
375         {
376             case GL_FRAGMENT_SHADER:
377                 setDefaultPrecision(EbtInt, EbpMedium);
378                 break;
379             case GL_VERTEX_SHADER:
380             case GL_COMPUTE_SHADER:
381             case GL_GEOMETRY_SHADER_EXT:
382                 setDefaultPrecision(EbtInt, EbpHigh);
383                 setDefaultPrecision(EbtFloat, EbpHigh);
384                 break;
385             default:
386                 UNREACHABLE();
387         }
388     }
389 
390     // Set defaults for sampler types that have default precision, even those that are
391     // only available if an extension exists.
392     // New sampler types in ESSL3 don't have default precision. ESSL1 types do.
393     initSamplerDefaultPrecision(EbtSampler2D);
394     initSamplerDefaultPrecision(EbtSamplerCube);
395     // SamplerExternalOES is specified in the extension to have default precision.
396     initSamplerDefaultPrecision(EbtSamplerExternalOES);
397     // SamplerExternal2DY2YEXT is specified in the extension to have default precision.
398     initSamplerDefaultPrecision(EbtSamplerExternal2DY2YEXT);
399     // It isn't specified whether Sampler2DRect has default precision.
400     initSamplerDefaultPrecision(EbtSampler2DRect);
401 
402     setDefaultPrecision(EbtAtomicCounter, EbpHigh);
403 
404     initializeBuiltInVariables(type, spec, resources);
405     mUniqueIdCounter = kLastBuiltInId + 1;
406 }
407 
initSamplerDefaultPrecision(TBasicType samplerType)408 void TSymbolTable::initSamplerDefaultPrecision(TBasicType samplerType)
409 {
410     ASSERT(samplerType >= EbtGuardSamplerBegin && samplerType <= EbtGuardSamplerEnd);
411     setDefaultPrecision(samplerType, EbpLow);
412 }
413 
VariableMetadata()414 TSymbolTable::VariableMetadata::VariableMetadata()
415     : staticRead(false), staticWrite(false), invariant(false)
416 {}
417 }  // namespace sh
418