Home | History | Annotate | Download | only in translator
      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 //
      6 
      7 #ifndef _TYPES_INCLUDED
      8 #define _TYPES_INCLUDED
      9 
     10 #include "common/angleutils.h"
     11 
     12 #include "compiler/translator/BaseTypes.h"
     13 #include "compiler/translator/Common.h"
     14 #include "compiler/translator/compilerdebug.h"
     15 
     16 struct TPublicType;
     17 class TType;
     18 class TSymbol;
     19 
     20 class TField
     21 {
     22   public:
     23     POOL_ALLOCATOR_NEW_DELETE();
     24     TField(TType *type, TString *name, const TSourceLoc &line)
     25         : mType(type),
     26           mName(name),
     27           mLine(line)
     28     {
     29     }
     30 
     31     // TODO(alokp): We should only return const type.
     32     // Fix it by tweaking grammar.
     33     TType *type()
     34     {
     35         return mType;
     36     }
     37     const TType *type() const
     38     {
     39         return mType;
     40     }
     41 
     42     const TString &name() const
     43     {
     44         return *mName;
     45     }
     46     const TSourceLoc &line() const
     47     {
     48         return mLine;
     49     }
     50 
     51   private:
     52     DISALLOW_COPY_AND_ASSIGN(TField);
     53     TType *mType;
     54     TString *mName;
     55     TSourceLoc mLine;
     56 };
     57 
     58 typedef TVector<TField *> TFieldList;
     59 inline TFieldList *NewPoolTFieldList()
     60 {
     61     void *memory = GetGlobalPoolAllocator()->allocate(sizeof(TFieldList));
     62     return new(memory) TFieldList;
     63 }
     64 
     65 class TFieldListCollection
     66 {
     67   public:
     68     const TString &name() const
     69     {
     70         return *mName;
     71     }
     72     const TFieldList &fields() const
     73     {
     74         return *mFields;
     75     }
     76 
     77     const TString &mangledName() const
     78     {
     79         if (mMangledName.empty())
     80             mMangledName = buildMangledName();
     81         return mMangledName;
     82     }
     83     size_t objectSize() const
     84     {
     85         if (mObjectSize == 0)
     86             mObjectSize = calculateObjectSize();
     87         return mObjectSize;
     88     };
     89 
     90   protected:
     91     TFieldListCollection(const TString *name, TFieldList *fields)
     92         : mName(name),
     93           mFields(fields),
     94           mObjectSize(0)
     95     {
     96     }
     97     TString buildMangledName() const;
     98     size_t calculateObjectSize() const;
     99     virtual TString mangledNamePrefix() const = 0;
    100 
    101     const TString *mName;
    102     TFieldList *mFields;
    103 
    104     mutable TString mMangledName;
    105     mutable size_t mObjectSize;
    106 };
    107 
    108 // May also represent interface blocks
    109 class TStructure : public TFieldListCollection
    110 {
    111   public:
    112     POOL_ALLOCATOR_NEW_DELETE();
    113     TStructure(const TString *name, TFieldList *fields)
    114         : TFieldListCollection(name, fields),
    115           mDeepestNesting(0),
    116           mUniqueId(0)
    117     {
    118     }
    119 
    120     int deepestNesting() const
    121     {
    122         if (mDeepestNesting == 0)
    123             mDeepestNesting = calculateDeepestNesting();
    124         return mDeepestNesting;
    125     }
    126     bool containsArrays() const;
    127 
    128     bool equals(const TStructure &other) const;
    129 
    130     void setUniqueId(int uniqueId)
    131     {
    132         mUniqueId = uniqueId;
    133     }
    134 
    135     int uniqueId() const
    136     {
    137         ASSERT(mUniqueId != 0);
    138         return mUniqueId;
    139     }
    140 
    141   private:
    142     DISALLOW_COPY_AND_ASSIGN(TStructure);
    143 
    144     // TODO(zmo): Find a way to get rid of the const_cast in function
    145     // setName().  At the moment keep this function private so only
    146     // friend class RegenerateStructNames may call it.
    147     friend class RegenerateStructNames;
    148     void setName(const TString &name)
    149     {
    150         TString *mutableName = const_cast<TString *>(mName);
    151         *mutableName = name;
    152     }
    153 
    154     virtual TString mangledNamePrefix() const
    155     {
    156         return "struct-";
    157     }
    158     int calculateDeepestNesting() const;
    159 
    160     mutable int mDeepestNesting;
    161     int mUniqueId;
    162 };
    163 
    164 class TInterfaceBlock : public TFieldListCollection
    165 {
    166   public:
    167     POOL_ALLOCATOR_NEW_DELETE();
    168     TInterfaceBlock(const TString *name, TFieldList *fields, const TString *instanceName,
    169                     int arraySize, const TLayoutQualifier &layoutQualifier)
    170         : TFieldListCollection(name, fields),
    171           mInstanceName(instanceName),
    172           mArraySize(arraySize),
    173           mBlockStorage(layoutQualifier.blockStorage),
    174           mMatrixPacking(layoutQualifier.matrixPacking)
    175     {
    176     }
    177 
    178     const TString &instanceName() const
    179     {
    180         return *mInstanceName;
    181     }
    182     bool hasInstanceName() const
    183     {
    184         return mInstanceName != NULL;
    185     }
    186     bool isArray() const
    187     {
    188         return mArraySize > 0;
    189     }
    190     int arraySize() const
    191     {
    192         return mArraySize;
    193     }
    194     TLayoutBlockStorage blockStorage() const
    195     {
    196         return mBlockStorage;
    197     }
    198     TLayoutMatrixPacking matrixPacking() const
    199     {
    200         return mMatrixPacking;
    201     }
    202 
    203   private:
    204     DISALLOW_COPY_AND_ASSIGN(TInterfaceBlock);
    205     virtual TString mangledNamePrefix() const
    206     {
    207         return "iblock-";
    208     }
    209 
    210     const TString *mInstanceName; // for interface block instance names
    211     int mArraySize; // 0 if not an array
    212     TLayoutBlockStorage mBlockStorage;
    213     TLayoutMatrixPacking mMatrixPacking;
    214 };
    215 
    216 //
    217 // Base class for things that have a type.
    218 //
    219 class TType
    220 {
    221   public:
    222     POOL_ALLOCATOR_NEW_DELETE();
    223     TType()
    224     {
    225     }
    226     TType(TBasicType t, unsigned char ps = 1, unsigned char ss = 1)
    227         : type(t), precision(EbpUndefined), qualifier(EvqGlobal),
    228           layoutQualifier(TLayoutQualifier::create()),
    229           primarySize(ps), secondarySize(ss), array(false), arraySize(0),
    230           interfaceBlock(0), structure(0)
    231     {
    232     }
    233     TType(TBasicType t, TPrecision p, TQualifier q = EvqTemporary,
    234           unsigned char ps = 1, unsigned char ss = 1, bool a = false)
    235         : type(t), precision(p), qualifier(q),
    236           layoutQualifier(TLayoutQualifier::create()),
    237           primarySize(ps), secondarySize(ss), array(a), arraySize(0),
    238           interfaceBlock(0), structure(0)
    239     {
    240     }
    241     explicit TType(const TPublicType &p);
    242     TType(TStructure *userDef, TPrecision p = EbpUndefined)
    243         : type(EbtStruct), precision(p), qualifier(EvqTemporary),
    244           layoutQualifier(TLayoutQualifier::create()),
    245           primarySize(1), secondarySize(1), array(false), arraySize(0),
    246           interfaceBlock(0), structure(userDef)
    247     {
    248     }
    249     TType(TInterfaceBlock *interfaceBlockIn, TQualifier qualifierIn,
    250           TLayoutQualifier layoutQualifierIn, int arraySizeIn)
    251         : type(EbtInterfaceBlock), precision(EbpUndefined), qualifier(qualifierIn),
    252           layoutQualifier(layoutQualifierIn),
    253           primarySize(1), secondarySize(1), array(arraySizeIn > 0), arraySize(arraySizeIn),
    254           interfaceBlock(interfaceBlockIn), structure(0)
    255     {
    256     }
    257 
    258     TBasicType getBasicType() const
    259     {
    260         return type;
    261     }
    262     void setBasicType(TBasicType t)
    263     {
    264         type = t;
    265     }
    266 
    267     TPrecision getPrecision() const
    268     {
    269         return precision;
    270     }
    271     void setPrecision(TPrecision p)
    272     {
    273         precision = p;
    274     }
    275 
    276     TQualifier getQualifier() const
    277     {
    278         return qualifier;
    279     }
    280     void setQualifier(TQualifier q)
    281     {
    282         qualifier = q;
    283     }
    284 
    285     TLayoutQualifier getLayoutQualifier() const
    286     {
    287         return layoutQualifier;
    288     }
    289     void setLayoutQualifier(TLayoutQualifier lq)
    290     {
    291         layoutQualifier = lq;
    292     }
    293 
    294     int getNominalSize() const
    295     {
    296         return primarySize;
    297     }
    298     int getSecondarySize() const
    299     {
    300         return secondarySize;
    301     }
    302     int getCols() const
    303     {
    304         ASSERT(isMatrix());
    305         return primarySize;
    306     }
    307     int getRows() const
    308     {
    309         ASSERT(isMatrix());
    310         return secondarySize;
    311     }
    312     void setPrimarySize(unsigned char ps)
    313     {
    314         primarySize = ps;
    315     }
    316     void setSecondarySize(unsigned char ss)
    317     {
    318         secondarySize = ss;
    319     }
    320 
    321     // Full size of single instance of type
    322     size_t getObjectSize() const;
    323 
    324     bool isMatrix() const
    325     {
    326         return primarySize > 1 && secondarySize > 1;
    327     }
    328     bool isArray() const
    329     {
    330         return array ? true : false;
    331     }
    332     int getArraySize() const
    333     {
    334         return arraySize;
    335     }
    336     void setArraySize(int s)
    337     {
    338         array = true;
    339         arraySize = s;
    340     }
    341     void clearArrayness()
    342     {
    343         array = false;
    344         arraySize = 0;
    345     }
    346 
    347     TInterfaceBlock *getInterfaceBlock() const
    348     {
    349         return interfaceBlock;
    350     }
    351     void setInterfaceBlock(TInterfaceBlock *interfaceBlockIn)
    352     {
    353         interfaceBlock = interfaceBlockIn;
    354     }
    355     bool isInterfaceBlock() const
    356     {
    357         return type == EbtInterfaceBlock;
    358     }
    359 
    360     bool isVector() const
    361     {
    362         return primarySize > 1 && secondarySize == 1;
    363     }
    364     bool isScalar() const
    365     {
    366         return primarySize == 1 && secondarySize == 1 && !structure;
    367     }
    368     bool isScalarInt() const
    369     {
    370         return isScalar() && (type == EbtInt || type == EbtUInt);
    371     }
    372 
    373     TStructure *getStruct() const
    374     {
    375         return structure;
    376     }
    377     void setStruct(TStructure *s)
    378     {
    379         structure = s;
    380     }
    381 
    382     const TString &getMangledName()
    383     {
    384         if (mangled.empty())
    385         {
    386             mangled = buildMangledName();
    387             mangled += ';';
    388         }
    389 
    390         return mangled;
    391     }
    392 
    393     bool sameElementType(const TType &right) const
    394     {
    395         return type == right.type &&
    396             primarySize == right.primarySize &&
    397             secondarySize == right.secondarySize &&
    398             structure == right.structure;
    399     }
    400     bool operator==(const TType &right) const
    401     {
    402         return type == right.type &&
    403             primarySize == right.primarySize &&
    404             secondarySize == right.secondarySize &&
    405             array == right.array && (!array || arraySize == right.arraySize) &&
    406             structure == right.structure;
    407         // don't check the qualifier, it's not ever what's being sought after
    408     }
    409     bool operator!=(const TType &right) const
    410     {
    411         return !operator==(right);
    412     }
    413     bool operator<(const TType &right) const
    414     {
    415         if (type != right.type)
    416             return type < right.type;
    417         if (primarySize != right.primarySize)
    418             return primarySize < right.primarySize;
    419         if (secondarySize != right.secondarySize)
    420             return secondarySize < right.secondarySize;
    421         if (array != right.array)
    422             return array < right.array;
    423         if (arraySize != right.arraySize)
    424             return arraySize < right.arraySize;
    425         if (structure != right.structure)
    426             return structure < right.structure;
    427 
    428         return false;
    429     }
    430 
    431     const char *getBasicString() const
    432     {
    433         return ::getBasicString(type);
    434     }
    435     const char *getPrecisionString() const
    436     {
    437         return ::getPrecisionString(precision);
    438     }
    439     const char *getQualifierString() const
    440     {
    441         return ::getQualifierString(qualifier);
    442     }
    443     TString getCompleteString() const;
    444 
    445     // If this type is a struct, returns the deepest struct nesting of
    446     // any field in the struct. For example:
    447     //   struct nesting1 {
    448     //     vec4 position;
    449     //   };
    450     //   struct nesting2 {
    451     //     nesting1 field1;
    452     //     vec4 field2;
    453     //   };
    454     // For type "nesting2", this method would return 2 -- the number
    455     // of structures through which indirection must occur to reach the
    456     // deepest field (nesting2.field1.position).
    457     int getDeepestStructNesting() const
    458     {
    459         return structure ? structure->deepestNesting() : 0;
    460     }
    461 
    462     bool isStructureContainingArrays() const
    463     {
    464         return structure ? structure->containsArrays() : false;
    465     }
    466 
    467   protected:
    468     TString buildMangledName() const;
    469     size_t getStructSize() const;
    470     void computeDeepestStructNesting();
    471 
    472     TBasicType type;
    473     TPrecision precision;
    474     TQualifier qualifier;
    475     TLayoutQualifier layoutQualifier;
    476     unsigned char primarySize; // size of vector or cols matrix
    477     unsigned char secondarySize; // rows of a matrix
    478     bool array;
    479     int arraySize;
    480 
    481     // 0 unless this is an interface block, or interface block member variable
    482     TInterfaceBlock *interfaceBlock;
    483 
    484     // 0 unless this is a struct
    485     TStructure *structure;
    486 
    487     mutable TString mangled;
    488 };
    489 
    490 //
    491 // This is a workaround for a problem with the yacc stack,  It can't have
    492 // types that it thinks have non-trivial constructors.  It should
    493 // just be used while recognizing the grammar, not anything else.  Pointers
    494 // could be used, but also trying to avoid lots of memory management overhead.
    495 //
    496 // Not as bad as it looks, there is no actual assumption that the fields
    497 // match up or are name the same or anything like that.
    498 //
    499 struct TPublicType
    500 {
    501     TBasicType type;
    502     TLayoutQualifier layoutQualifier;
    503     TQualifier qualifier;
    504     TPrecision precision;
    505     unsigned char primarySize;          // size of vector or cols of matrix
    506     unsigned char secondarySize;        // rows of matrix
    507     bool array;
    508     int arraySize;
    509     TType *userDef;
    510     TSourceLoc line;
    511 
    512     void setBasic(TBasicType bt, TQualifier q, const TSourceLoc &ln)
    513     {
    514         type = bt;
    515         layoutQualifier = TLayoutQualifier::create();
    516         qualifier = q;
    517         precision = EbpUndefined;
    518         primarySize = 1;
    519         secondarySize = 1;
    520         array = false;
    521         arraySize = 0;
    522         userDef = 0;
    523         line = ln;
    524     }
    525 
    526     void setAggregate(unsigned char size)
    527     {
    528         primarySize = size;
    529     }
    530 
    531     void setMatrix(unsigned char c, unsigned char r)
    532     {
    533         ASSERT(c > 1 && r > 1 && c <= 4 && r <= 4);
    534         primarySize = c;
    535         secondarySize = r;
    536     }
    537 
    538     void setArray(bool a, int s = 0)
    539     {
    540         array = a;
    541         arraySize = s;
    542     }
    543 
    544     bool isStructureContainingArrays() const
    545     {
    546         if (!userDef)
    547         {
    548             return false;
    549         }
    550 
    551         return userDef->isStructureContainingArrays();
    552     }
    553 
    554     bool isMatrix() const
    555     {
    556         return primarySize > 1 && secondarySize > 1;
    557     }
    558 
    559     bool isVector() const
    560     {
    561         return primarySize > 1 && secondarySize == 1;
    562     }
    563 
    564     int getCols() const
    565     {
    566         ASSERT(isMatrix());
    567         return primarySize;
    568     }
    569 
    570     int getRows() const
    571     {
    572         ASSERT(isMatrix());
    573         return secondarySize;
    574     }
    575 
    576     int getNominalSize() const
    577     {
    578         return primarySize;
    579     }
    580 
    581     bool isAggregate() const
    582     {
    583         return array || isMatrix() || isVector();
    584     }
    585 };
    586 
    587 #endif // _TYPES_INCLUDED_
    588