LCOV - code coverage report
Current view: top level - gfx/angle/src/compiler/translator - SymbolTable.h (source / functions) Hit Total Coverage
Test: output.info Lines: 0 185 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 69 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //
       2             : // Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
       3             : // Use of this source code is governed by a BSD-style license that can be
       4             : // found in the LICENSE file.
       5             : //
       6             : 
       7             : #ifndef COMPILER_TRANSLATOR_SYMBOLTABLE_H_
       8             : #define COMPILER_TRANSLATOR_SYMBOLTABLE_H_
       9             : 
      10             : //
      11             : // Symbol table for parsing.  Has these design characteristics:
      12             : //
      13             : // * Same symbol table can be used to compile many shaders, to preserve
      14             : //   effort of creating and loading with the large numbers of built-in
      15             : //   symbols.
      16             : //
      17             : // * Name mangling will be used to give each function a unique name
      18             : //   so that symbol table lookups are never ambiguous.  This allows
      19             : //   a simpler symbol table structure.
      20             : //
      21             : // * Pushing and popping of scope, so symbol table will really be a stack 
      22             : //   of symbol tables.  Searched from the top, with new inserts going into
      23             : //   the top.
      24             : //
      25             : // * Constants:  Compile time constant symbols will keep their values
      26             : //   in the symbol table.  The parser can substitute constants at parse
      27             : //   time, including doing constant folding and constant propagation.
      28             : //
      29             : // * No temporaries:  Temporaries made from operations (+, --, .xy, etc.)
      30             : //   are tracked in the intermediate representation, not the symbol table.
      31             : //
      32             : 
      33             : #include <array>
      34             : #include <assert.h>
      35             : #include <set>
      36             : 
      37             : #include "common/angleutils.h"
      38             : #include "compiler/translator/InfoSink.h"
      39             : #include "compiler/translator/IntermNode.h"
      40             : 
      41             : namespace sh
      42             : {
      43             : 
      44             : // Symbol base class. (Can build functions or variables out of these...)
      45             : class TSymbol : angle::NonCopyable
      46             : {
      47             :   public:
      48           0 :     POOL_ALLOCATOR_NEW_DELETE();
      49             :     TSymbol(const TString *n);
      50             : 
      51           0 :     virtual ~TSymbol()
      52           0 :     {
      53             :         // don't delete name, it's from the pool
      54           0 :     }
      55             : 
      56           0 :     const TString &getName() const
      57             :     {
      58           0 :         return *name;
      59             :     }
      60           0 :     virtual const TString &getMangledName() const
      61             :     {
      62           0 :         return getName();
      63             :     }
      64           0 :     virtual bool isFunction() const
      65             :     {
      66           0 :         return false;
      67             :     }
      68           0 :     virtual bool isVariable() const
      69             :     {
      70           0 :         return false;
      71             :     }
      72           0 :     int getUniqueId() const
      73             :     {
      74           0 :         return uniqueId;
      75             :     }
      76           0 :     void relateToExtension(const TString &ext)
      77             :     {
      78           0 :         extension = ext;
      79           0 :     }
      80           0 :     const TString &getExtension() const
      81             :     {
      82           0 :         return extension;
      83             :     }
      84             : 
      85             :   private:
      86             :     const int uniqueId;
      87             :     const TString *name;
      88             :     TString extension;
      89             : };
      90             : 
      91             : // Variable class, meaning a symbol that's not a function.
      92             : // 
      93             : // There could be a separate class heirarchy for Constant variables;
      94             : // Only one of int, bool, or float, (or none) is correct for
      95             : // any particular use, but it's easy to do this way, and doesn't
      96             : // seem worth having separate classes, and "getConst" can't simply return
      97             : // different values for different types polymorphically, so this is 
      98             : // just simple and pragmatic.
      99             : class TVariable : public TSymbol
     100             : {
     101             :   public:
     102           0 :     TVariable(const TString *name, const TType &t, bool uT = false)
     103           0 :         : TSymbol(name),
     104             :           type(t),
     105             :           userType(uT),
     106           0 :           unionArray(0)
     107             :     {
     108           0 :     }
     109           0 :     ~TVariable() override {}
     110           0 :     bool isVariable() const override { return true; }
     111           0 :     TType &getType()
     112             :     {
     113           0 :         return type;
     114             :     }
     115           0 :     const TType &getType() const
     116             :     {
     117           0 :         return type;
     118             :     }
     119           0 :     bool isUserType() const
     120             :     {
     121           0 :         return userType;
     122             :     }
     123           0 :     void setQualifier(TQualifier qualifier)
     124             :     {
     125           0 :         type.setQualifier(qualifier);
     126           0 :     }
     127             : 
     128           0 :     const TConstantUnion *getConstPointer() const { return unionArray; }
     129             : 
     130           0 :     void shareConstPointer(const TConstantUnion *constArray) { unionArray = constArray; }
     131             : 
     132             :   private:
     133             :     TType type;
     134             :     bool userType;
     135             :     // we are assuming that Pool Allocator will free the memory
     136             :     // allocated to unionArray when this object is destroyed.
     137             :     const TConstantUnion *unionArray;
     138             : };
     139             : 
     140             : // Immutable version of TParameter.
     141             : struct TConstParameter
     142             : {
     143             :     TConstParameter()
     144             :         : name(nullptr),
     145             :           type(nullptr)
     146             :     {
     147             :     }
     148             :     explicit TConstParameter(const TString *n)
     149             :         : name(n),
     150             :           type(nullptr)
     151             :     {
     152             :     }
     153           0 :     explicit TConstParameter(const TType *t)
     154           0 :         : name(nullptr),
     155           0 :           type(t)
     156             :     {
     157           0 :     }
     158           0 :     TConstParameter(const TString *n, const TType *t)
     159           0 :         : name(n),
     160           0 :           type(t)
     161             :     {
     162           0 :     }
     163             : 
     164             :     // Both constructor arguments must be const.
     165             :     TConstParameter(TString *n, TType *t) = delete;
     166             :     TConstParameter(const TString *n, TType *t) = delete;
     167             :     TConstParameter(TString *n, const TType *t) = delete;
     168             : 
     169             :     const TString *name;
     170             :     const TType *type;
     171             : };
     172             : 
     173             : // The function sub-class of symbols and the parser will need to
     174             : // share this definition of a function parameter.
     175             : struct TParameter
     176             : {
     177             :     // Destructively converts to TConstParameter.
     178             :     // This method resets name and type to nullptrs to make sure
     179             :     // their content cannot be modified after the call.
     180           0 :     TConstParameter turnToConst()
     181             :     {
     182           0 :         const TString *constName = name;
     183           0 :         const TType *constType = type;
     184           0 :         name = nullptr;
     185           0 :         type = nullptr;
     186           0 :         return TConstParameter(constName, constType);
     187             :     }
     188             : 
     189             :     TString *name;
     190             :     TType *type;
     191             : };
     192             : 
     193             : // The function sub-class of a symbol.  
     194             : class TFunction : public TSymbol
     195             : {
     196             :   public:
     197           0 :     TFunction(const TString *name,
     198             :               const TType *retType,
     199             :               TOperator tOp   = EOpNull,
     200             :               const char *ext = "")
     201           0 :         : TSymbol(name),
     202             :           returnType(retType),
     203             :           mangledName(nullptr),
     204             :           op(tOp),
     205             :           defined(false),
     206           0 :           mHasPrototypeDeclaration(false)
     207             :     {
     208           0 :         relateToExtension(ext);
     209           0 :     }
     210             :     ~TFunction() override;
     211           0 :     bool isFunction() const override { return true; }
     212             : 
     213           0 :     static TString mangleName(const TString &name)
     214             :     {
     215           0 :         return name + '(';
     216             :     }
     217           0 :     static TString unmangleName(const TString &mangledName)
     218             :     {
     219           0 :         return TString(mangledName.c_str(), mangledName.find_first_of('('));
     220             :     }
     221             : 
     222           0 :     void addParameter(const TConstParameter &p)
     223             :     {
     224           0 :         parameters.push_back(p);
     225           0 :         mangledName = nullptr;
     226           0 :     }
     227             : 
     228             :     void swapParameters(const TFunction &parametersSource);
     229             : 
     230           0 :     const TString &getMangledName() const override
     231             :     {
     232           0 :         if (mangledName == nullptr)
     233             :         {
     234           0 :             mangledName = buildMangledName();
     235             :         }
     236           0 :         return *mangledName;
     237             :     }
     238           0 :     const TType &getReturnType() const
     239             :     {
     240           0 :         return *returnType;
     241             :     }
     242             : 
     243           0 :     TOperator getBuiltInOp() const
     244             :     {
     245           0 :         return op;
     246             :     }
     247             : 
     248           0 :     void setDefined() { defined = true; }
     249           0 :     bool isDefined() { return defined; }
     250           0 :     void setHasPrototypeDeclaration() { mHasPrototypeDeclaration = true; }
     251           0 :     bool hasPrototypeDeclaration() const { return mHasPrototypeDeclaration; }
     252             : 
     253           0 :     size_t getParamCount() const
     254             :     {
     255           0 :         return parameters.size();
     256             :     }
     257           0 :     const TConstParameter &getParam(size_t i) const
     258             :     {
     259           0 :         return parameters[i];
     260             :     }
     261             : 
     262             :   private:
     263             :     void clearParameters();
     264             : 
     265             :     const TString *buildMangledName() const;
     266             : 
     267             :     typedef TVector<TConstParameter> TParamList;
     268             :     TParamList parameters;
     269             :     const TType *returnType;
     270             :     mutable const TString *mangledName;
     271             :     TOperator op;
     272             :     bool defined;
     273             :     bool mHasPrototypeDeclaration;
     274             : };
     275             : 
     276             : // Interface block name sub-symbol
     277             : class TInterfaceBlockName : public TSymbol
     278             : {
     279             :   public:
     280           0 :     TInterfaceBlockName(const TString *name)
     281           0 :         : TSymbol(name)
     282             :     {
     283           0 :     }
     284             : 
     285           0 :     virtual ~TInterfaceBlockName()
     286           0 :     {
     287           0 :     }
     288             : };
     289             : 
     290             : class TSymbolTableLevel
     291             : {
     292             :   public:
     293             :     typedef TMap<TString, TSymbol *> tLevel;
     294             :     typedef tLevel::const_iterator const_iterator;
     295             :     typedef const tLevel::value_type tLevelPair;
     296             :     typedef std::pair<tLevel::iterator, bool> tInsertResult;
     297             : 
     298           0 :     TSymbolTableLevel()
     299           0 :         : mGlobalInvariant(false)
     300             :     {
     301           0 :     }
     302             :     ~TSymbolTableLevel();
     303             : 
     304             :     bool insert(TSymbol *symbol);
     305             : 
     306             :     // Insert a function using its unmangled name as the key.
     307             :     bool insertUnmangled(TFunction *function);
     308             : 
     309             :     TSymbol *find(const TString &name) const;
     310             : 
     311           0 :     void addInvariantVarying(const std::string &name)
     312             :     {
     313           0 :         mInvariantVaryings.insert(name);
     314           0 :     }
     315             : 
     316           0 :     bool isVaryingInvariant(const std::string &name)
     317             :     {
     318           0 :         return (mGlobalInvariant || mInvariantVaryings.count(name) > 0);
     319             :     }
     320             : 
     321           0 :     void setGlobalInvariant(bool invariant) { mGlobalInvariant = invariant; }
     322             : 
     323             :   protected:
     324             :     tLevel level;
     325             :     std::set<std::string> mInvariantVaryings;
     326             :     bool mGlobalInvariant;
     327             : };
     328             : 
     329             : // Define ESymbolLevel as int rather than an enum since level can go
     330             : // above GLOBAL_LEVEL and cause atBuiltInLevel() to fail if the
     331             : // compiler optimizes the >= of the last element to ==.
     332             : typedef int ESymbolLevel;
     333             : const int COMMON_BUILTINS = 0;
     334             : const int ESSL1_BUILTINS = 1;
     335             : const int ESSL3_BUILTINS = 2;
     336             : const int ESSL3_1_BUILTINS   = 3;
     337             : const int LAST_BUILTIN_LEVEL = ESSL3_1_BUILTINS;
     338             : const int GLOBAL_LEVEL       = 4;
     339             : 
     340             : class TSymbolTable : angle::NonCopyable
     341             : {
     342             :   public:
     343           0 :     TSymbolTable()
     344           0 :     {
     345             :         // The symbol table cannot be used until push() is called, but
     346             :         // the lack of an initial call to push() can be used to detect
     347             :         // that the symbol table has not been preloaded with built-ins.
     348           0 :     }
     349             : 
     350             :     ~TSymbolTable();
     351             : 
     352             :     // When the symbol table is initialized with the built-ins, there should
     353             :     // 'push' calls, so that built-ins are at level 0 and the shader
     354             :     // globals are at level 1.
     355           0 :     bool isEmpty() const
     356             :     {
     357           0 :         return table.empty();
     358             :     }
     359           0 :     bool atBuiltInLevel() const
     360             :     {
     361           0 :         return currentLevel() <= LAST_BUILTIN_LEVEL;
     362             :     }
     363           0 :     bool atGlobalLevel() const
     364             :     {
     365           0 :         return currentLevel() == GLOBAL_LEVEL;
     366             :     }
     367           0 :     void push()
     368             :     {
     369           0 :         table.push_back(new TSymbolTableLevel);
     370           0 :         precisionStack.push_back(new PrecisionStackLevel);
     371           0 :     }
     372             : 
     373           0 :     void pop()
     374             :     {
     375           0 :         delete table.back();
     376           0 :         table.pop_back();
     377             : 
     378           0 :         delete precisionStack.back();
     379           0 :         precisionStack.pop_back();
     380           0 :     }
     381             : 
     382           0 :     bool declare(TSymbol *symbol)
     383             :     {
     384           0 :         return insert(currentLevel(), symbol);
     385             :     }
     386             : 
     387           0 :     bool insert(ESymbolLevel level, TSymbol *symbol)
     388             :     {
     389           0 :         return table[level]->insert(symbol);
     390             :     }
     391             : 
     392           0 :     bool insert(ESymbolLevel level, const char *ext, TSymbol *symbol)
     393             :     {
     394           0 :         symbol->relateToExtension(ext);
     395           0 :         return table[level]->insert(symbol);
     396             :     }
     397             : 
     398           0 :     bool insertConstInt(ESymbolLevel level, const char *name, int value, TPrecision precision)
     399             :     {
     400             :         TVariable *constant =
     401           0 :             new TVariable(NewPoolTString(name), TType(EbtInt, precision, EvqConst, 1));
     402           0 :         TConstantUnion *unionArray = new TConstantUnion[1];
     403           0 :         unionArray[0].setIConst(value);
     404           0 :         constant->shareConstPointer(unionArray);
     405           0 :         return insert(level, constant);
     406             :     }
     407             : 
     408           0 :     bool insertConstIntExt(ESymbolLevel level, const char *ext, const char *name, int value)
     409             :     {
     410             :         TVariable *constant =
     411           0 :             new TVariable(NewPoolTString(name), TType(EbtInt, EbpUndefined, EvqConst, 1));
     412           0 :         TConstantUnion *unionArray = new TConstantUnion[1];
     413           0 :         unionArray[0].setIConst(value);
     414           0 :         constant->shareConstPointer(unionArray);
     415           0 :         return insert(level, ext, constant);
     416             :     }
     417             : 
     418           0 :     bool insertConstIvec3(ESymbolLevel level,
     419             :                           const char *name,
     420             :                           const std::array<int, 3> &values,
     421             :                           TPrecision precision)
     422             :     {
     423             :         TVariable *constantIvec3 =
     424           0 :             new TVariable(NewPoolTString(name), TType(EbtInt, precision, EvqConst, 3));
     425             : 
     426           0 :         TConstantUnion *unionArray = new TConstantUnion[3];
     427           0 :         for (size_t index = 0u; index < 3u; ++index)
     428             :         {
     429           0 :             unionArray[index].setIConst(values[index]);
     430             :         }
     431           0 :         constantIvec3->shareConstPointer(unionArray);
     432             : 
     433           0 :         return insert(level, constantIvec3);
     434             :     }
     435             : 
     436             :     void insertBuiltIn(ESymbolLevel level, TOperator op, const char *ext, const TType *rvalue, const char *name,
     437             :                        const TType *ptype1, const TType *ptype2 = 0, const TType *ptype3 = 0, const TType *ptype4 = 0, const TType *ptype5 = 0);
     438             : 
     439           0 :     void insertBuiltIn(ESymbolLevel level, const TType *rvalue, const char *name,
     440             :                        const TType *ptype1, const TType *ptype2 = 0, const TType *ptype3 = 0, const TType *ptype4 = 0, const TType *ptype5 = 0)
     441             :     {
     442           0 :         insertUnmangledBuiltIn(name);
     443           0 :         insertBuiltIn(level, EOpNull, "", rvalue, name, ptype1, ptype2, ptype3, ptype4, ptype5);
     444           0 :     }
     445             : 
     446           0 :     void insertBuiltIn(ESymbolLevel level, const char *ext, const TType *rvalue, const char *name,
     447             :                        const TType *ptype1, const TType *ptype2 = 0, const TType *ptype3 = 0, const TType *ptype4 = 0, const TType *ptype5 = 0)
     448             :     {
     449           0 :         insertUnmangledBuiltIn(name);
     450           0 :         insertBuiltIn(level, EOpNull, ext, rvalue, name, ptype1, ptype2, ptype3, ptype4, ptype5);
     451           0 :     }
     452             : 
     453           0 :     void insertBuiltIn(ESymbolLevel level, TOperator op, const TType *rvalue, const char *name,
     454             :                        const TType *ptype1, const TType *ptype2 = 0, const TType *ptype3 = 0, const TType *ptype4 = 0, const TType *ptype5 = 0)
     455             :     {
     456           0 :         insertUnmangledBuiltIn(name);
     457           0 :         insertBuiltIn(level, op, "", rvalue, name, ptype1, ptype2, ptype3, ptype4, ptype5);
     458           0 :     }
     459             : 
     460             :     TSymbol *find(const TString &name, int shaderVersion,
     461             :                   bool *builtIn = NULL, bool *sameScope = NULL) const;
     462             : 
     463             :     TSymbol *findGlobal(const TString &name) const;
     464             : 
     465             :     TSymbol *findBuiltIn(const TString &name, int shaderVersion) const;
     466             : 
     467           0 :     TSymbolTableLevel *getOuterLevel()
     468             :     {
     469           0 :         assert(currentLevel() >= 1);
     470           0 :         return table[currentLevel() - 1];
     471             :     }
     472             : 
     473             :     void dump(TInfoSink &infoSink) const;
     474             : 
     475           0 :     bool setDefaultPrecision(const TPublicType &type, TPrecision prec)
     476             :     {
     477           0 :         if (!SupportsPrecision(type.getBasicType()))
     478           0 :             return false;
     479           0 :         if (type.getBasicType() == EbtUInt)
     480           0 :             return false;  // ESSL 3.00.4 section 4.5.4
     481           0 :         if (type.isAggregate())
     482           0 :             return false; // Not allowed to set for aggregate types
     483           0 :         int indexOfLastElement = static_cast<int>(precisionStack.size()) - 1;
     484             :         // Uses map operator [], overwrites the current value
     485           0 :         (*precisionStack[indexOfLastElement])[type.getBasicType()] = prec;
     486           0 :         return true;
     487             :     }
     488             : 
     489             :     // Searches down the precisionStack for a precision qualifier
     490             :     // for the specified TBasicType
     491             :     TPrecision getDefaultPrecision(TBasicType type) const;
     492             : 
     493             :     // This records invariant varyings declared through
     494             :     // "invariant varying_name;".
     495           0 :     void addInvariantVarying(const std::string &originalName)
     496             :     {
     497           0 :         ASSERT(atGlobalLevel());
     498           0 :         table[currentLevel()]->addInvariantVarying(originalName);
     499           0 :     }
     500             :     // If this returns false, the varying could still be invariant
     501             :     // if it is set as invariant during the varying variable
     502             :     // declaration - this piece of information is stored in the
     503             :     // variable's type, not here.
     504           0 :     bool isVaryingInvariant(const std::string &originalName) const
     505             :     {
     506           0 :         ASSERT(atGlobalLevel());
     507           0 :         return table[currentLevel()]->isVaryingInvariant(originalName);
     508             :     }
     509             : 
     510           0 :     void setGlobalInvariant(bool invariant)
     511             :     {
     512           0 :         ASSERT(atGlobalLevel());
     513           0 :         table[currentLevel()]->setGlobalInvariant(invariant);
     514           0 :     }
     515             : 
     516           0 :     static int nextUniqueId()
     517             :     {
     518           0 :         return ++uniqueIdCounter;
     519             :     }
     520             : 
     521           0 :     bool hasUnmangledBuiltIn(const char *name)
     522             :     {
     523           0 :         return mUnmangledBuiltinNames.count(std::string(name)) > 0;
     524             :     }
     525             : 
     526             :   private:
     527           0 :     ESymbolLevel currentLevel() const
     528             :     {
     529           0 :         return static_cast<ESymbolLevel>(table.size() - 1);
     530             :     }
     531             : 
     532             :     // Used to insert unmangled functions to check redeclaration of built-ins in ESSL 3.00.
     533           0 :     void insertUnmangledBuiltIn(const char *name)
     534             :     {
     535           0 :         mUnmangledBuiltinNames.insert(std::string(name));
     536           0 :     }
     537             : 
     538             :     std::vector<TSymbolTableLevel *> table;
     539             :     typedef TMap<TBasicType, TPrecision> PrecisionStackLevel;
     540             :     std::vector< PrecisionStackLevel *> precisionStack;
     541             : 
     542             :     std::set<std::string> mUnmangledBuiltinNames;
     543             : 
     544             :     static int uniqueIdCounter;
     545             : };
     546             : 
     547             : }  // namespace sh
     548             : 
     549             : #endif // COMPILER_TRANSLATOR_SYMBOLTABLE_H_

Generated by: LCOV version 1.13