• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
3 // Copyright (C) 2013 LunarG, Inc.
4 // Copyright (C) 2015-2018 Google, Inc.
5 //
6 // All rights reserved.
7 //
8 // Redistribution and use in source and binary forms, with or without
9 // modification, are permitted provided that the following conditions
10 // are met:
11 //
12 //    Redistributions of source code must retain the above copyright
13 //    notice, this list of conditions and the following disclaimer.
14 //
15 //    Redistributions in binary form must reproduce the above
16 //    copyright notice, this list of conditions and the following
17 //    disclaimer in the documentation and/or other materials provided
18 //    with the distribution.
19 //
20 //    Neither the name of 3Dlabs Inc. Ltd. nor the names of its
21 //    contributors may be used to endorse or promote products derived
22 //    from this software without specific prior written permission.
23 //
24 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28 // COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30 // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 // POSSIBILITY OF SUCH DAMAGE.
36 //
37 
38 #ifndef _SYMBOL_TABLE_INCLUDED_
39 #define _SYMBOL_TABLE_INCLUDED_
40 
41 //
42 // Symbol table for parsing.  Has these design characteristics:
43 //
44 // * Same symbol table can be used to compile many shaders, to preserve
45 //   effort of creating and loading with the large numbers of built-in
46 //   symbols.
47 //
48 // -->  This requires a copy mechanism, so initial pools used to create
49 //   the shared information can be popped.  Done through "clone"
50 //   methods.
51 //
52 // * Name mangling will be used to give each function a unique name
53 //   so that symbol table lookups are never ambiguous.  This allows
54 //   a simpler symbol table structure.
55 //
56 // * Pushing and popping of scope, so symbol table will really be a stack
57 //   of symbol tables.  Searched from the top, with new inserts going into
58 //   the top.
59 //
60 // * Constants:  Compile time constant symbols will keep their values
61 //   in the symbol table.  The parser can substitute constants at parse
62 //   time, including doing constant folding and constant propagation.
63 //
64 // * No temporaries:  Temporaries made from operations (+, --, .xy, etc.)
65 //   are tracked in the intermediate representation, not the symbol table.
66 //
67 
68 #include "../Include/Common.h"
69 #include "../Include/intermediate.h"
70 #include "../Include/InfoSink.h"
71 
72 namespace glslang {
73 
74 //
75 // Symbol base class.  (Can build functions or variables out of these...)
76 //
77 
78 class TVariable;
79 class TFunction;
80 class TAnonMember;
81 
82 typedef TVector<const char*> TExtensionList;
83 
84 class TSymbol {
85 public:
POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator ())86     POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
87     explicit TSymbol(const TString *n) :  name(n), uniqueId(0), extensions(nullptr), writable(true) { }
88     virtual TSymbol* clone() const = 0;
~TSymbol()89     virtual ~TSymbol() { }  // rely on all symbol owned memory coming from the pool
90 
getName()91     virtual const TString& getName() const { return *name; }
changeName(const TString * newName)92     virtual void changeName(const TString* newName) { name = newName; }
addPrefix(const char * prefix)93     virtual void addPrefix(const char* prefix)
94     {
95         TString newName(prefix);
96         newName.append(*name);
97         changeName(NewPoolTString(newName.c_str()));
98     }
getMangledName()99     virtual const TString& getMangledName() const { return getName(); }
getAsFunction()100     virtual TFunction* getAsFunction() { return nullptr; }
getAsFunction()101     virtual const TFunction* getAsFunction() const { return nullptr; }
getAsVariable()102     virtual TVariable* getAsVariable() { return nullptr; }
getAsVariable()103     virtual const TVariable* getAsVariable() const { return nullptr; }
getAsAnonMember()104     virtual const TAnonMember* getAsAnonMember() const { return nullptr; }
105     virtual const TType& getType() const = 0;
106     virtual TType& getWritableType() = 0;
setUniqueId(long long id)107     virtual void setUniqueId(long long id) { uniqueId = id; }
getUniqueId()108     virtual long long getUniqueId() const { return uniqueId; }
setExtensions(int numExts,const char * const exts[])109     virtual void setExtensions(int numExts, const char* const exts[])
110     {
111         assert(extensions == nullptr);
112         assert(numExts > 0);
113         extensions = NewPoolObject(extensions);
114         for (int e = 0; e < numExts; ++e)
115             extensions->push_back(exts[e]);
116     }
getNumExtensions()117     virtual int getNumExtensions() const { return extensions == nullptr ? 0 : (int)extensions->size(); }
getExtensions()118     virtual const char** getExtensions() const { return extensions->data(); }
119 
120     virtual void dump(TInfoSink& infoSink, bool complete = false) const = 0;
121     void dumpExtensions(TInfoSink& infoSink) const;
122 
isReadOnly()123     virtual bool isReadOnly() const { return ! writable; }
makeReadOnly()124     virtual void makeReadOnly() { writable = false; }
125 
126 protected:
127     explicit TSymbol(const TSymbol&);
128     TSymbol& operator=(const TSymbol&);
129 
130     const TString *name;
131     unsigned long long uniqueId;      // For cross-scope comparing during code generation
132 
133     // For tracking what extensions must be present
134     // (don't use if correct version/profile is present).
135     TExtensionList* extensions; // an array of pointers to existing constant char strings
136 
137     //
138     // N.B.: Non-const functions that will be generally used should assert on this,
139     // to avoid overwriting shared symbol-table information.
140     //
141     bool writable;
142 };
143 
144 //
145 // Variable class, meaning a symbol that's not a function.
146 //
147 // There could be a separate class hierarchy for Constant variables;
148 // Only one of int, bool, or float, (or none) is correct for
149 // any particular use, but it's easy to do this way, and doesn't
150 // seem worth having separate classes, and "getConst" can't simply return
151 // different values for different types polymorphically, so this is
152 // just simple and pragmatic.
153 //
154 class TVariable : public TSymbol {
155 public:
156     TVariable(const TString *name, const TType& t, bool uT = false )
TSymbol(name)157         : TSymbol(name),
158           userType(uT),
159           constSubtree(nullptr),
160           memberExtensions(nullptr),
161           anonId(-1)
162         { type.shallowCopy(t); }
163     virtual TVariable* clone() const;
~TVariable()164     virtual ~TVariable() { }
165 
getAsVariable()166     virtual TVariable* getAsVariable() { return this; }
getAsVariable()167     virtual const TVariable* getAsVariable() const { return this; }
getType()168     virtual const TType& getType() const { return type; }
getWritableType()169     virtual TType& getWritableType() { assert(writable); return type; }
isUserType()170     virtual bool isUserType() const { return userType; }
getConstArray()171     virtual const TConstUnionArray& getConstArray() const { return constArray; }
getWritableConstArray()172     virtual TConstUnionArray& getWritableConstArray() { assert(writable); return constArray; }
setConstArray(const TConstUnionArray & array)173     virtual void setConstArray(const TConstUnionArray& array) { constArray = array; }
setConstSubtree(TIntermTyped * subtree)174     virtual void setConstSubtree(TIntermTyped* subtree) { constSubtree = subtree; }
getConstSubtree()175     virtual TIntermTyped* getConstSubtree() const { return constSubtree; }
setAnonId(int i)176     virtual void setAnonId(int i) { anonId = i; }
getAnonId()177     virtual int getAnonId() const { return anonId; }
178 
setMemberExtensions(int member,int numExts,const char * const exts[])179     virtual void setMemberExtensions(int member, int numExts, const char* const exts[])
180     {
181         assert(type.isStruct());
182         assert(numExts > 0);
183         if (memberExtensions == nullptr) {
184             memberExtensions = NewPoolObject(memberExtensions);
185             memberExtensions->resize(type.getStruct()->size());
186         }
187         for (int e = 0; e < numExts; ++e)
188             (*memberExtensions)[member].push_back(exts[e]);
189     }
hasMemberExtensions()190     virtual bool hasMemberExtensions() const { return memberExtensions != nullptr; }
getNumMemberExtensions(int member)191     virtual int getNumMemberExtensions(int member) const
192     {
193         return memberExtensions == nullptr ? 0 : (int)(*memberExtensions)[member].size();
194     }
getMemberExtensions(int member)195     virtual const char** getMemberExtensions(int member) const { return (*memberExtensions)[member].data(); }
196 
197     virtual void dump(TInfoSink& infoSink, bool complete = false) const;
198 
199 protected:
200     explicit TVariable(const TVariable&);
201     TVariable& operator=(const TVariable&);
202 
203     TType type;
204     bool userType;
205 
206     // we are assuming that Pool Allocator will free the memory allocated to unionArray
207     // when this object is destroyed
208 
209     TConstUnionArray constArray;               // for compile-time constant value
210     TIntermTyped* constSubtree;                // for specialization constant computation
211     TVector<TExtensionList>* memberExtensions; // per-member extension list, allocated only when needed
212     int anonId; // the ID used for anonymous blocks: TODO: see if uniqueId could serve a dual purpose
213 };
214 
215 //
216 // The function sub-class of symbols and the parser will need to
217 // share this definition of a function parameter.
218 //
219 struct TParameter {
220     TString *name;
221     TType* type;
222     TIntermTyped* defaultValue;
copyParamTParameter223     TParameter& copyParam(const TParameter& param)
224     {
225         if (param.name)
226             name = NewPoolTString(param.name->c_str());
227         else
228             name = nullptr;
229         type = param.type->clone();
230         defaultValue = param.defaultValue;
231         return *this;
232     }
getDeclaredBuiltInTParameter233     TBuiltInVariable getDeclaredBuiltIn() const { return type->getQualifier().declaredBuiltIn; }
234 };
235 
236 //
237 // The function sub-class of a symbol.
238 //
239 class TFunction : public TSymbol {
240 public:
TFunction(TOperator o)241     explicit TFunction(TOperator o) :
242         TSymbol(nullptr),
243         op(o),
244         defined(false), prototyped(false), implicitThis(false), illegalImplicitThis(false), defaultParamCount(0) { }
245     TFunction(const TString *name, const TType& retType, TOperator tOp = EOpNull) :
TSymbol(name)246         TSymbol(name),
247         mangledName(*name + '('),
248         op(tOp),
249         defined(false), prototyped(false), implicitThis(false), illegalImplicitThis(false), defaultParamCount(0),
250         linkType(ELinkNone)
251     {
252         returnType.shallowCopy(retType);
253         declaredBuiltIn = retType.getQualifier().builtIn;
254     }
255     virtual TFunction* clone() const override;
256     virtual ~TFunction();
257 
getAsFunction()258     virtual TFunction* getAsFunction() override { return this; }
getAsFunction()259     virtual const TFunction* getAsFunction() const override { return this; }
260 
261     // Install 'p' as the (non-'this') last parameter.
262     // Non-'this' parameters are reflected in both the list of parameters and the
263     // mangled name.
addParameter(TParameter & p)264     virtual void addParameter(TParameter& p)
265     {
266         assert(writable);
267         parameters.push_back(p);
268         p.type->appendMangledName(mangledName);
269 
270         if (p.defaultValue != nullptr)
271             defaultParamCount++;
272     }
273 
274     // Install 'this' as the first parameter.
275     // 'this' is reflected in the list of parameters, but not the mangled name.
addThisParameter(TType & type,const char * name)276     virtual void addThisParameter(TType& type, const char* name)
277     {
278         TParameter p = { NewPoolTString(name), new TType, nullptr };
279         p.type->shallowCopy(type);
280         parameters.insert(parameters.begin(), p);
281     }
282 
addPrefix(const char * prefix)283     virtual void addPrefix(const char* prefix) override
284     {
285         TSymbol::addPrefix(prefix);
286         mangledName.insert(0, prefix);
287     }
288 
removePrefix(const TString & prefix)289     virtual void removePrefix(const TString& prefix)
290     {
291         assert(mangledName.compare(0, prefix.size(), prefix) == 0);
292         mangledName.erase(0, prefix.size());
293     }
294 
getMangledName()295     virtual const TString& getMangledName() const override { return mangledName; }
getType()296     virtual const TType& getType() const override { return returnType; }
getDeclaredBuiltInType()297     virtual TBuiltInVariable getDeclaredBuiltInType() const { return declaredBuiltIn; }
getWritableType()298     virtual TType& getWritableType() override { return returnType; }
relateToOperator(TOperator o)299     virtual void relateToOperator(TOperator o) { assert(writable); op = o; }
getBuiltInOp()300     virtual TOperator getBuiltInOp() const { return op; }
setDefined()301     virtual void setDefined() { assert(writable); defined = true; }
isDefined()302     virtual bool isDefined() const { return defined; }
setPrototyped()303     virtual void setPrototyped() { assert(writable); prototyped = true; }
isPrototyped()304     virtual bool isPrototyped() const { return prototyped; }
setImplicitThis()305     virtual void setImplicitThis() { assert(writable); implicitThis = true; }
hasImplicitThis()306     virtual bool hasImplicitThis() const { return implicitThis; }
setIllegalImplicitThis()307     virtual void setIllegalImplicitThis() { assert(writable); illegalImplicitThis = true; }
hasIllegalImplicitThis()308     virtual bool hasIllegalImplicitThis() const { return illegalImplicitThis; }
309 
310     // Return total number of parameters
getParamCount()311     virtual int getParamCount() const { return static_cast<int>(parameters.size()); }
312     // Return number of parameters with default values.
getDefaultParamCount()313     virtual int getDefaultParamCount() const { return defaultParamCount; }
314     // Return number of fixed parameters (without default values)
getFixedParamCount()315     virtual int getFixedParamCount() const { return getParamCount() - getDefaultParamCount(); }
316 
317     virtual TParameter& operator[](int i) { assert(writable); return parameters[i]; }
318     virtual const TParameter& operator[](int i) const { return parameters[i]; }
getQualifier()319     const TQualifier& getQualifier() const { return returnType.getQualifier(); }
320 
setSpirvInstruction(const TSpirvInstruction & inst)321     virtual void setSpirvInstruction(const TSpirvInstruction& inst)
322     {
323         relateToOperator(EOpSpirvInst);
324         spirvInst = inst;
325     }
getSpirvInstruction()326     virtual const TSpirvInstruction& getSpirvInstruction() const { return spirvInst; }
327 
328     virtual void dump(TInfoSink& infoSink, bool complete = false) const override;
329 
setExport()330     void setExport() { linkType = ELinkExport; }
getLinkType()331     TLinkType getLinkType() const { return linkType; }
332 
333 protected:
334     explicit TFunction(const TFunction&);
335     TFunction& operator=(const TFunction&);
336 
337     typedef TVector<TParameter> TParamList;
338     TParamList parameters;
339     TType returnType;
340     TBuiltInVariable declaredBuiltIn;
341 
342     TString mangledName;
343     TOperator op;
344     bool defined;
345     bool prototyped;
346     bool implicitThis;         // True if this function is allowed to see all members of 'this'
347     bool illegalImplicitThis;  // True if this function is not supposed to have access to dynamic members of 'this',
348                                // even if it finds member variables in the symbol table.
349                                // This is important for a static member function that has member variables in scope,
350                                // but is not allowed to use them, or see hidden symbols instead.
351     int  defaultParamCount;
352 
353     TSpirvInstruction spirvInst; // SPIR-V instruction qualifiers
354     TLinkType linkType;
355 };
356 
357 //
358 // Members of anonymous blocks are a kind of TSymbol.  They are not hidden in
359 // the symbol table behind a container; rather they are visible and point to
360 // their anonymous container.  (The anonymous container is found through the
361 // member, not the other way around.)
362 //
363 class TAnonMember : public TSymbol {
364 public:
TAnonMember(const TString * n,unsigned int m,TVariable & a,int an)365     TAnonMember(const TString* n, unsigned int m, TVariable& a, int an) : TSymbol(n), anonContainer(a), memberNumber(m), anonId(an) { }
366     virtual TAnonMember* clone() const override;
~TAnonMember()367     virtual ~TAnonMember() { }
368 
getAsAnonMember()369     virtual const TAnonMember* getAsAnonMember() const override { return this; }
getAnonContainer()370     virtual const TVariable& getAnonContainer() const { return anonContainer; }
getMemberNumber()371     virtual unsigned int getMemberNumber() const { return memberNumber; }
372 
getType()373     virtual const TType& getType() const override
374     {
375         const TTypeList& types = *anonContainer.getType().getStruct();
376         return *types[memberNumber].type;
377     }
378 
getWritableType()379     virtual TType& getWritableType() override
380     {
381         assert(writable);
382         const TTypeList& types = *anonContainer.getType().getStruct();
383         return *types[memberNumber].type;
384     }
385 
setExtensions(int numExts,const char * const exts[])386     virtual void setExtensions(int numExts, const char* const exts[]) override
387     {
388         anonContainer.setMemberExtensions(memberNumber, numExts, exts);
389     }
getNumExtensions()390     virtual int getNumExtensions() const override { return anonContainer.getNumMemberExtensions(memberNumber); }
getExtensions()391     virtual const char** getExtensions() const override { return anonContainer.getMemberExtensions(memberNumber); }
392 
getAnonId()393     virtual int getAnonId() const { return anonId; }
394     virtual void dump(TInfoSink& infoSink, bool complete = false) const override;
395 
396 protected:
397     explicit TAnonMember(const TAnonMember&);
398     TAnonMember& operator=(const TAnonMember&);
399 
400     TVariable& anonContainer;
401     unsigned int memberNumber;
402     int anonId;
403 };
404 
405 class TSymbolTableLevel {
406 public:
POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator ())407     POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
408     TSymbolTableLevel() : defaultPrecision(nullptr), anonId(0), thisLevel(false) { }
409     ~TSymbolTableLevel();
410 
insert(const TString & name,TSymbol * symbol)411     bool insert(const TString& name, TSymbol* symbol) {
412         return level.insert(tLevelPair(name, symbol)).second;
413     }
414 
415     bool insert(TSymbol& symbol, bool separateNameSpaces, const TString& forcedKeyName = TString())
416     {
417         //
418         // returning true means symbol was added to the table with no semantic errors
419         //
420         const TString& name = symbol.getName();
421         if (forcedKeyName.length()) {
422             return level.insert(tLevelPair(forcedKeyName, &symbol)).second;
423         }
424         else if (name == "") {
425             symbol.getAsVariable()->setAnonId(anonId++);
426             // An empty name means an anonymous container, exposing its members to the external scope.
427             // Give it a name and insert its members in the symbol table, pointing to the container.
428             char buf[20];
429             snprintf(buf, 20, "%s%d", AnonymousPrefix, symbol.getAsVariable()->getAnonId());
430             symbol.changeName(NewPoolTString(buf));
431 
432             return insertAnonymousMembers(symbol, 0);
433         } else {
434             // Check for redefinition errors:
435             // - STL itself will tell us if there is a direct name collision, with name mangling, at this level
436             // - additionally, check for function-redefining-variable name collisions
437             const TString& insertName = symbol.getMangledName();
438             if (symbol.getAsFunction()) {
439                 // make sure there isn't a variable of this name
440                 if (! separateNameSpaces && level.find(name) != level.end())
441                     return false;
442 
443                 // insert, and whatever happens is okay
444                 level.insert(tLevelPair(insertName, &symbol));
445 
446                 return true;
447             } else
448                 return level.insert(tLevelPair(insertName, &symbol)).second;
449         }
450     }
451 
452     // Add more members to an already inserted aggregate object
amend(TSymbol & symbol,int firstNewMember)453     bool amend(TSymbol& symbol, int firstNewMember)
454     {
455         // See insert() for comments on basic explanation of insert.
456         // This operates similarly, but more simply.
457         // Only supporting amend of anonymous blocks so far.
458         if (IsAnonymous(symbol.getName()))
459             return insertAnonymousMembers(symbol, firstNewMember);
460         else
461             return false;
462     }
463 
insertAnonymousMembers(TSymbol & symbol,int firstMember)464     bool insertAnonymousMembers(TSymbol& symbol, int firstMember)
465     {
466         const TTypeList& types = *symbol.getAsVariable()->getType().getStruct();
467         for (unsigned int m = firstMember; m < types.size(); ++m) {
468             TAnonMember* member = new TAnonMember(&types[m].type->getFieldName(), m, *symbol.getAsVariable(), symbol.getAsVariable()->getAnonId());
469             if (! level.insert(tLevelPair(member->getMangledName(), member)).second)
470                 return false;
471         }
472 
473         return true;
474     }
475 
retargetSymbol(const TString & from,const TString & to)476     void retargetSymbol(const TString& from, const TString& to) {
477         tLevel::const_iterator fromIt = level.find(from);
478         tLevel::const_iterator toIt = level.find(to);
479         if (fromIt == level.end() || toIt == level.end())
480             return;
481         delete fromIt->second;
482         level[from] = toIt->second;
483         retargetedSymbols.push_back({from, to});
484     }
485 
find(const TString & name)486     TSymbol* find(const TString& name) const
487     {
488         tLevel::const_iterator it = level.find(name);
489         if (it == level.end())
490             return nullptr;
491         else
492             return (*it).second;
493     }
494 
findFunctionNameList(const TString & name,TVector<const TFunction * > & list)495     void findFunctionNameList(const TString& name, TVector<const TFunction*>& list)
496     {
497         size_t parenAt = name.find_first_of('(');
498         TString base(name, 0, parenAt + 1);
499 
500         tLevel::const_iterator begin = level.lower_bound(base);
501         base[parenAt] = ')';  // assume ')' is lexically after '('
502         tLevel::const_iterator end = level.upper_bound(base);
503         for (tLevel::const_iterator it = begin; it != end; ++it)
504             list.push_back(it->second->getAsFunction());
505     }
506 
507     // See if there is already a function in the table having the given non-function-style name.
hasFunctionName(const TString & name)508     bool hasFunctionName(const TString& name) const
509     {
510         tLevel::const_iterator candidate = level.lower_bound(name);
511         if (candidate != level.end()) {
512             const TString& candidateName = (*candidate).first;
513             TString::size_type parenAt = candidateName.find_first_of('(');
514             if (parenAt != candidateName.npos && candidateName.compare(0, parenAt, name) == 0)
515 
516                 return true;
517         }
518 
519         return false;
520     }
521 
522     // See if there is a variable at this level having the given non-function-style name.
523     // Return true if name is found, and set variable to true if the name was a variable.
findFunctionVariableName(const TString & name,bool & variable)524     bool findFunctionVariableName(const TString& name, bool& variable) const
525     {
526         tLevel::const_iterator candidate = level.lower_bound(name);
527         if (candidate != level.end()) {
528             const TString& candidateName = (*candidate).first;
529             TString::size_type parenAt = candidateName.find_first_of('(');
530             if (parenAt == candidateName.npos) {
531                 // not a mangled name
532                 if (candidateName == name) {
533                     // found a variable name match
534                     variable = true;
535                     return true;
536                 }
537             } else {
538                 // a mangled name
539                 if (candidateName.compare(0, parenAt, name) == 0) {
540                     // found a function name match
541                     variable = false;
542                     return true;
543                 }
544             }
545         }
546 
547         return false;
548     }
549 
550     // Use this to do a lazy 'push' of precision defaults the first time
551     // a precision statement is seen in a new scope.  Leave it at 0 for
552     // when no push was needed.  Thus, it is not the current defaults,
553     // it is what to restore the defaults to when popping a level.
setPreviousDefaultPrecisions(const TPrecisionQualifier * p)554     void setPreviousDefaultPrecisions(const TPrecisionQualifier *p)
555     {
556         // can call multiple times at one scope, will only latch on first call,
557         // as we're tracking the previous scope's values, not the current values
558         if (defaultPrecision != nullptr)
559             return;
560 
561         defaultPrecision = new TPrecisionQualifier[EbtNumTypes];
562         for (int t = 0; t < EbtNumTypes; ++t)
563             defaultPrecision[t] = p[t];
564     }
565 
getPreviousDefaultPrecisions(TPrecisionQualifier * p)566     void getPreviousDefaultPrecisions(TPrecisionQualifier *p)
567     {
568         // can be called for table level pops that didn't set the
569         // defaults
570         if (defaultPrecision == nullptr || p == nullptr)
571             return;
572 
573         for (int t = 0; t < EbtNumTypes; ++t)
574             p[t] = defaultPrecision[t];
575     }
576 
577     void relateToOperator(const char* name, TOperator op);
578     void setFunctionExtensions(const char* name, int num, const char* const extensions[]);
579     void setSingleFunctionExtensions(const char* name, int num, const char* const extensions[]);
580     void dump(TInfoSink& infoSink, bool complete = false) const;
581     TSymbolTableLevel* clone() const;
582     void readOnly();
583 
setThisLevel()584     void setThisLevel() { thisLevel = true; }
isThisLevel()585     bool isThisLevel() const { return thisLevel; }
586 
587 protected:
588     explicit TSymbolTableLevel(TSymbolTableLevel&);
589     TSymbolTableLevel& operator=(TSymbolTableLevel&);
590 
591     typedef std::map<TString, TSymbol*, std::less<TString>, pool_allocator<std::pair<const TString, TSymbol*> > > tLevel;
592     typedef const tLevel::value_type tLevelPair;
593     typedef std::pair<tLevel::iterator, bool> tInsertResult;
594 
595     tLevel level;  // named mappings
596     TPrecisionQualifier *defaultPrecision;
597     // pair<FromName, ToName>
598     TVector<std::pair<TString, TString>> retargetedSymbols;
599     int anonId;
600     bool thisLevel;  // True if this level of the symbol table is a structure scope containing member function
601                      // that are supposed to see anonymous access to member variables.
602 };
603 
604 class TSymbolTable {
605 public:
TSymbolTable()606     TSymbolTable() : uniqueId(0), noBuiltInRedeclarations(false), separateNameSpaces(false), adoptedLevels(0)
607     {
608         //
609         // This symbol table cannot be used until push() is called.
610         //
611     }
~TSymbolTable()612     ~TSymbolTable()
613     {
614         // this can be called explicitly; safest to code it so it can be called multiple times
615 
616         // don't deallocate levels passed in from elsewhere
617         while (table.size() > adoptedLevels)
618             pop(nullptr);
619     }
620 
adoptLevels(TSymbolTable & symTable)621     void adoptLevels(TSymbolTable& symTable)
622     {
623         for (unsigned int level = 0; level < symTable.table.size(); ++level) {
624             table.push_back(symTable.table[level]);
625             ++adoptedLevels;
626         }
627         uniqueId = symTable.uniqueId;
628         noBuiltInRedeclarations = symTable.noBuiltInRedeclarations;
629         separateNameSpaces = symTable.separateNameSpaces;
630     }
631 
632     //
633     // While level adopting is generic, the methods below enact a the following
634     // convention for levels:
635     //   0: common built-ins shared across all stages, all compiles, only one copy for all symbol tables
636     //   1: per-stage built-ins, shared across all compiles, but a different copy per stage
637     //   2: built-ins specific to a compile, like resources that are context-dependent, or redeclared built-ins
638     //   3: user-shader globals
639     //
640 protected:
641     static const uint32_t LevelFlagBitOffset = 56;
642     static const int globalLevel = 3;
isSharedLevel(int level)643     static bool isSharedLevel(int level)  { return level <= 1; }            // exclude all per-compile levels
isBuiltInLevel(int level)644     static bool isBuiltInLevel(int level) { return level <= 2; }            // exclude user globals
isGlobalLevel(int level)645     static bool isGlobalLevel(int level)  { return level <= globalLevel; }  // include user globals
646 public:
isEmpty()647     bool isEmpty() { return table.size() == 0; }
atBuiltInLevel()648     bool atBuiltInLevel() { return isBuiltInLevel(currentLevel()); }
atGlobalLevel()649     bool atGlobalLevel()  { return isGlobalLevel(currentLevel()); }
isBuiltInSymbol(long long uniqueId)650     static bool isBuiltInSymbol(long long uniqueId) {
651         int level = static_cast<int>(uniqueId >> LevelFlagBitOffset);
652         return isBuiltInLevel(level);
653     }
654     static constexpr uint64_t uniqueIdMask = (1LL << LevelFlagBitOffset) - 1;
655     static const uint32_t MaxLevelInUniqueID = 127;
setNoBuiltInRedeclarations()656     void setNoBuiltInRedeclarations() { noBuiltInRedeclarations = true; }
setSeparateNameSpaces()657     void setSeparateNameSpaces() { separateNameSpaces = true; }
658 
push()659     void push()
660     {
661         table.push_back(new TSymbolTableLevel);
662         updateUniqueIdLevelFlag();
663     }
664 
665     // Make a new symbol-table level to represent the scope introduced by a structure
666     // containing member functions, such that the member functions can find anonymous
667     // references to member variables.
668     //
669     // 'thisSymbol' should have a name of "" to trigger anonymous structure-member
670     // symbol finds.
pushThis(TSymbol & thisSymbol)671     void pushThis(TSymbol& thisSymbol)
672     {
673         assert(thisSymbol.getName().size() == 0);
674         table.push_back(new TSymbolTableLevel);
675         updateUniqueIdLevelFlag();
676         table.back()->setThisLevel();
677         insert(thisSymbol);
678     }
679 
pop(TPrecisionQualifier * p)680     void pop(TPrecisionQualifier *p)
681     {
682         table[currentLevel()]->getPreviousDefaultPrecisions(p);
683         delete table.back();
684         table.pop_back();
685         updateUniqueIdLevelFlag();
686     }
687 
688     //
689     // Insert a visible symbol into the symbol table so it can
690     // be found later by name.
691     //
692     // Returns false if the was a name collision.
693     //
insert(TSymbol & symbol)694     bool insert(TSymbol& symbol)
695     {
696         symbol.setUniqueId(++uniqueId);
697 
698         // make sure there isn't a function of this variable name
699         if (! separateNameSpaces && ! symbol.getAsFunction() && table[currentLevel()]->hasFunctionName(symbol.getName()))
700             return false;
701 
702         // check for not overloading or redefining a built-in function
703         if (noBuiltInRedeclarations) {
704             if (atGlobalLevel() && currentLevel() > 0) {
705                 if (table[0]->hasFunctionName(symbol.getName()))
706                     return false;
707                 if (currentLevel() > 1 && table[1]->hasFunctionName(symbol.getName()))
708                     return false;
709             }
710         }
711 
712         return table[currentLevel()]->insert(symbol, separateNameSpaces);
713     }
714 
715     // Add more members to an already inserted aggregate object
amend(TSymbol & symbol,int firstNewMember)716     bool amend(TSymbol& symbol, int firstNewMember)
717     {
718         // See insert() for comments on basic explanation of insert.
719         // This operates similarly, but more simply.
720         return table[currentLevel()]->amend(symbol, firstNewMember);
721     }
722 
723     // Update the level info in symbol's unique ID to current level
amendSymbolIdLevel(TSymbol & symbol)724     void amendSymbolIdLevel(TSymbol& symbol)
725     {
726         // clamp level to avoid overflow
727         uint64_t level = (uint32_t)currentLevel() > MaxLevelInUniqueID ? MaxLevelInUniqueID : currentLevel();
728         uint64_t symbolId = symbol.getUniqueId();
729         symbolId &= uniqueIdMask;
730         symbolId |= (level << LevelFlagBitOffset);
731         symbol.setUniqueId(symbolId);
732     }
733     //
734     // To allocate an internal temporary, which will need to be uniquely
735     // identified by the consumer of the AST, but never need to
736     // found by doing a symbol table search by name, hence allowed an
737     // arbitrary name in the symbol with no worry of collision.
738     //
makeInternalVariable(TSymbol & symbol)739     void makeInternalVariable(TSymbol& symbol)
740     {
741         symbol.setUniqueId(++uniqueId);
742     }
743 
744     //
745     // Copy a variable or anonymous member's structure from a shared level so that
746     // it can be added (soon after return) to the symbol table where it can be
747     // modified without impacting other users of the shared table.
748     //
copyUpDeferredInsert(TSymbol * shared)749     TSymbol* copyUpDeferredInsert(TSymbol* shared)
750     {
751         if (shared->getAsVariable()) {
752             TSymbol* copy = shared->clone();
753             copy->setUniqueId(shared->getUniqueId());
754             return copy;
755         } else {
756             const TAnonMember* anon = shared->getAsAnonMember();
757             assert(anon);
758             TVariable* container = anon->getAnonContainer().clone();
759             container->changeName(NewPoolTString(""));
760             container->setUniqueId(anon->getAnonContainer().getUniqueId());
761             return container;
762         }
763     }
764 
copyUp(TSymbol * shared)765     TSymbol* copyUp(TSymbol* shared)
766     {
767         TSymbol* copy = copyUpDeferredInsert(shared);
768         table[globalLevel]->insert(*copy, separateNameSpaces);
769         if (shared->getAsVariable())
770             return copy;
771         else {
772             // return the copy of the anonymous member
773             return table[globalLevel]->find(shared->getName());
774         }
775     }
776 
777     // Normal find of a symbol, that can optionally say whether the symbol was found
778     // at a built-in level or the current top-scope level.
779     TSymbol* find(const TString& name, bool* builtIn = nullptr, bool* currentScope = nullptr, int* thisDepthP = nullptr)
780     {
781         int level = currentLevel();
782         TSymbol* symbol;
783         int thisDepth = 0;
784         do {
785             if (table[level]->isThisLevel())
786                 ++thisDepth;
787             symbol = table[level]->find(name);
788             --level;
789         } while (symbol == nullptr && level >= 0);
790         level++;
791         if (builtIn)
792             *builtIn = isBuiltInLevel(level);
793         if (currentScope)
794             *currentScope = isGlobalLevel(currentLevel()) || level == currentLevel();  // consider shared levels as "current scope" WRT user globals
795         if (thisDepthP != nullptr) {
796             if (! table[level]->isThisLevel())
797                 thisDepth = 0;
798             *thisDepthP = thisDepth;
799         }
800 
801         return symbol;
802     }
803 
retargetSymbol(const TString & from,const TString & to)804     void retargetSymbol(const TString& from, const TString& to) {
805         int level = currentLevel();
806         table[level]->retargetSymbol(from, to);
807     }
808 
809 
810     // Find of a symbol that returns how many layers deep of nested
811     // structures-with-member-functions ('this' scopes) deep the symbol was
812     // found in.
find(const TString & name,int & thisDepth)813     TSymbol* find(const TString& name, int& thisDepth)
814     {
815         int level = currentLevel();
816         TSymbol* symbol;
817         thisDepth = 0;
818         do {
819             if (table[level]->isThisLevel())
820                 ++thisDepth;
821             symbol = table[level]->find(name);
822             --level;
823         } while (symbol == nullptr && level >= 0);
824 
825         if (! table[level + 1]->isThisLevel())
826             thisDepth = 0;
827 
828         return symbol;
829     }
830 
isFunctionNameVariable(const TString & name)831     bool isFunctionNameVariable(const TString& name) const
832     {
833         if (separateNameSpaces)
834             return false;
835 
836         int level = currentLevel();
837         do {
838             bool variable;
839             bool found = table[level]->findFunctionVariableName(name, variable);
840             if (found)
841                 return variable;
842             --level;
843         } while (level >= 0);
844 
845         return false;
846     }
847 
findFunctionNameList(const TString & name,TVector<const TFunction * > & list,bool & builtIn)848     void findFunctionNameList(const TString& name, TVector<const TFunction*>& list, bool& builtIn)
849     {
850         // For user levels, return the set found in the first scope with a match
851         builtIn = false;
852         int level = currentLevel();
853         do {
854             table[level]->findFunctionNameList(name, list);
855             --level;
856         } while (list.empty() && level >= globalLevel);
857 
858         if (! list.empty())
859             return;
860 
861         // Gather across all built-in levels; they don't hide each other
862         builtIn = true;
863         do {
864             table[level]->findFunctionNameList(name, list);
865             --level;
866         } while (level >= 0);
867     }
868 
relateToOperator(const char * name,TOperator op)869     void relateToOperator(const char* name, TOperator op)
870     {
871         for (unsigned int level = 0; level < table.size(); ++level)
872             table[level]->relateToOperator(name, op);
873     }
874 
setFunctionExtensions(const char * name,int num,const char * const extensions[])875     void setFunctionExtensions(const char* name, int num, const char* const extensions[])
876     {
877         for (unsigned int level = 0; level < table.size(); ++level)
878             table[level]->setFunctionExtensions(name, num, extensions);
879     }
880 
setSingleFunctionExtensions(const char * name,int num,const char * const extensions[])881     void setSingleFunctionExtensions(const char* name, int num, const char* const extensions[])
882     {
883         for (unsigned int level = 0; level < table.size(); ++level)
884             table[level]->setSingleFunctionExtensions(name, num, extensions);
885     }
886 
setVariableExtensions(const char * name,int numExts,const char * const extensions[])887     void setVariableExtensions(const char* name, int numExts, const char* const extensions[])
888     {
889         TSymbol* symbol = find(TString(name));
890         if (symbol == nullptr)
891             return;
892 
893         symbol->setExtensions(numExts, extensions);
894     }
895 
setVariableExtensions(const char * blockName,const char * name,int numExts,const char * const extensions[])896     void setVariableExtensions(const char* blockName, const char* name, int numExts, const char* const extensions[])
897     {
898         TSymbol* symbol = find(TString(blockName));
899         if (symbol == nullptr)
900             return;
901         TVariable* variable = symbol->getAsVariable();
902         assert(variable != nullptr);
903 
904         const TTypeList& structure = *variable->getAsVariable()->getType().getStruct();
905         for (int member = 0; member < (int)structure.size(); ++member) {
906             if (structure[member].type->getFieldName().compare(name) == 0) {
907                 variable->setMemberExtensions(member, numExts, extensions);
908                 return;
909             }
910         }
911     }
912 
getMaxSymbolId()913     long long getMaxSymbolId() { return uniqueId; }
914     void dump(TInfoSink& infoSink, bool complete = false) const;
915     void copyTable(const TSymbolTable& copyOf);
916 
setPreviousDefaultPrecisions(TPrecisionQualifier * p)917     void setPreviousDefaultPrecisions(TPrecisionQualifier *p) { table[currentLevel()]->setPreviousDefaultPrecisions(p); }
918 
readOnly()919     void readOnly()
920     {
921         for (unsigned int level = 0; level < table.size(); ++level)
922             table[level]->readOnly();
923     }
924 
925     // Add current level in the high-bits of unique id
updateUniqueIdLevelFlag()926     void updateUniqueIdLevelFlag() {
927         // clamp level to avoid overflow
928         uint64_t level = (uint32_t)currentLevel() > MaxLevelInUniqueID ? MaxLevelInUniqueID : currentLevel();
929         uniqueId &= uniqueIdMask;
930         uniqueId |= (level << LevelFlagBitOffset);
931     }
932 
overwriteUniqueId(long long id)933     void overwriteUniqueId(long long id)
934     {
935         uniqueId = id;
936         updateUniqueIdLevelFlag();
937     }
938 
939 protected:
940     TSymbolTable(TSymbolTable&);
941     TSymbolTable& operator=(TSymbolTableLevel&);
942 
currentLevel()943     int currentLevel() const { return static_cast<int>(table.size()) - 1; }
944     std::vector<TSymbolTableLevel*> table;
945     long long uniqueId;     // for unique identification in code generation
946     bool noBuiltInRedeclarations;
947     bool separateNameSpaces;
948     unsigned int adoptedLevels;
949 };
950 
951 } // end namespace glslang
952 
953 #endif // _SYMBOL_TABLE_INCLUDED_
954