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