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), extensions(0), 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 0; }
getAsFunction()101     virtual const TFunction* getAsFunction() const { return 0; }
getAsVariable()102     virtual TVariable* getAsVariable() { return 0; }
getAsVariable()103     virtual const TVariable* getAsVariable() const { return 0; }
getAsAnonMember()104     virtual const TAnonMember* getAsAnonMember() const { return 0; }
105     virtual const TType& getType() const = 0;
106     virtual TType& getWritableType() = 0;
setUniqueId(int id)107     virtual void setUniqueId(int id) { uniqueId = id; }
getUniqueId()108     virtual int 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 == 0);
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     virtual void dump(TInfoSink& infoSink, bool complete = false) const = 0;
120     void dumpExtensions(TInfoSink& infoSink) const;
121 
isReadOnly()122     virtual bool isReadOnly() const { return ! writable; }
makeReadOnly()123     virtual void makeReadOnly() { writable = false; }
124 
125 protected:
126     explicit TSymbol(const TSymbol&);
127     TSymbol& operator=(const TSymbol&);
128 
129     const TString *name;
130     unsigned int uniqueId;      // For cross-scope comparing during code generation
131 
132     // For tracking what extensions must be present
133     // (don't use if correct version/profile is present).
134     TExtensionList* extensions; // an array of pointers to existing constant char strings
135 
136     //
137     // N.B.: Non-const functions that will be generally used should assert on this,
138     // to avoid overwriting shared symbol-table information.
139     //
140     bool writable;
141 };
142 
143 //
144 // Variable class, meaning a symbol that's not a function.
145 //
146 // There could be a separate class hierarchy for Constant variables;
147 // Only one of int, bool, or float, (or none) is correct for
148 // any particular use, but it's easy to do this way, and doesn't
149 // seem worth having separate classes, and "getConst" can't simply return
150 // different values for different types polymorphically, so this is
151 // just simple and pragmatic.
152 //
153 class TVariable : public TSymbol {
154 public:
155     TVariable(const TString *name, const TType& t, bool uT = false )
TSymbol(name)156         : TSymbol(name),
157           userType(uT),
158           constSubtree(nullptr),
159           memberExtensions(nullptr),
160           anonId(-1)
161         { type.shallowCopy(t); }
162     virtual TVariable* clone() const;
~TVariable()163     virtual ~TVariable() { }
164 
getAsVariable()165     virtual TVariable* getAsVariable() { return this; }
getAsVariable()166     virtual const TVariable* getAsVariable() const { return this; }
getType()167     virtual const TType& getType() const { return type; }
getWritableType()168     virtual TType& getWritableType() { assert(writable); return type; }
isUserType()169     virtual bool isUserType() const { return userType; }
getConstArray()170     virtual const TConstUnionArray& getConstArray() const { return constArray; }
getWritableConstArray()171     virtual TConstUnionArray& getWritableConstArray() { assert(writable); return constArray; }
setConstArray(const TConstUnionArray & array)172     virtual void setConstArray(const TConstUnionArray& array) { constArray = array; }
setConstSubtree(TIntermTyped * subtree)173     virtual void setConstSubtree(TIntermTyped* subtree) { constSubtree = subtree; }
getConstSubtree()174     virtual TIntermTyped* getConstSubtree() const { return constSubtree; }
setAnonId(int i)175     virtual void setAnonId(int i) { anonId = i; }
getAnonId()176     virtual int getAnonId() const { return anonId; }
177 
setMemberExtensions(int member,int numExts,const char * const exts[])178     virtual void setMemberExtensions(int member, int numExts, const char* const exts[])
179     {
180         assert(type.isStruct());
181         assert(numExts > 0);
182         if (memberExtensions == nullptr) {
183             memberExtensions = NewPoolObject(memberExtensions);
184             memberExtensions->resize(type.getStruct()->size());
185         }
186         for (int e = 0; e < numExts; ++e)
187             (*memberExtensions)[member].push_back(exts[e]);
188     }
hasMemberExtensions()189     virtual bool hasMemberExtensions() const { return memberExtensions != nullptr; }
getNumMemberExtensions(int member)190     virtual int getNumMemberExtensions(int member) const
191     {
192         return memberExtensions == nullptr ? 0 : (int)(*memberExtensions)[member].size();
193     }
getMemberExtensions(int member)194     virtual const char** getMemberExtensions(int member) const { return (*memberExtensions)[member].data(); }
195 
196     virtual void dump(TInfoSink& infoSink, bool complete = false) const;
197 
198 protected:
199     explicit TVariable(const TVariable&);
200     TVariable& operator=(const TVariable&);
201 
202     TType type;
203     bool userType;
204 
205     // we are assuming that Pool Allocator will free the memory allocated to unionArray
206     // when this object is destroyed
207 
208     TConstUnionArray constArray;               // for compile-time constant value
209     TIntermTyped* constSubtree;                // for specialization constant computation
210     TVector<TExtensionList>* memberExtensions; // per-member extension list, allocated only when needed
211     int anonId; // the ID used for anonymous blocks: TODO: see if uniqueId could serve a dual purpose
212 };
213 
214 //
215 // The function sub-class of symbols and the parser will need to
216 // share this definition of a function parameter.
217 //
218 struct TParameter {
219     TString *name;
220     TType* type;
221     TIntermTyped* defaultValue;
copyParamTParameter222     void copyParam(const TParameter& param)
223     {
224         if (param.name)
225             name = NewPoolTString(param.name->c_str());
226         else
227             name = 0;
228         type = param.type->clone();
229         defaultValue = param.defaultValue;
230     }
getDeclaredBuiltInTParameter231     TBuiltInVariable getDeclaredBuiltIn() const { return type->getQualifier().declaredBuiltIn; }
232 };
233 
234 //
235 // The function sub-class of a symbol.
236 //
237 class TFunction : public TSymbol {
238 public:
TFunction(TOperator o)239     explicit TFunction(TOperator o) :
240         TSymbol(0),
241         op(o),
242         defined(false), prototyped(false), implicitThis(false), illegalImplicitThis(false), defaultParamCount(0) { }
243     TFunction(const TString *name, const TType& retType, TOperator tOp = EOpNull) :
TSymbol(name)244         TSymbol(name),
245         mangledName(*name + '('),
246         op(tOp),
247         defined(false), prototyped(false), implicitThis(false), illegalImplicitThis(false), defaultParamCount(0)
248     {
249         returnType.shallowCopy(retType);
250         declaredBuiltIn = retType.getQualifier().builtIn;
251     }
252     virtual TFunction* clone() const override;
253     virtual ~TFunction();
254 
getAsFunction()255     virtual TFunction* getAsFunction() override { return this; }
getAsFunction()256     virtual const TFunction* getAsFunction() const override { return this; }
257 
258     // Install 'p' as the (non-'this') last parameter.
259     // Non-'this' parameters are reflected in both the list of parameters and the
260     // mangled name.
addParameter(TParameter & p)261     virtual void addParameter(TParameter& p)
262     {
263         assert(writable);
264         parameters.push_back(p);
265         p.type->appendMangledName(mangledName);
266 
267         if (p.defaultValue != nullptr)
268             defaultParamCount++;
269     }
270 
271     // Install 'this' as the first parameter.
272     // 'this' is reflected in the list of parameters, but not the mangled name.
addThisParameter(TType & type,const char * name)273     virtual void addThisParameter(TType& type, const char* name)
274     {
275         TParameter p = { NewPoolTString(name), new TType, nullptr };
276         p.type->shallowCopy(type);
277         parameters.insert(parameters.begin(), p);
278     }
279 
addPrefix(const char * prefix)280     virtual void addPrefix(const char* prefix) override
281     {
282         TSymbol::addPrefix(prefix);
283         mangledName.insert(0, prefix);
284     }
285 
removePrefix(const TString & prefix)286     virtual void removePrefix(const TString& prefix)
287     {
288         assert(mangledName.compare(0, prefix.size(), prefix) == 0);
289         mangledName.erase(0, prefix.size());
290     }
291 
getMangledName()292     virtual const TString& getMangledName() const override { return mangledName; }
getType()293     virtual const TType& getType() const override { return returnType; }
getDeclaredBuiltInType()294     virtual TBuiltInVariable getDeclaredBuiltInType() const { return declaredBuiltIn; }
getWritableType()295     virtual TType& getWritableType() override { return returnType; }
relateToOperator(TOperator o)296     virtual void relateToOperator(TOperator o) { assert(writable); op = o; }
getBuiltInOp()297     virtual TOperator getBuiltInOp() const { return op; }
setDefined()298     virtual void setDefined() { assert(writable); defined = true; }
isDefined()299     virtual bool isDefined() const { return defined; }
setPrototyped()300     virtual void setPrototyped() { assert(writable); prototyped = true; }
isPrototyped()301     virtual bool isPrototyped() const { return prototyped; }
setImplicitThis()302     virtual void setImplicitThis() { assert(writable); implicitThis = true; }
hasImplicitThis()303     virtual bool hasImplicitThis() const { return implicitThis; }
setIllegalImplicitThis()304     virtual void setIllegalImplicitThis() { assert(writable); illegalImplicitThis = true; }
hasIllegalImplicitThis()305     virtual bool hasIllegalImplicitThis() const { return illegalImplicitThis; }
306 
307     // Return total number of parameters
getParamCount()308     virtual int getParamCount() const { return static_cast<int>(parameters.size()); }
309     // Return number of parameters with default values.
getDefaultParamCount()310     virtual int getDefaultParamCount() const { return defaultParamCount; }
311     // Return number of fixed parameters (without default values)
getFixedParamCount()312     virtual int getFixedParamCount() const { return getParamCount() - getDefaultParamCount(); }
313 
314     virtual TParameter& operator[](int i) { assert(writable); return parameters[i]; }
315     virtual const TParameter& operator[](int i) const { return parameters[i]; }
316 
317     virtual void dump(TInfoSink& infoSink, bool complete = false) const override;
318 
319 protected:
320     explicit TFunction(const TFunction&);
321     TFunction& operator=(const TFunction&);
322 
323     typedef TVector<TParameter> TParamList;
324     TParamList parameters;
325     TType returnType;
326     TBuiltInVariable declaredBuiltIn;
327 
328     TString mangledName;
329     TOperator op;
330     bool defined;
331     bool prototyped;
332     bool implicitThis;         // True if this function is allowed to see all members of 'this'
333     bool illegalImplicitThis;  // True if this function is not supposed to have access to dynamic members of 'this',
334                                // even if it finds member variables in the symbol table.
335                                // This is important for a static member function that has member variables in scope,
336                                // but is not allowed to use them, or see hidden symbols instead.
337     int  defaultParamCount;
338 };
339 
340 //
341 // Members of anonymous blocks are a kind of TSymbol.  They are not hidden in
342 // the symbol table behind a container; rather they are visible and point to
343 // their anonymous container.  (The anonymous container is found through the
344 // member, not the other way around.)
345 //
346 class TAnonMember : public TSymbol {
347 public:
TAnonMember(const TString * n,unsigned int m,TVariable & a,int an)348     TAnonMember(const TString* n, unsigned int m, TVariable& a, int an) : TSymbol(n), anonContainer(a), memberNumber(m), anonId(an) { }
349     virtual TAnonMember* clone() const override;
~TAnonMember()350     virtual ~TAnonMember() { }
351 
getAsAnonMember()352     virtual const TAnonMember* getAsAnonMember() const override { return this; }
getAnonContainer()353     virtual const TVariable& getAnonContainer() const { return anonContainer; }
getMemberNumber()354     virtual unsigned int getMemberNumber() const { return memberNumber; }
355 
getType()356     virtual const TType& getType() const override
357     {
358         const TTypeList& types = *anonContainer.getType().getStruct();
359         return *types[memberNumber].type;
360     }
361 
getWritableType()362     virtual TType& getWritableType() override
363     {
364         assert(writable);
365         const TTypeList& types = *anonContainer.getType().getStruct();
366         return *types[memberNumber].type;
367     }
368 
setExtensions(int numExts,const char * const exts[])369     virtual void setExtensions(int numExts, const char* const exts[]) override
370     {
371         anonContainer.setMemberExtensions(memberNumber, numExts, exts);
372     }
getNumExtensions()373     virtual int getNumExtensions() const override { return anonContainer.getNumMemberExtensions(memberNumber); }
getExtensions()374     virtual const char** getExtensions() const override { return anonContainer.getMemberExtensions(memberNumber); }
375 
getAnonId()376     virtual int getAnonId() const { return anonId; }
377     virtual void dump(TInfoSink& infoSink, bool complete = false) const override;
378 
379 protected:
380     explicit TAnonMember(const TAnonMember&);
381     TAnonMember& operator=(const TAnonMember&);
382 
383     TVariable& anonContainer;
384     unsigned int memberNumber;
385     int anonId;
386 };
387 
388 class TSymbolTableLevel {
389 public:
POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator ())390     POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
391     TSymbolTableLevel() : defaultPrecision(0), anonId(0), thisLevel(false) { }
392     ~TSymbolTableLevel();
393 
insert(TSymbol & symbol,bool separateNameSpaces)394     bool insert(TSymbol& symbol, bool separateNameSpaces)
395     {
396         //
397         // returning true means symbol was added to the table with no semantic errors
398         //
399         const TString& name = symbol.getName();
400         if (name == "") {
401             symbol.getAsVariable()->setAnonId(anonId++);
402             // An empty name means an anonymous container, exposing its members to the external scope.
403             // Give it a name and insert its members in the symbol table, pointing to the container.
404             char buf[20];
405             snprintf(buf, 20, "%s%d", AnonymousPrefix, symbol.getAsVariable()->getAnonId());
406             symbol.changeName(NewPoolTString(buf));
407 
408             return insertAnonymousMembers(symbol, 0);
409         } else {
410             // Check for redefinition errors:
411             // - STL itself will tell us if there is a direct name collision, with name mangling, at this level
412             // - additionally, check for function-redefining-variable name collisions
413             const TString& insertName = symbol.getMangledName();
414             if (symbol.getAsFunction()) {
415                 // make sure there isn't a variable of this name
416                 if (! separateNameSpaces && level.find(name) != level.end())
417                     return false;
418 
419                 // insert, and whatever happens is okay
420                 level.insert(tLevelPair(insertName, &symbol));
421 
422                 return true;
423             } else
424                 return level.insert(tLevelPair(insertName, &symbol)).second;
425         }
426     }
427 
428     // Add more members to an already inserted aggregate object
amend(TSymbol & symbol,int firstNewMember)429     bool amend(TSymbol& symbol, int firstNewMember)
430     {
431         // See insert() for comments on basic explanation of insert.
432         // This operates similarly, but more simply.
433         // Only supporting amend of anonymous blocks so far.
434         if (IsAnonymous(symbol.getName()))
435             return insertAnonymousMembers(symbol, firstNewMember);
436         else
437             return false;
438     }
439 
insertAnonymousMembers(TSymbol & symbol,int firstMember)440     bool insertAnonymousMembers(TSymbol& symbol, int firstMember)
441     {
442         const TTypeList& types = *symbol.getAsVariable()->getType().getStruct();
443         for (unsigned int m = firstMember; m < types.size(); ++m) {
444             TAnonMember* member = new TAnonMember(&types[m].type->getFieldName(), m, *symbol.getAsVariable(), symbol.getAsVariable()->getAnonId());
445             if (! level.insert(tLevelPair(member->getMangledName(), member)).second)
446                 return false;
447         }
448 
449         return true;
450     }
451 
find(const TString & name)452     TSymbol* find(const TString& name) const
453     {
454         tLevel::const_iterator it = level.find(name);
455         if (it == level.end())
456             return 0;
457         else
458             return (*it).second;
459     }
460 
findFunctionNameList(const TString & name,TVector<const TFunction * > & list)461     void findFunctionNameList(const TString& name, TVector<const TFunction*>& list)
462     {
463         size_t parenAt = name.find_first_of('(');
464         TString base(name, 0, parenAt + 1);
465 
466         tLevel::const_iterator begin = level.lower_bound(base);
467         base[parenAt] = ')';  // assume ')' is lexically after '('
468         tLevel::const_iterator end = level.upper_bound(base);
469         for (tLevel::const_iterator it = begin; it != end; ++it)
470             list.push_back(it->second->getAsFunction());
471     }
472 
473     // See if there is already a function in the table having the given non-function-style name.
hasFunctionName(const TString & name)474     bool hasFunctionName(const TString& name) const
475     {
476         tLevel::const_iterator candidate = level.lower_bound(name);
477         if (candidate != level.end()) {
478             const TString& candidateName = (*candidate).first;
479             TString::size_type parenAt = candidateName.find_first_of('(');
480             if (parenAt != candidateName.npos && candidateName.compare(0, parenAt, name) == 0)
481 
482                 return true;
483         }
484 
485         return false;
486     }
487 
488     // See if there is a variable at this level having the given non-function-style name.
489     // Return true if name is found, and set variable to true if the name was a variable.
findFunctionVariableName(const TString & name,bool & variable)490     bool findFunctionVariableName(const TString& name, bool& variable) const
491     {
492         tLevel::const_iterator candidate = level.lower_bound(name);
493         if (candidate != level.end()) {
494             const TString& candidateName = (*candidate).first;
495             TString::size_type parenAt = candidateName.find_first_of('(');
496             if (parenAt == candidateName.npos) {
497                 // not a mangled name
498                 if (candidateName == name) {
499                     // found a variable name match
500                     variable = true;
501                     return true;
502                 }
503             } else {
504                 // a mangled name
505                 if (candidateName.compare(0, parenAt, name) == 0) {
506                     // found a function name match
507                     variable = false;
508                     return true;
509                 }
510             }
511         }
512 
513         return false;
514     }
515 
516     // Use this to do a lazy 'push' of precision defaults the first time
517     // a precision statement is seen in a new scope.  Leave it at 0 for
518     // when no push was needed.  Thus, it is not the current defaults,
519     // it is what to restore the defaults to when popping a level.
setPreviousDefaultPrecisions(const TPrecisionQualifier * p)520     void setPreviousDefaultPrecisions(const TPrecisionQualifier *p)
521     {
522         // can call multiple times at one scope, will only latch on first call,
523         // as we're tracking the previous scope's values, not the current values
524         if (defaultPrecision != 0)
525             return;
526 
527         defaultPrecision = new TPrecisionQualifier[EbtNumTypes];
528         for (int t = 0; t < EbtNumTypes; ++t)
529             defaultPrecision[t] = p[t];
530     }
531 
getPreviousDefaultPrecisions(TPrecisionQualifier * p)532     void getPreviousDefaultPrecisions(TPrecisionQualifier *p)
533     {
534         // can be called for table level pops that didn't set the
535         // defaults
536         if (defaultPrecision == 0 || p == 0)
537             return;
538 
539         for (int t = 0; t < EbtNumTypes; ++t)
540             p[t] = defaultPrecision[t];
541     }
542 
543     void relateToOperator(const char* name, TOperator op);
544     void setFunctionExtensions(const char* name, int num, const char* const extensions[]);
545     void dump(TInfoSink& infoSink, bool complete = false) const;
546     TSymbolTableLevel* clone() const;
547     void readOnly();
548 
setThisLevel()549     void setThisLevel() { thisLevel = true; }
isThisLevel()550     bool isThisLevel() const { return thisLevel; }
551 
552 protected:
553     explicit TSymbolTableLevel(TSymbolTableLevel&);
554     TSymbolTableLevel& operator=(TSymbolTableLevel&);
555 
556     typedef std::map<TString, TSymbol*, std::less<TString>, pool_allocator<std::pair<const TString, TSymbol*> > > tLevel;
557     typedef const tLevel::value_type tLevelPair;
558     typedef std::pair<tLevel::iterator, bool> tInsertResult;
559 
560     tLevel level;  // named mappings
561     TPrecisionQualifier *defaultPrecision;
562     int anonId;
563     bool thisLevel;  // True if this level of the symbol table is a structure scope containing member function
564                      // that are supposed to see anonymous access to member variables.
565 };
566 
567 class TSymbolTable {
568 public:
TSymbolTable()569     TSymbolTable() : uniqueId(0), noBuiltInRedeclarations(false), separateNameSpaces(false), adoptedLevels(0)
570     {
571         //
572         // This symbol table cannot be used until push() is called.
573         //
574     }
~TSymbolTable()575     ~TSymbolTable()
576     {
577         // this can be called explicitly; safest to code it so it can be called multiple times
578 
579         // don't deallocate levels passed in from elsewhere
580         while (table.size() > adoptedLevels)
581             pop(0);
582     }
583 
adoptLevels(TSymbolTable & symTable)584     void adoptLevels(TSymbolTable& symTable)
585     {
586         for (unsigned int level = 0; level < symTable.table.size(); ++level) {
587             table.push_back(symTable.table[level]);
588             ++adoptedLevels;
589         }
590         uniqueId = symTable.uniqueId;
591         noBuiltInRedeclarations = symTable.noBuiltInRedeclarations;
592         separateNameSpaces = symTable.separateNameSpaces;
593     }
594 
595     //
596     // While level adopting is generic, the methods below enact a the following
597     // convention for levels:
598     //   0: common built-ins shared across all stages, all compiles, only one copy for all symbol tables
599     //   1: per-stage built-ins, shared across all compiles, but a different copy per stage
600     //   2: built-ins specific to a compile, like resources that are context-dependent, or redeclared built-ins
601     //   3: user-shader globals
602     //
603 protected:
604     static const int globalLevel = 3;
isSharedLevel(int level)605     bool isSharedLevel(int level)  { return level <= 1; }              // exclude all per-compile levels
isBuiltInLevel(int level)606     bool isBuiltInLevel(int level) { return level <= 2; }              // exclude user globals
isGlobalLevel(int level)607     bool isGlobalLevel(int level)  { return level <= globalLevel; }    // include user globals
608 public:
isEmpty()609     bool isEmpty() { return table.size() == 0; }
atBuiltInLevel()610     bool atBuiltInLevel() { return isBuiltInLevel(currentLevel()); }
atGlobalLevel()611     bool atGlobalLevel()  { return isGlobalLevel(currentLevel()); }
612 
setNoBuiltInRedeclarations()613     void setNoBuiltInRedeclarations() { noBuiltInRedeclarations = true; }
setSeparateNameSpaces()614     void setSeparateNameSpaces() { separateNameSpaces = true; }
615 
push()616     void push()
617     {
618         table.push_back(new TSymbolTableLevel);
619     }
620 
621     // Make a new symbol-table level to represent the scope introduced by a structure
622     // containing member functions, such that the member functions can find anonymous
623     // references to member variables.
624     //
625     // 'thisSymbol' should have a name of "" to trigger anonymous structure-member
626     // symbol finds.
pushThis(TSymbol & thisSymbol)627     void pushThis(TSymbol& thisSymbol)
628     {
629         assert(thisSymbol.getName().size() == 0);
630         table.push_back(new TSymbolTableLevel);
631         table.back()->setThisLevel();
632         insert(thisSymbol);
633     }
634 
pop(TPrecisionQualifier * p)635     void pop(TPrecisionQualifier *p)
636     {
637         table[currentLevel()]->getPreviousDefaultPrecisions(p);
638         delete table.back();
639         table.pop_back();
640     }
641 
642     //
643     // Insert a visible symbol into the symbol table so it can
644     // be found later by name.
645     //
646     // Returns false if the was a name collision.
647     //
insert(TSymbol & symbol)648     bool insert(TSymbol& symbol)
649     {
650         symbol.setUniqueId(++uniqueId);
651 
652         // make sure there isn't a function of this variable name
653         if (! separateNameSpaces && ! symbol.getAsFunction() && table[currentLevel()]->hasFunctionName(symbol.getName()))
654             return false;
655 
656         // check for not overloading or redefining a built-in function
657         if (noBuiltInRedeclarations) {
658             if (atGlobalLevel() && currentLevel() > 0) {
659                 if (table[0]->hasFunctionName(symbol.getName()))
660                     return false;
661                 if (currentLevel() > 1 && table[1]->hasFunctionName(symbol.getName()))
662                     return false;
663             }
664         }
665 
666         return table[currentLevel()]->insert(symbol, separateNameSpaces);
667     }
668 
669     // Add more members to an already inserted aggregate object
amend(TSymbol & symbol,int firstNewMember)670     bool amend(TSymbol& symbol, int firstNewMember)
671     {
672         // See insert() for comments on basic explanation of insert.
673         // This operates similarly, but more simply.
674         return table[currentLevel()]->amend(symbol, firstNewMember);
675     }
676 
677     //
678     // To allocate an internal temporary, which will need to be uniquely
679     // identified by the consumer of the AST, but never need to
680     // found by doing a symbol table search by name, hence allowed an
681     // arbitrary name in the symbol with no worry of collision.
682     //
makeInternalVariable(TSymbol & symbol)683     void makeInternalVariable(TSymbol& symbol)
684     {
685         symbol.setUniqueId(++uniqueId);
686     }
687 
688     //
689     // Copy a variable or anonymous member's structure from a shared level so that
690     // it can be added (soon after return) to the symbol table where it can be
691     // modified without impacting other users of the shared table.
692     //
copyUpDeferredInsert(TSymbol * shared)693     TSymbol* copyUpDeferredInsert(TSymbol* shared)
694     {
695         if (shared->getAsVariable()) {
696             TSymbol* copy = shared->clone();
697             copy->setUniqueId(shared->getUniqueId());
698             return copy;
699         } else {
700             const TAnonMember* anon = shared->getAsAnonMember();
701             assert(anon);
702             TVariable* container = anon->getAnonContainer().clone();
703             container->changeName(NewPoolTString(""));
704             container->setUniqueId(anon->getAnonContainer().getUniqueId());
705             return container;
706         }
707     }
708 
copyUp(TSymbol * shared)709     TSymbol* copyUp(TSymbol* shared)
710     {
711         TSymbol* copy = copyUpDeferredInsert(shared);
712         table[globalLevel]->insert(*copy, separateNameSpaces);
713         if (shared->getAsVariable())
714             return copy;
715         else {
716             // return the copy of the anonymous member
717             return table[globalLevel]->find(shared->getName());
718         }
719     }
720 
721     // Normal find of a symbol, that can optionally say whether the symbol was found
722     // at a built-in level or the current top-scope level.
723     TSymbol* find(const TString& name, bool* builtIn = 0, bool* currentScope = 0, int* thisDepthP = 0)
724     {
725         int level = currentLevel();
726         TSymbol* symbol;
727         int thisDepth = 0;
728         do {
729             if (table[level]->isThisLevel())
730                 ++thisDepth;
731             symbol = table[level]->find(name);
732             --level;
733         } while (symbol == nullptr && level >= 0);
734         level++;
735         if (builtIn)
736             *builtIn = isBuiltInLevel(level);
737         if (currentScope)
738             *currentScope = isGlobalLevel(currentLevel()) || level == currentLevel();  // consider shared levels as "current scope" WRT user globals
739         if (thisDepthP != nullptr) {
740             if (! table[level]->isThisLevel())
741                 thisDepth = 0;
742             *thisDepthP = thisDepth;
743         }
744 
745         return symbol;
746     }
747 
748     // Find of a symbol that returns how many layers deep of nested
749     // structures-with-member-functions ('this' scopes) deep the symbol was
750     // found in.
find(const TString & name,int & thisDepth)751     TSymbol* find(const TString& name, int& thisDepth)
752     {
753         int level = currentLevel();
754         TSymbol* symbol;
755         thisDepth = 0;
756         do {
757             if (table[level]->isThisLevel())
758                 ++thisDepth;
759             symbol = table[level]->find(name);
760             --level;
761         } while (symbol == 0 && level >= 0);
762 
763         if (! table[level + 1]->isThisLevel())
764             thisDepth = 0;
765 
766         return symbol;
767     }
768 
isFunctionNameVariable(const TString & name)769     bool isFunctionNameVariable(const TString& name) const
770     {
771         if (separateNameSpaces)
772             return false;
773 
774         int level = currentLevel();
775         do {
776             bool variable;
777             bool found = table[level]->findFunctionVariableName(name, variable);
778             if (found)
779                 return variable;
780             --level;
781         } while (level >= 0);
782 
783         return false;
784     }
785 
findFunctionNameList(const TString & name,TVector<const TFunction * > & list,bool & builtIn)786     void findFunctionNameList(const TString& name, TVector<const TFunction*>& list, bool& builtIn)
787     {
788         // For user levels, return the set found in the first scope with a match
789         builtIn = false;
790         int level = currentLevel();
791         do {
792             table[level]->findFunctionNameList(name, list);
793             --level;
794         } while (list.empty() && level >= globalLevel);
795 
796         if (! list.empty())
797             return;
798 
799         // Gather across all built-in levels; they don't hide each other
800         builtIn = true;
801         do {
802             table[level]->findFunctionNameList(name, list);
803             --level;
804         } while (level >= 0);
805     }
806 
relateToOperator(const char * name,TOperator op)807     void relateToOperator(const char* name, TOperator op)
808     {
809         for (unsigned int level = 0; level < table.size(); ++level)
810             table[level]->relateToOperator(name, op);
811     }
812 
setFunctionExtensions(const char * name,int num,const char * const extensions[])813     void setFunctionExtensions(const char* name, int num, const char* const extensions[])
814     {
815         for (unsigned int level = 0; level < table.size(); ++level)
816             table[level]->setFunctionExtensions(name, num, extensions);
817     }
818 
setVariableExtensions(const char * name,int numExts,const char * const extensions[])819     void setVariableExtensions(const char* name, int numExts, const char* const extensions[])
820     {
821         TSymbol* symbol = find(TString(name));
822         if (symbol == nullptr)
823             return;
824 
825         symbol->setExtensions(numExts, extensions);
826     }
827 
setVariableExtensions(const char * blockName,const char * name,int numExts,const char * const extensions[])828     void setVariableExtensions(const char* blockName, const char* name, int numExts, const char* const extensions[])
829     {
830         TSymbol* symbol = find(TString(blockName));
831         if (symbol == nullptr)
832             return;
833         TVariable* variable = symbol->getAsVariable();
834         assert(variable != nullptr);
835 
836         const TTypeList& structure = *variable->getAsVariable()->getType().getStruct();
837         for (int member = 0; member < (int)structure.size(); ++member) {
838             if (structure[member].type->getFieldName().compare(name) == 0) {
839                 variable->setMemberExtensions(member, numExts, extensions);
840                 return;
841             }
842         }
843     }
844 
getMaxSymbolId()845     int getMaxSymbolId() { return uniqueId; }
846     void dump(TInfoSink& infoSink, bool complete = false) const;
847     void copyTable(const TSymbolTable& copyOf);
848 
setPreviousDefaultPrecisions(TPrecisionQualifier * p)849     void setPreviousDefaultPrecisions(TPrecisionQualifier *p) { table[currentLevel()]->setPreviousDefaultPrecisions(p); }
850 
readOnly()851     void readOnly()
852     {
853         for (unsigned int level = 0; level < table.size(); ++level)
854             table[level]->readOnly();
855     }
856 
857 protected:
858     TSymbolTable(TSymbolTable&);
859     TSymbolTable& operator=(TSymbolTableLevel&);
860 
currentLevel()861     int currentLevel() const { return static_cast<int>(table.size()) - 1; }
862 
863     std::vector<TSymbolTableLevel*> table;
864     int uniqueId;     // for unique identification in code generation
865     bool noBuiltInRedeclarations;
866     bool separateNameSpaces;
867     unsigned int adoptedLevels;
868 };
869 
870 } // end namespace glslang
871 
872 #endif // _SYMBOL_TABLE_INCLUDED_
873