Edit

kc3-lang/angle/src/compiler/Types.h

Branch :

  • Show log

    Commit

  • Author : Jamie Madill
    Date : 2013-07-08 14:39:03
    Hash : 98493ddc
    Message : Simplified TType class by carving out TStructure and TField. R=kbr@chromium.org Review URL: https://codereview.appspot.com/9866043 git-svn-id: https://angleproject.googlecode.com/svn/trunk@2423 736b8ea6-26fd-11df-bfd4-992fa37f6226 TRAC #23415 Authored-by: alokp@chromium.org Signed-off-by: Shannon Woods Signed-off-by Nicolas Capens Merged-by: Jamie Madill

  • src/compiler/Types.h
  • //
    // Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
    // Use of this source code is governed by a BSD-style license that can be
    // found in the LICENSE file.
    //
    
    #ifndef _TYPES_INCLUDED
    #define _TYPES_INCLUDED
    
    #include "common/angleutils.h"
    
    #include "compiler/BaseTypes.h"
    #include "compiler/Common.h"
    #include "compiler/debug.h"
    
    struct TPublicType;
    class TType;
    
    class TField
    {
    public:
        POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator);
        TField(TType* type, TString* name, const TSourceLoc& line) : mType(type), mName(name), mLine(line) {}
    
        // TODO(alokp): We should only return const type.
        // Fix it by tweaking grammar.
        TType* type() { return mType; }
        const TType* type() const { return mType; }
    
        const TString& name() const { return *mName; }
        const TSourceLoc& line() const { return mLine; }
    
    private:
        DISALLOW_COPY_AND_ASSIGN(TField);
        TType* mType;
        TString* mName;
        TSourceLoc mLine;
    };
    
    typedef TVector<TField*> TFieldList;
    inline TFieldList* NewPoolTFieldList()
    {
        void* memory = GlobalPoolAllocator.allocate(sizeof(TFieldList));
        return new(memory) TFieldList;
    }
    
    class TFieldListCollection
    {
    public:
        const TString& name() const { return *mName; }
        const TFieldList& fields() const { return *mFields; }
    
        const TString& mangledName() const {
            if (mMangledName.empty())
                mMangledName = buildMangledName();
            return mMangledName;
        }
        size_t objectSize() const {
            if (mObjectSize == 0)
                mObjectSize = calculateObjectSize();
            return mObjectSize;
        };
    
    protected:
        TFieldListCollection(const TString* name, TFieldList* fields)
            : mName(name),
              mFields(fields),
              mObjectSize(0) {
        }
        TString buildMangledName() const;
        size_t calculateObjectSize() const;
        virtual TString mangledNamePrefix() const = 0;
    
        const TString* mName;
        TFieldList* mFields;
    
        mutable TString mMangledName;
        mutable size_t mObjectSize;
    };
    
    // May also represent interface blocks
    class TStructure : public TFieldListCollection
    {
    public:
        POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator);
        TStructure(const TString* name, TFieldList* fields)
            : TFieldListCollection(name, fields),
              mDeepestNesting(0) {
        }
    
        int deepestNesting() const {
            if (mDeepestNesting == 0)
                mDeepestNesting = calculateDeepestNesting();
            return mDeepestNesting;
        }
        bool containsArrays() const;
    
    private:
        DISALLOW_COPY_AND_ASSIGN(TStructure);
        virtual TString mangledNamePrefix() const { return "struct-"; }
        int calculateDeepestNesting() const;
    
        mutable int mDeepestNesting;
    };
    
    class TInterfaceBlock : public TFieldListCollection
    {
    public:
        POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator);
        TInterfaceBlock(const TString* name, TFieldList* fields, const TString* instanceName, int arraySize, const TLayoutQualifier& layoutQualifier)
            : TFieldListCollection(name, fields),
              mInstanceName(instanceName),
              mArraySize(arraySize),
              mBlockStorage(layoutQualifier.blockStorage),
              mMatrixPacking(layoutQualifier.matrixPacking) {
        }
    
        const TString& instanceName() const { return *mInstanceName; }
        bool hasInstanceName() const { return mInstanceName != NULL; }
        bool isArray() const { return mArraySize > 0; }
        int arraySize() const { return mArraySize; }
        TLayoutBlockStorage blockStorage() const { return mBlockStorage; }
        TLayoutMatrixPacking matrixPacking() const { return mMatrixPacking; }
    
    private:
        DISALLOW_COPY_AND_ASSIGN(TInterfaceBlock);
        virtual TString mangledNamePrefix() const { return "iblock-"; }
    
        const TString* mInstanceName; // for interface block instance names
        int mArraySize; // 0 if not an array
        TLayoutBlockStorage mBlockStorage;
        TLayoutMatrixPacking mMatrixPacking;
    };
    
    //
    // Base class for things that have a type.
    //
    class TType
    {
    public:
        POOL_ALLOCATOR_NEW_DELETE(GlobalPoolAllocator)
        TType() {}
        TType(TBasicType t, TPrecision p, TQualifier q = EvqTemporary, int ps = 1, int ss = 1, bool a = false) :
                type(t), precision(p), qualifier(q), primarySize(ps), secondarySize(ss), array(a), layoutQualifier(TLayoutQualifier::create()), arraySize(0),
                interfaceBlock(0), structure(0)
        {
        }
        explicit TType(const TPublicType &p);
        TType(TStructure* userDef, TPrecision p = EbpUndefined) :
                type(EbtStruct), precision(p), qualifier(EvqTemporary), primarySize(1), secondarySize(1), array(false), layoutQualifier(TLayoutQualifier::create()), arraySize(0),
                interfaceBlock(0), structure(userDef)
        {
        }
        TType(TInterfaceBlock* interfaceBlockIn, TQualifier qualifierIn, TLayoutQualifier layoutQualifierIn, int arraySizeIn) :
                type(EbtInterfaceBlock), precision(EbpUndefined), qualifier(qualifierIn), primarySize(1), secondarySize(1), array(arraySizeIn > 0), layoutQualifier(layoutQualifierIn), arraySize(arraySizeIn),
                interfaceBlock(interfaceBlockIn), structure(0)
        {
        }
    
        TBasicType getBasicType() const { return type; }
        void setBasicType(TBasicType t) { type = t; }
    
        TPrecision getPrecision() const { return precision; }
        void setPrecision(TPrecision p) { precision = p; }
    
        TQualifier getQualifier() const { return qualifier; }
        void setQualifier(TQualifier q) { qualifier = q; }
    
        TLayoutQualifier getLayoutQualifier() const { return layoutQualifier; }
        void setLayoutQualifier(TLayoutQualifier lq) { layoutQualifier = lq; }
    
        int getNominalSize() const { return primarySize; }
        int getSecondarySize() const { return secondarySize; }
        int getCols() const { ASSERT(isMatrix()); return primarySize; }
        int getRows() const { ASSERT(isMatrix()); return secondarySize; }
        void setPrimarySize(int ps) { primarySize = ps; }
        void setSecondarySize(int ss) { secondarySize = ss; }
    
        // Full size of single instance of type
        size_t getObjectSize() const;
    
        int elementRegisterCount() const
        {
            if (structure)
            {
                const TFieldList& fields = structure->fields();
                int registerCount = 0;
    
                for (size_t i = 0; i < fields.size(); i++)
                {
                    registerCount += fields[i]->type()->totalRegisterCount();
                }
    
                return registerCount;
            }
            else if (isMatrix())
            {
                return getRows();
            }
            else
            {
                return 1;
            }
        }
    
        int totalRegisterCount() const
        {
            if (array)
            {
                return arraySize * elementRegisterCount();
            }
            else
            {
                return elementRegisterCount();
            }
        }
    
        bool isMatrix() const { return primarySize > 1 && secondarySize > 1; }
        bool isArray() const  { return array ? true : false; }
        int getArraySize() const { return arraySize; }
        void setArraySize(int s) { array = true; arraySize = s; }
        void clearArrayness() { array = false; arraySize = 0; }
    
        TInterfaceBlock* getInterfaceBlock() const { return interfaceBlock; }
        void setInterfaceBlock(TInterfaceBlock* interfaceBlockIn) { interfaceBlock = interfaceBlockIn; }
        bool isInterfaceBlock() const { return type == EbtInterfaceBlock; }
    
        bool isVector() const { return primarySize > 1 && secondarySize == 1; }
        bool isScalar() const { return primarySize == 1 && secondarySize == 1 && !structure; }
        bool isScalarInt() const { return isScalar() && (type == EbtInt || type == EbtUInt); }
    
        TStructure* getStruct() const { return structure; }
        void setStruct(TStructure* s) { structure = s; }
    
        const TString& getMangledName() {
            if (mangled.empty()) {
                mangled = buildMangledName();
                mangled += ';';
            }
    
            return mangled;
        }
    
        bool sameElementType(const TType& right) const {
            return      type == right.type          &&
                 primarySize == right.primarySize   &&
               secondarySize == right.secondarySize &&
                   structure == right.structure;
        }
        bool operator==(const TType& right) const {
            return      type == right.type          &&
                 primarySize == right.primarySize   &&
               secondarySize == right.secondarySize &&
                       array == right.array && (!array || arraySize == right.arraySize) &&
                   structure == right.structure;
            // don't check the qualifier, it's not ever what's being sought after
        }
        bool operator!=(const TType& right) const {
            return !operator==(right);
        }
        bool operator<(const TType& right) const {
            if (type != right.type) return type < right.type;
            if (primarySize != right.primarySize) return primarySize < right.primarySize;
            if (secondarySize != right.secondarySize) return secondarySize < right.secondarySize;
            if (array != right.array) return array < right.array;
            if (arraySize != right.arraySize) return arraySize < right.arraySize;
            if (structure != right.structure) return structure < right.structure;
    
            return false;
        }
    
        const char* getBasicString() const { return ::getBasicString(type); }
        const char* getPrecisionString() const { return ::getPrecisionString(precision); }
        const char* getQualifierString() const { return ::getQualifierString(qualifier); }
        TString getCompleteString() const;
    
        // If this type is a struct, returns the deepest struct nesting of
        // any field in the struct. For example:
        //   struct nesting1 {
        //     vec4 position;
        //   };
        //   struct nesting2 {
        //     nesting1 field1;
        //     vec4 field2;
        //   };
        // For type "nesting2", this method would return 2 -- the number
        // of structures through which indirection must occur to reach the
        // deepest field (nesting2.field1.position).
        int getDeepestStructNesting() const {
            return structure ? structure->deepestNesting() : 0;
        }
    
        bool isStructureContainingArrays() const {
            return structure ? structure->containsArrays() : false;
        }
    
    protected:
        TString buildMangledName() const;
        size_t getStructSize() const;
        void computeDeepestStructNesting();
    
        TBasicType type      : 6;
        TPrecision precision : 4;
        TQualifier qualifier : 7;
        unsigned int array   : 1;
        TLayoutQualifier layoutQualifier;
        int primarySize; // size of vector or cols matrix
        int secondarySize; // rows of a matrix
        int arraySize;
    
        // 0 unless this is an interface block, or interface block member variable
        TInterfaceBlock* interfaceBlock;
    
        // 0 unless this is a struct
        TStructure* structure;
    
        mutable TString mangled;
    };
    
    //
    // This is a workaround for a problem with the yacc stack,  It can't have
    // types that it thinks have non-trivial constructors.  It should
    // just be used while recognizing the grammar, not anything else.  Pointers
    // could be used, but also trying to avoid lots of memory management overhead.
    //
    // Not as bad as it looks, there is no actual assumption that the fields
    // match up or are name the same or anything like that.
    //
    struct TPublicType
    {
        TBasicType type;
        TLayoutQualifier layoutQualifier;
        TQualifier qualifier;
        TPrecision precision;
        int primarySize;          // size of vector or cols of matrix
        int secondarySize;        // rows of matrix
        bool array;
        int arraySize;
        TType* userDef;
        TSourceLoc line;
    
        void setBasic(TBasicType bt, TQualifier q, const TSourceLoc& ln)
        {
            type = bt;
            layoutQualifier = TLayoutQualifier::create();
            qualifier = q;
            precision = EbpUndefined;
            primarySize = 1;
            secondarySize = 1;
            array = false;
            arraySize = 0;
            userDef = 0;
            line = ln;
        }
    
        void setAggregate(int size)
        {
            primarySize = size;
        }
    
        void setMatrix(int c, int r)
        {
            ASSERT(c > 1 && r > 1 && c <= 4 && r <= 4);
            primarySize = c;
            secondarySize = r;
        }
    
        void setArray(bool a, int s = 0)
        {
            array = a;
            arraySize = s;
        }
    
        bool isStructureContainingArrays() const
        {
            if (!userDef)
            {
                return false;
            }
    
            return userDef->isStructureContainingArrays();
        }
    
        bool isMatrix() const
        {
            return primarySize > 1 && secondarySize > 1;
        }
    
        bool isVector() const
        {
            return primarySize > 1 && secondarySize == 1;
        }
    
        int getCols() const
        {
            ASSERT(isMatrix());
            return primarySize;
        }
    
        int getRows() const
        {
            ASSERT(isMatrix());
            return secondarySize;
        }
    
        int getNominalSize() const
        {
            return primarySize;
        }
    
        bool isAggregate() const
        {
            return array || isMatrix() || isVector();
        }
    };
    
    #endif // _TYPES_INCLUDED_