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