Home | History | Annotate | Download | only in Include
      1 //
      2 //Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
      3 //Copyright (C) 2012-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 //
     38 // Implement types for tracking GLSL arrays, arrays of arrays, etc.
     39 //
     40 
     41 #ifndef _ARRAYS_INCLUDED
     42 #define _ARRAYS_INCLUDED
     43 
     44 namespace glslang {
     45 
     46 // This is used to mean there is no size yet (unsized), it is waiting to get a size from somewhere else.
     47 const int UnsizedArraySize = 0;
     48 
     49 class TIntermTyped;
     50 extern bool SameSpecializationConstants(TIntermTyped*, TIntermTyped*);
     51 
     52 // Specialization constants need both a nominal size and a node that defines
     53 // the specialization constant being used.  Array types are the same when their
     54 // size and specialization constant nodes are the same.
     55 struct TArraySize {
     56     unsigned int size;
     57     TIntermTyped* node;  // nullptr means no specialization constant node
     58     bool operator==(const TArraySize& rhs) const
     59     {
     60         if (size != rhs.size)
     61             return false;
     62         if (node == nullptr || rhs.node == nullptr)
     63             return node == rhs.node;
     64 
     65         return SameSpecializationConstants(node, rhs.node);
     66     }
     67 };
     68 
     69 //
     70 // TSmallArrayVector is used as the container for the set of sizes in TArraySizes.
     71 // It has generic-container semantics, while TArraySizes has array-of-array semantics.
     72 // That is, TSmallArrayVector should be more focused on mechanism and TArraySizes on policy.
     73 //
     74 struct TSmallArrayVector {
     75     //
     76     // TODO: memory: TSmallArrayVector is intended to be smaller.
     77     // Almost all arrays could be handled by two sizes each fitting
     78     // in 16 bits, needing a real vector only in the cases where there
     79     // are more than 3 sizes or a size needing more than 16 bits.
     80     //
     81     POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
     82 
     83     TSmallArrayVector() : sizes(nullptr) { }
     84     virtual ~TSmallArrayVector() { dealloc(); }
     85 
     86     // For breaking into two non-shared copies, independently modifiable.
     87     TSmallArrayVector& operator=(const TSmallArrayVector& from)
     88     {
     89         if (from.sizes == nullptr)
     90             sizes = nullptr;
     91         else {
     92             alloc();
     93             *sizes = *from.sizes;
     94         }
     95 
     96         return *this;
     97     }
     98 
     99     int size() const
    100     {
    101         if (sizes == nullptr)
    102             return 0;
    103         return (int)sizes->size();
    104     }
    105 
    106     unsigned int frontSize() const
    107     {
    108         assert(sizes != nullptr && sizes->size() > 0);
    109         return sizes->front().size;
    110     }
    111 
    112     TIntermTyped* frontNode() const
    113     {
    114         assert(sizes != nullptr && sizes->size() > 0);
    115         return sizes->front().node;
    116     }
    117 
    118     void changeFront(unsigned int s)
    119     {
    120         assert(sizes != nullptr);
    121         // this should only happen for implicitly sized arrays, not specialization constants
    122         assert(sizes->front().node == nullptr);
    123         sizes->front().size = s;
    124     }
    125 
    126     void push_back(unsigned int e, TIntermTyped* n)
    127     {
    128         alloc();
    129         TArraySize pair = { e, n };
    130         sizes->push_back(pair);
    131     }
    132 
    133     void push_front(const TSmallArrayVector& newDims)
    134     {
    135         alloc();
    136         sizes->insert(sizes->begin(), newDims.sizes->begin(), newDims.sizes->end());
    137     }
    138 
    139     void pop_front()
    140     {
    141         assert(sizes != nullptr && sizes->size() > 0);
    142         if (sizes->size() == 1)
    143             dealloc();
    144         else
    145             sizes->erase(sizes->begin());
    146     }
    147 
    148     // 'this' should currently not be holding anything, and copyNonFront
    149     // will make it hold a copy of all but the first element of rhs.
    150     // (This would be useful for making a type that is dereferenced by
    151     // one dimension.)
    152     void copyNonFront(const TSmallArrayVector& rhs)
    153     {
    154         assert(sizes == nullptr);
    155         if (rhs.size() > 1) {
    156             alloc();
    157             sizes->insert(sizes->begin(), rhs.sizes->begin() + 1, rhs.sizes->end());
    158         }
    159     }
    160 
    161     unsigned int getDimSize(int i) const
    162     {
    163         assert(sizes != nullptr && (int)sizes->size() > i);
    164         return (*sizes)[i].size;
    165     }
    166 
    167     void setDimSize(int i, unsigned int size) const
    168     {
    169         assert(sizes != nullptr && (int)sizes->size() > i);
    170         assert((*sizes)[i].node == nullptr);
    171         (*sizes)[i].size = size;
    172     }
    173 
    174     TIntermTyped* getDimNode(int i) const
    175     {
    176         assert(sizes != nullptr && (int)sizes->size() > i);
    177         return (*sizes)[i].node;
    178     }
    179 
    180     bool operator==(const TSmallArrayVector& rhs) const
    181     {
    182         if (sizes == nullptr && rhs.sizes == nullptr)
    183             return true;
    184         if (sizes == nullptr || rhs.sizes == nullptr)
    185             return false;
    186         return *sizes == *rhs.sizes;
    187     }
    188     bool operator!=(const TSmallArrayVector& rhs) const { return ! operator==(rhs); }
    189 
    190 protected:
    191     TSmallArrayVector(const TSmallArrayVector&);
    192 
    193     void alloc()
    194     {
    195         if (sizes == nullptr)
    196             sizes = new TVector<TArraySize>;
    197     }
    198     void dealloc()
    199     {
    200         delete sizes;
    201         sizes = nullptr;
    202     }
    203 
    204     TVector<TArraySize>* sizes; // will either hold such a pointer, or in the future, hold the two array sizes
    205 };
    206 
    207 //
    208 // Represent an array, or array of arrays, to arbitrary depth.  This is not
    209 // done through a hierarchy of types in a type tree, rather all contiguous arrayness
    210 // in the type hierarchy is localized into this single cumulative object.
    211 //
    212 // The arrayness in TTtype is a pointer, so that it can be non-allocated and zero
    213 // for the vast majority of types that are non-array types.
    214 //
    215 // Order Policy: these are all identical:
    216 //  - left to right order within a contiguous set of ...[..][..][..]... in the source language
    217 //  - index order 0, 1, 2, ... within the 'sizes' member below
    218 //  - outer-most to inner-most
    219 //
    220 struct TArraySizes {
    221     POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
    222 
    223     TArraySizes() : implicitArraySize(1) { }
    224 
    225     // For breaking into two non-shared copies, independently modifiable.
    226     TArraySizes& operator=(const TArraySizes& from)
    227     {
    228         implicitArraySize = from.implicitArraySize;
    229         sizes = from.sizes;
    230 
    231         return *this;
    232     }
    233 
    234     // translate from array-of-array semantics to container semantics
    235     int getNumDims() const { return sizes.size(); }
    236     int getDimSize(int dim) const { return sizes.getDimSize(dim); }
    237     TIntermTyped* getDimNode(int dim) const { return sizes.getDimNode(dim); }
    238     void setDimSize(int dim, int size) { sizes.setDimSize(dim, size); }
    239     int getOuterSize() const { return sizes.frontSize(); }
    240     TIntermTyped* getOuterNode() const { return sizes.frontNode(); }
    241     int getCumulativeSize() const
    242     {
    243         int size = 1;
    244         for (int d = 0; d < sizes.size(); ++d) {
    245             // this only makes sense in paths that have a known array size
    246             assert(sizes.getDimSize(d) != UnsizedArraySize);
    247             size *= sizes.getDimSize(d);
    248         }
    249         return size;
    250     }
    251     void addInnerSize() { addInnerSize((unsigned)UnsizedArraySize); }
    252     void addInnerSize(int s) { addInnerSize((unsigned)s, nullptr); }
    253     void addInnerSize(int s, TIntermTyped* n) { sizes.push_back((unsigned)s, n); }
    254     void addInnerSize(TArraySize pair) { sizes.push_back(pair.size, pair.node); }
    255     void changeOuterSize(int s) { sizes.changeFront((unsigned)s); }
    256     int getImplicitSize() const { return (int)implicitArraySize; }
    257     void setImplicitSize(int s) { implicitArraySize = s; }
    258     bool isInnerImplicit() const
    259     {
    260         for (int d = 1; d < sizes.size(); ++d) {
    261             if (sizes.getDimSize(d) == (unsigned)UnsizedArraySize)
    262                 return true;
    263         }
    264 
    265         return false;
    266     }
    267     bool isImplicit() const { return getOuterSize() == UnsizedArraySize || isInnerImplicit(); }
    268     void addOuterSizes(const TArraySizes& s) { sizes.push_front(s.sizes); }
    269     void dereference() { sizes.pop_front(); }
    270     void copyDereferenced(const TArraySizes& rhs)
    271     {
    272         assert(sizes.size() == 0);
    273         if (rhs.sizes.size() > 1)
    274             sizes.copyNonFront(rhs.sizes);
    275     }
    276 
    277     bool sameInnerArrayness(const TArraySizes& rhs) const
    278     {
    279         if (sizes.size() != rhs.sizes.size())
    280             return false;
    281 
    282         for (int d = 1; d < sizes.size(); ++d) {
    283             if (sizes.getDimSize(d) != rhs.sizes.getDimSize(d) ||
    284                 sizes.getDimNode(d) != rhs.sizes.getDimNode(d))
    285                 return false;
    286         }
    287 
    288         return true;
    289     }
    290 
    291     // Returns true if any of the dimensions of the array is sized with a node
    292     // instead of a front-end compile-time constant.
    293     bool containsNode()
    294     {
    295         for (int d = 0; d < sizes.size(); ++d) {
    296             if (sizes.getDimNode(d) != nullptr)
    297                 return true;
    298         }
    299 
    300         return false;
    301     }
    302 
    303     bool operator==(const TArraySizes& rhs) { return sizes == rhs.sizes; }
    304     bool operator!=(const TArraySizes& rhs) { return sizes != rhs.sizes; }
    305 
    306 protected:
    307     TSmallArrayVector sizes;
    308 
    309     TArraySizes(const TArraySizes&);
    310 
    311     // for tracking maximum referenced index, before an explicit size is given
    312     // applies only to the outer-most dimension
    313     int implicitArraySize;
    314 };
    315 
    316 } // end namespace glslang
    317 
    318 #endif // _ARRAYS_INCLUDED_
    319