• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include <algorithm>
45 
46 namespace glslang {
47 
48 // This is used to mean there is no size yet (unsized), it is waiting to get a size from somewhere else.
49 const int UnsizedArraySize = 0;
50 
51 class TIntermTyped;
52 extern bool SameSpecializationConstants(TIntermTyped*, TIntermTyped*);
53 
54 // Specialization constants need both a nominal size and a node that defines
55 // the specialization constant being used.  Array types are the same when their
56 // size and specialization constant nodes are the same.
57 struct TArraySize {
58     unsigned int size;
59     TIntermTyped* node;  // nullptr means no specialization constant node
60     bool operator==(const TArraySize& rhs) const
61     {
62         if (size != rhs.size)
63             return false;
64         if (node == nullptr || rhs.node == nullptr)
65             return node == rhs.node;
66 
67         return SameSpecializationConstants(node, rhs.node);
68     }
69 };
70 
71 //
72 // TSmallArrayVector is used as the container for the set of sizes in TArraySizes.
73 // It has generic-container semantics, while TArraySizes has array-of-array semantics.
74 // That is, TSmallArrayVector should be more focused on mechanism and TArraySizes on policy.
75 //
76 struct TSmallArrayVector {
77     //
78     // TODO: memory: TSmallArrayVector is intended to be smaller.
79     // Almost all arrays could be handled by two sizes each fitting
80     // in 16 bits, needing a real vector only in the cases where there
81     // are more than 3 sizes or a size needing more than 16 bits.
82     //
83     POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
84 
TSmallArrayVectorTSmallArrayVector85     TSmallArrayVector() : sizes(nullptr) { }
~TSmallArrayVectorTSmallArrayVector86     virtual ~TSmallArrayVector() { dealloc(); }
87 
88     // For breaking into two non-shared copies, independently modifiable.
89     TSmallArrayVector& operator=(const TSmallArrayVector& from)
90     {
91         if (from.sizes == nullptr)
92             sizes = nullptr;
93         else {
94             alloc();
95             *sizes = *from.sizes;
96         }
97 
98         return *this;
99     }
100 
sizeTSmallArrayVector101     int size() const
102     {
103         if (sizes == nullptr)
104             return 0;
105         return (int)sizes->size();
106     }
107 
frontSizeTSmallArrayVector108     unsigned int frontSize() const
109     {
110         assert(sizes != nullptr && sizes->size() > 0);
111         return sizes->front().size;
112     }
113 
frontNodeTSmallArrayVector114     TIntermTyped* frontNode() const
115     {
116         assert(sizes != nullptr && sizes->size() > 0);
117         return sizes->front().node;
118     }
119 
changeFrontTSmallArrayVector120     void changeFront(unsigned int s)
121     {
122         assert(sizes != nullptr);
123         // this should only happen for implicitly sized arrays, not specialization constants
124         assert(sizes->front().node == nullptr);
125         sizes->front().size = s;
126     }
127 
push_backTSmallArrayVector128     void push_back(unsigned int e, TIntermTyped* n)
129     {
130         alloc();
131         TArraySize pair = { e, n };
132         sizes->push_back(pair);
133     }
134 
push_backTSmallArrayVector135     void push_back(const TSmallArrayVector& newDims)
136     {
137         alloc();
138         sizes->insert(sizes->end(), newDims.sizes->begin(), newDims.sizes->end());
139     }
140 
pop_frontTSmallArrayVector141     void pop_front()
142     {
143         assert(sizes != nullptr && sizes->size() > 0);
144         if (sizes->size() == 1)
145             dealloc();
146         else
147             sizes->erase(sizes->begin());
148     }
149 
pop_backTSmallArrayVector150     void pop_back()
151     {
152         assert(sizes != nullptr && sizes->size() > 0);
153         if (sizes->size() == 1)
154             dealloc();
155         else
156             sizes->resize(sizes->size() - 1);
157     }
158 
159     // 'this' should currently not be holding anything, and copyNonFront
160     // will make it hold a copy of all but the first element of rhs.
161     // (This would be useful for making a type that is dereferenced by
162     // one dimension.)
copyNonFrontTSmallArrayVector163     void copyNonFront(const TSmallArrayVector& rhs)
164     {
165         assert(sizes == nullptr);
166         if (rhs.size() > 1) {
167             alloc();
168             sizes->insert(sizes->begin(), rhs.sizes->begin() + 1, rhs.sizes->end());
169         }
170     }
171 
getDimSizeTSmallArrayVector172     unsigned int getDimSize(int i) const
173     {
174         assert(sizes != nullptr && (int)sizes->size() > i);
175         return (*sizes)[i].size;
176     }
177 
setDimSizeTSmallArrayVector178     void setDimSize(int i, unsigned int size) const
179     {
180         assert(sizes != nullptr && (int)sizes->size() > i);
181         assert((*sizes)[i].node == nullptr);
182         (*sizes)[i].size = size;
183     }
184 
getDimNodeTSmallArrayVector185     TIntermTyped* getDimNode(int i) const
186     {
187         assert(sizes != nullptr && (int)sizes->size() > i);
188         return (*sizes)[i].node;
189     }
190 
191     bool operator==(const TSmallArrayVector& rhs) const
192     {
193         if (sizes == nullptr && rhs.sizes == nullptr)
194             return true;
195         if (sizes == nullptr || rhs.sizes == nullptr)
196             return false;
197         return *sizes == *rhs.sizes;
198     }
199     bool operator!=(const TSmallArrayVector& rhs) const { return ! operator==(rhs); }
200 
201 protected:
202     TSmallArrayVector(const TSmallArrayVector&);
203 
allocTSmallArrayVector204     void alloc()
205     {
206         if (sizes == nullptr)
207             sizes = new TVector<TArraySize>;
208     }
deallocTSmallArrayVector209     void dealloc()
210     {
211         delete sizes;
212         sizes = nullptr;
213     }
214 
215     TVector<TArraySize>* sizes; // will either hold such a pointer, or in the future, hold the two array sizes
216 };
217 
218 //
219 // Represent an array, or array of arrays, to arbitrary depth.  This is not
220 // done through a hierarchy of types in a type tree, rather all contiguous arrayness
221 // in the type hierarchy is localized into this single cumulative object.
222 //
223 // The arrayness in TTtype is a pointer, so that it can be non-allocated and zero
224 // for the vast majority of types that are non-array types.
225 //
226 // Order Policy: these are all identical:
227 //  - left to right order within a contiguous set of ...[..][..][..]... in the source language
228 //  - index order 0, 1, 2, ... within the 'sizes' member below
229 //  - outer-most to inner-most
230 //
231 struct TArraySizes {
232     POOL_ALLOCATOR_NEW_DELETE(GetThreadPoolAllocator())
233 
TArraySizesTArraySizes234     TArraySizes() : implicitArraySize(0), implicitlySized(true), variablyIndexed(false){ }
235 
236     // For breaking into two non-shared copies, independently modifiable.
237     TArraySizes& operator=(const TArraySizes& from)
238     {
239         implicitArraySize = from.implicitArraySize;
240         variablyIndexed = from.variablyIndexed;
241         sizes = from.sizes;
242         implicitlySized = from.implicitlySized;
243 
244         return *this;
245     }
246 
247     // translate from array-of-array semantics to container semantics
getNumDimsTArraySizes248     int getNumDims() const { return sizes.size(); }
getDimSizeTArraySizes249     int getDimSize(int dim) const { return sizes.getDimSize(dim); }
getDimNodeTArraySizes250     TIntermTyped* getDimNode(int dim) const { return sizes.getDimNode(dim); }
setDimSizeTArraySizes251     void setDimSize(int dim, int size) { sizes.setDimSize(dim, size); }
getOuterSizeTArraySizes252     int getOuterSize() const { return sizes.frontSize(); }
getOuterNodeTArraySizes253     TIntermTyped* getOuterNode() const { return sizes.frontNode(); }
getCumulativeSizeTArraySizes254     int getCumulativeSize() const
255     {
256         int size = 1;
257         for (int d = 0; d < sizes.size(); ++d) {
258             // this only makes sense in paths that have a known array size
259             assert(sizes.getDimSize(d) != UnsizedArraySize);
260             size *= sizes.getDimSize(d);
261         }
262         return size;
263     }
addInnerSizeTArraySizes264     void addInnerSize() { addInnerSize((unsigned)UnsizedArraySize); }
addInnerSizeTArraySizes265     void addInnerSize(int s) { addInnerSize((unsigned)s, nullptr); }
addInnerSizeTArraySizes266     void addInnerSize(int s, TIntermTyped* n) { sizes.push_back((unsigned)s, n); }
addInnerSizeTArraySizes267     void addInnerSize(TArraySize pair) {
268         sizes.push_back(pair.size, pair.node);
269         implicitlySized = false;
270     }
addInnerSizesTArraySizes271     void addInnerSizes(const TArraySizes& s) { sizes.push_back(s.sizes); }
changeOuterSizeTArraySizes272     void changeOuterSize(int s) {
273         sizes.changeFront((unsigned)s);
274         implicitlySized = false;
275     }
getImplicitSizeTArraySizes276     int getImplicitSize() const { return implicitArraySize > 0 ? implicitArraySize : 1; }
updateImplicitSizeTArraySizes277     void updateImplicitSize(int s) {
278         implicitArraySize = (std::max)(implicitArraySize, s);
279     }
isInnerUnsizedTArraySizes280     bool isInnerUnsized() const
281     {
282         for (int d = 1; d < sizes.size(); ++d) {
283             if (sizes.getDimSize(d) == (unsigned)UnsizedArraySize)
284                 return true;
285         }
286 
287         return false;
288     }
clearInnerUnsizedTArraySizes289     bool clearInnerUnsized()
290     {
291         for (int d = 1; d < sizes.size(); ++d) {
292             if (sizes.getDimSize(d) == (unsigned)UnsizedArraySize)
293                 setDimSize(d, 1);
294         }
295 
296         return false;
297     }
isInnerSpecializationTArraySizes298     bool isInnerSpecialization() const
299     {
300         for (int d = 1; d < sizes.size(); ++d) {
301             if (sizes.getDimNode(d) != nullptr)
302                 return true;
303         }
304 
305         return false;
306     }
isOuterSpecializationTArraySizes307     bool isOuterSpecialization()
308     {
309         return sizes.getDimNode(0) != nullptr;
310     }
311 
hasUnsizedTArraySizes312     bool hasUnsized() const { return getOuterSize() == UnsizedArraySize || isInnerUnsized(); }
isSizedTArraySizes313     bool isSized() const { return getOuterSize() != UnsizedArraySize; }
isImplicitlySizedTArraySizes314     bool isImplicitlySized() const { return implicitlySized; }
isDefaultImplicitlySizedTArraySizes315     bool isDefaultImplicitlySized() const { return implicitlySized && implicitArraySize == 0; }
setImplicitlySizedTArraySizes316     void setImplicitlySized(bool isImplicitSizing) { implicitlySized = isImplicitSizing; }
dereferenceTArraySizes317     void dereference() { sizes.pop_front(); }
removeLastSizeTArraySizes318     void removeLastSize() { sizes.pop_back(); }
copyDereferencedTArraySizes319     void copyDereferenced(const TArraySizes& rhs)
320     {
321         assert(sizes.size() == 0);
322         if (rhs.sizes.size() > 1)
323             sizes.copyNonFront(rhs.sizes);
324     }
325 
sameInnerArraynessTArraySizes326     bool sameInnerArrayness(const TArraySizes& rhs) const
327     {
328         if (sizes.size() != rhs.sizes.size())
329             return false;
330 
331         for (int d = 1; d < sizes.size(); ++d) {
332             if (sizes.getDimSize(d) != rhs.sizes.getDimSize(d) ||
333                 sizes.getDimNode(d) != rhs.sizes.getDimNode(d))
334                 return false;
335         }
336 
337         return true;
338     }
339 
setVariablyIndexedTArraySizes340     void setVariablyIndexed() { variablyIndexed = true; }
isVariablyIndexedTArraySizes341     bool isVariablyIndexed() const { return variablyIndexed; }
342 
343     bool operator==(const TArraySizes& rhs) const { return sizes == rhs.sizes; }
344     bool operator!=(const TArraySizes& rhs) const { return sizes != rhs.sizes; }
345 
346 protected:
347     TSmallArrayVector sizes;
348 
349     TArraySizes(const TArraySizes&);
350 
351     // For tracking maximum referenced compile-time constant index.
352     // Applies only to the outer-most dimension. Potentially becomes
353     // the implicit size of the array, if not variably indexed and
354     // otherwise legal.
355     int implicitArraySize;
356     bool implicitlySized;
357     bool variablyIndexed;  // true if array is indexed with a non compile-time constant
358 };
359 
360 } // end namespace glslang
361 
362 #endif // _ARRAYS_INCLUDED_
363