gfx/angle/src/compiler/SymbolTable.h

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     1 //
     2 // Copyright (c) 2002-2013 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 //
     7 #ifndef _SYMBOL_TABLE_INCLUDED_
     8 #define _SYMBOL_TABLE_INCLUDED_
    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 //
    33 #include <assert.h>
    35 #include "common/angleutils.h"
    36 #include "compiler/InfoSink.h"
    37 #include "compiler/intermediate.h"
    39 //
    40 // Symbol base class.  (Can build functions or variables out of these...)
    41 //
    42 class TSymbol {    
    43 public:
    44     POOL_ALLOCATOR_NEW_DELETE();
    45     TSymbol(const TString *n) :  name(n) { }
    46     virtual ~TSymbol() { /* don't delete name, it's from the pool */ }
    48     const TString& getName() const { return *name; }
    49     virtual const TString& getMangledName() const { return getName(); }
    50     virtual bool isFunction() const { return false; }
    51     virtual bool isVariable() const { return false; }
    52     void setUniqueId(int id) { uniqueId = id; }
    53     int getUniqueId() const { return uniqueId; }
    54     virtual void dump(TInfoSink &infoSink) const = 0;
    55     void relateToExtension(const TString& ext) { extension = ext; }
    56     const TString& getExtension() const { return extension; }
    58 private:
    59     DISALLOW_COPY_AND_ASSIGN(TSymbol);
    61     const TString *name;
    62     unsigned int uniqueId;      // For real comparing during code generation
    63     TString extension;
    64 };
    66 //
    67 // Variable class, meaning a symbol that's not a function.
    68 // 
    69 // There could be a separate class heirarchy for Constant variables;
    70 // Only one of int, bool, or float, (or none) is correct for
    71 // any particular use, but it's easy to do this way, and doesn't
    72 // seem worth having separate classes, and "getConst" can't simply return
    73 // different values for different types polymorphically, so this is 
    74 // just simple and pragmatic.
    75 //
    76 class TVariable : public TSymbol {
    77 public:
    78     TVariable(const TString *name, const TType& t, bool uT = false ) : TSymbol(name), type(t), userType(uT), unionArray(0) { }
    79     virtual ~TVariable() { }
    80     virtual bool isVariable() const { return true; }    
    81     TType& getType() { return type; }    
    82     const TType& getType() const { return type; }
    83     bool isUserType() const { return userType; }
    84     void setQualifier(TQualifier qualifier) { type.setQualifier(qualifier); }
    86     virtual void dump(TInfoSink &infoSink) const;
    88     ConstantUnion* getConstPointer()
    89     { 
    90         if (!unionArray)
    91             unionArray = new ConstantUnion[type.getObjectSize()];
    93         return unionArray;
    94     }
    96     ConstantUnion* getConstPointer() const { return unionArray; }
    98     void shareConstPointer( ConstantUnion *constArray)
    99     {
   100         if (unionArray == constArray)
   101             return;
   103         delete[] unionArray;
   104         unionArray = constArray;  
   105     }
   107 private:
   108     DISALLOW_COPY_AND_ASSIGN(TVariable);
   110     TType type;
   111     bool userType;
   112     // we are assuming that Pool Allocator will free the memory allocated to unionArray
   113     // when this object is destroyed
   114     ConstantUnion *unionArray;
   115 };
   117 //
   118 // The function sub-class of symbols and the parser will need to
   119 // share this definition of a function parameter.
   120 //
   121 struct TParameter {
   122     TString *name;
   123     TType* type;
   124 };
   126 //
   127 // The function sub-class of a symbol.  
   128 //
   129 class TFunction : public TSymbol {
   130 public:
   131     TFunction(TOperator o) :
   132         TSymbol(0),
   133         returnType(TType(EbtVoid, EbpUndefined)),
   134         op(o),
   135         defined(false) { }
   136     TFunction(const TString *name, TType& retType, TOperator tOp = EOpNull) : 
   137         TSymbol(name), 
   138         returnType(retType),
   139         mangledName(TFunction::mangleName(*name)),
   140         op(tOp),
   141         defined(false) { }
   142     virtual ~TFunction();
   143     virtual bool isFunction() const { return true; }    
   145     static TString mangleName(const TString& name) { return name + '('; }
   146     static TString unmangleName(const TString& mangledName)
   147     {
   148         return TString(mangledName.c_str(), mangledName.find_first_of('('));
   149     }
   151     void addParameter(TParameter& p) 
   152     { 
   153         parameters.push_back(p);
   154         mangledName = mangledName + p.type->getMangledName();
   155     }
   157     const TString& getMangledName() const { return mangledName; }
   158     const TType& getReturnType() const { return returnType; }
   160     void relateToOperator(TOperator o) { op = o; }
   161     TOperator getBuiltInOp() const { return op; }
   163     void setDefined() { defined = true; }
   164     bool isDefined() { return defined; }
   166     size_t getParamCount() const { return parameters.size(); }  
   167     const TParameter& getParam(size_t i) const { return parameters[i]; }
   169     virtual void dump(TInfoSink &infoSink) const;
   171 private:
   172     DISALLOW_COPY_AND_ASSIGN(TFunction);
   174     typedef TVector<TParameter> TParamList;
   175     TParamList parameters;
   176     TType returnType;
   177     TString mangledName;
   178     TOperator op;
   179     bool defined;
   180 };
   183 class TSymbolTableLevel {
   184 public:
   185     typedef TMap<TString, TSymbol*> tLevel;
   186     typedef tLevel::const_iterator const_iterator;
   187     typedef const tLevel::value_type tLevelPair;
   188     typedef std::pair<tLevel::iterator, bool> tInsertResult;
   190     POOL_ALLOCATOR_NEW_DELETE();
   191     TSymbolTableLevel() { }
   192     ~TSymbolTableLevel();
   194     bool insert(const TString &name, TSymbol &symbol)
   195     {
   196         //
   197         // returning true means symbol was added to the table
   198         //
   199         tInsertResult result;
   200         result = level.insert(tLevelPair(name, &symbol));
   202         return result.second;
   203     }
   205     bool insert(TSymbol &symbol)
   206     {
   207         return insert(symbol.getMangledName(), symbol);
   208     }
   210     TSymbol* find(const TString& name) const
   211     {
   212         tLevel::const_iterator it = level.find(name);
   213         if (it == level.end())
   214             return 0;
   215         else
   216             return (*it).second;
   217     }
   219     const_iterator begin() const
   220     {
   221         return level.begin();
   222     }
   224     const_iterator end() const
   225     {
   226         return level.end();
   227     }
   229     void relateToOperator(const char* name, TOperator op);
   230     void relateToExtension(const char* name, const TString& ext);
   231     void dump(TInfoSink &infoSink) const;
   233 protected:
   234     tLevel level;
   235 };
   237 class TSymbolTable {
   238 public:
   239     TSymbolTable() : uniqueId(0)
   240     {
   241         //
   242         // The symbol table cannot be used until push() is called, but
   243         // the lack of an initial call to push() can be used to detect
   244         // that the symbol table has not been preloaded with built-ins.
   245         //
   246     }
   248     ~TSymbolTable()
   249     {
   250         // level 0 is always built In symbols, so we never pop that out
   251         while (table.size() > 1)
   252             pop();
   253     }
   255     //
   256     // When the symbol table is initialized with the built-ins, there should
   257     // 'push' calls, so that built-ins are at level 0 and the shader
   258     // globals are at level 1.
   259     //
   260     bool isEmpty() { return table.size() == 0; }
   261     bool atBuiltInLevel() { return table.size() == 1; }
   262     bool atGlobalLevel() { return table.size() <= 2; }
   263     void push()
   264     {
   265         table.push_back(new TSymbolTableLevel);
   266         precisionStack.push_back( PrecisionStackLevel() );
   267     }
   269     void pop()
   270     { 
   271         delete table[currentLevel()]; 
   272         table.pop_back(); 
   273         precisionStack.pop_back();
   274     }
   276     bool insert(TSymbol& symbol)
   277     {
   278         symbol.setUniqueId(++uniqueId);
   279         return table[currentLevel()]->insert(symbol);
   280     }
   282     bool insertConstInt(const char *name, int value)
   283     {
   284         TVariable *constant = new TVariable(NewPoolTString(name), TType(EbtInt, EbpUndefined, EvqConst, 1));
   285         constant->getConstPointer()->setIConst(value);
   286         return insert(*constant);
   287     }
   289     bool insertBuiltIn(TType *rvalue, const char *name, TType *ptype1, TType *ptype2 = 0, TType *ptype3 = 0)
   290     {
   291         TFunction *function = new TFunction(NewPoolTString(name), *rvalue);
   293         TParameter param1 = {NULL, ptype1};
   294         function->addParameter(param1);
   296         if(ptype2)
   297         {
   298             TParameter param2 = {NULL, ptype2};
   299             function->addParameter(param2);
   300         }
   302         if(ptype3)
   303         {
   304             TParameter param3 = {NULL, ptype3};
   305             function->addParameter(param3);
   306         }
   308         return insert(*function);
   309     }
   311     TSymbol* find(const TString& name, bool* builtIn = 0, bool *sameScope = 0) 
   312     {
   313         int level = currentLevel();
   314         TSymbol* symbol;
   315         do {
   316             symbol = table[level]->find(name);
   317             --level;
   318         } while (symbol == 0 && level >= 0);
   319         level++;
   320         if (builtIn)
   321             *builtIn = level == 0;
   322         if (sameScope)
   323             *sameScope = level == currentLevel();
   324         return symbol;
   325     }
   327     TSymbol *findBuiltIn(const TString &name)
   328     {
   329         return table[0]->find(name);
   330     }
   332     TSymbolTableLevel* getGlobalLevel() {
   333         assert(table.size() >= 2);
   334         return table[1];
   335     }
   337     TSymbolTableLevel* getOuterLevel() {
   338         assert(table.size() >= 2);
   339         return table[currentLevel() - 1];
   340     }
   342     void relateToOperator(const char* name, TOperator op) {
   343         table[0]->relateToOperator(name, op);
   344     }
   345     void relateToExtension(const char* name, const TString& ext) {
   346         table[0]->relateToExtension(name, ext);
   347     }
   348     int getMaxSymbolId() { return uniqueId; }
   349     void dump(TInfoSink &infoSink) const;
   351     bool setDefaultPrecision( const TPublicType& type, TPrecision prec ){
   352         if (IsSampler(type.type))
   353             return true;  // Skip sampler types for the time being
   354         if (type.type != EbtFloat && type.type != EbtInt)
   355             return false; // Only set default precision for int/float
   356         if (type.size != 1 || type.matrix || type.array)
   357             return false; // Not allowed to set for aggregate types
   358         int indexOfLastElement = static_cast<int>(precisionStack.size()) - 1;
   359         precisionStack[indexOfLastElement][type.type] = prec; // Uses map operator [], overwrites the current value
   360         return true;
   361     }
   363     // Searches down the precisionStack for a precision qualifier for the specified TBasicType
   364     TPrecision getDefaultPrecision( TBasicType type){
   365         if( type != EbtFloat && type != EbtInt ) return EbpUndefined;
   366         int level = static_cast<int>(precisionStack.size()) - 1;
   367         assert( level >= 0); // Just to be safe. Should not happen.
   368         PrecisionStackLevel::iterator it;
   369         TPrecision prec = EbpUndefined; // If we dont find anything we return this. Should we error check this?
   370         while( level >= 0 ){
   371             it = precisionStack[level].find( type );
   372             if( it != precisionStack[level].end() ){
   373                 prec = (*it).second;
   374                 break;
   375             }
   376             level--;
   377         }
   378         return prec;
   379     }
   381 protected:    
   382     int currentLevel() const { return static_cast<int>(table.size()) - 1; }
   384     std::vector<TSymbolTableLevel*> table;
   385     typedef std::map< TBasicType, TPrecision > PrecisionStackLevel;
   386     std::vector< PrecisionStackLevel > precisionStack;
   387     int uniqueId;     // for unique identification in code generation
   388 };
   390 #endif // _SYMBOL_TABLE_INCLUDED_

mercurial