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