summaryrefslogtreecommitdiffstats
path: root/gfx/angle/checkout/src/compiler/translator/Types.h
blob: 623a3b335bd11fcafc61e40bf1a2dbc64719389f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
//
// Copyright 2002 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 COMPILER_TRANSLATOR_TYPES_H_
#define COMPILER_TRANSLATOR_TYPES_H_

#include "common/angleutils.h"
#include "common/debug.h"

#include "compiler/translator/BaseTypes.h"
#include "compiler/translator/Common.h"
#include "compiler/translator/ImmutableString.h"
#include "compiler/translator/SymbolUniqueId.h"

namespace sh
{

struct TPublicType;
class TType;
class TInterfaceBlock;
class TStructure;
class TSymbol;
class TVariable;
class TIntermSymbol;
class TSymbolTable;

class TField : angle::NonCopyable
{
  public:
    POOL_ALLOCATOR_NEW_DELETE
    TField(TType *type, const ImmutableString &name, const TSourceLoc &line, SymbolType symbolType)
        : mType(type), mName(name), mLine(line), mSymbolType(symbolType)
    {
        ASSERT(mSymbolType != SymbolType::Empty);
    }

    // TODO(alokp): We should only return const type.
    // Fix it by tweaking grammar.
    TType *type() { return mType; }
    const TType *type() const { return mType; }
    const ImmutableString &name() const { return mName; }
    const TSourceLoc &line() const { return mLine; }
    SymbolType symbolType() const { return mSymbolType; }

  private:
    TType *mType;
    const ImmutableString mName;
    const TSourceLoc mLine;
    const SymbolType mSymbolType;
};

typedef TVector<TField *> TFieldList;

class TFieldListCollection : angle::NonCopyable
{
  public:
    const TFieldList &fields() const { return *mFields; }

    bool containsArrays() const;
    bool containsMatrices() const;
    bool containsType(TBasicType t) const;
    bool containsSamplers() const;

    size_t objectSize() const;
    // How many locations the field list consumes as a uniform.
    int getLocationCount() const;
    int deepestNesting() const;
    const TString &mangledFieldList() const;

  protected:
    TFieldListCollection(const TFieldList *fields);

    const TFieldList *mFields;

  private:
    size_t calculateObjectSize() const;
    int calculateDeepestNesting() const;
    TString buildMangledFieldList() const;

    mutable size_t mObjectSize;
    mutable int mDeepestNesting;
    mutable TString mMangledFieldList;
};

//
// Base class for things that have a type.
//
class TType
{
  public:
    POOL_ALLOCATOR_NEW_DELETE
    TType();
    explicit TType(TBasicType t, uint8_t ps = 1, uint8_t ss = 1);
    TType(TBasicType t, TPrecision p, TQualifier q = EvqTemporary, uint8_t ps = 1, uint8_t ss = 1);
    explicit TType(const TPublicType &p);
    TType(const TStructure *userDef, bool isStructSpecifier);
    TType(const TInterfaceBlock *interfaceBlockIn,
          TQualifier qualifierIn,
          TLayoutQualifier layoutQualifierIn);
    TType(const TType &t);
    TType &operator=(const TType &t);

    constexpr TType(TBasicType t,
                    TPrecision p,
                    TQualifier q,
                    uint8_t ps,
                    uint8_t ss,
                    const TSpan<const unsigned int> arraySizes,
                    const char *mangledName)
        : type(t),
          precision(p),
          qualifier(q),
          invariant(false),
          precise(false),
          memoryQualifier(TMemoryQualifier::Create()),
          layoutQualifier(TLayoutQualifier::Create()),
          primarySize(ps),
          secondarySize(ss),
          mArraySizes(arraySizes),
          mArraySizesStorage(nullptr),
          mInterfaceBlock(nullptr),
          mStructure(nullptr),
          mIsStructSpecifier(false),
          mInterfaceBlockFieldIndex(0),
          mMangledName(mangledName)
    {}

    constexpr TType(TType &&t)
        : type(t.type),
          precision(t.precision),
          qualifier(t.qualifier),
          invariant(t.invariant),
          precise(t.precise),
          memoryQualifier(t.memoryQualifier),
          layoutQualifier(t.layoutQualifier),
          primarySize(t.primarySize),
          secondarySize(t.secondarySize),
          mArraySizes(t.mArraySizes),
          mArraySizesStorage(t.mArraySizesStorage),
          mInterfaceBlock(t.mInterfaceBlock),
          mStructure(t.mStructure),
          mIsStructSpecifier(t.mIsStructSpecifier),
          mInterfaceBlockFieldIndex(0),
          mMangledName(t.mMangledName)
    {
        t.mArraySizesStorage = nullptr;
    }

    constexpr TBasicType getBasicType() const { return type; }
    void setBasicType(TBasicType t);

    TPrecision getPrecision() const { return precision; }
    void setPrecision(TPrecision p) { precision = p; }

    constexpr TQualifier getQualifier() const { return qualifier; }
    void setQualifier(TQualifier q) { qualifier = q; }

    bool isInvariant() const { return invariant; }
    void setInvariant(bool i) { invariant = i; }

    bool isPrecise() const { return precise; }
    void setPrecise(bool i) { precise = i; }

    TMemoryQualifier getMemoryQualifier() const { return memoryQualifier; }
    void setMemoryQualifier(const TMemoryQualifier &mq) { memoryQualifier = mq; }

    TLayoutQualifier getLayoutQualifier() const { return layoutQualifier; }
    void setLayoutQualifier(TLayoutQualifier lq) { layoutQualifier = lq; }

    uint8_t getNominalSize() const { return primarySize; }
    uint8_t getSecondarySize() const { return secondarySize; }
    uint8_t getCols() const
    {
        ASSERT(isMatrix());
        return primarySize;
    }
    uint8_t getRows() const
    {
        ASSERT(isMatrix());
        return secondarySize;
    }
    void setPrimarySize(uint8_t ps);
    void setSecondarySize(uint8_t ss);

    // Full size of single instance of type
    size_t getObjectSize() const;

    // Get how many locations this type consumes as a uniform.
    int getLocationCount() const;

    bool isMatrix() const { return primarySize > 1 && secondarySize > 1; }
    bool isNonSquareMatrix() const { return isMatrix() && primarySize != secondarySize; }
    bool isArray() const { return !mArraySizes.empty(); }
    bool isArrayOfArrays() const { return mArraySizes.size() > 1u; }
    size_t getNumArraySizes() const { return mArraySizes.size(); }
    const TSpan<const unsigned int> &getArraySizes() const { return mArraySizes; }
    unsigned int getArraySizeProduct() const;
    bool isUnsizedArray() const;
    unsigned int getOutermostArraySize() const
    {
        ASSERT(isArray());
        return mArraySizes.back();
    }
    void makeArray(unsigned int s);

    // sizes contain new outermost array sizes.
    void makeArrays(const TSpan<const unsigned int> &sizes);
    // Here, the array dimension value 0 corresponds to the innermost array.
    void setArraySize(size_t arrayDimension, unsigned int s);

    // Will set unsized array sizes according to newArraySizes. In case there are more
    // unsized arrays than there are sizes in newArraySizes, defaults to setting any
    // remaining array sizes to 1.
    void sizeUnsizedArrays(const TSpan<const unsigned int> &newArraySizes);

    // Will size the outermost array according to arraySize.
    void sizeOutermostUnsizedArray(unsigned int arraySize);

    // Note that the array element type might still be an array type in GLSL ES version >= 3.10.
    void toArrayElementType();
    // Removes all array sizes.
    void toArrayBaseType();
    // Turns a matrix into a column of it.
    void toMatrixColumnType();
    // Turns a matrix or vector into a component of it.
    void toComponentType();

    const TInterfaceBlock *getInterfaceBlock() const { return mInterfaceBlock; }
    void setInterfaceBlock(const TInterfaceBlock *interfaceBlockIn);
    bool isInterfaceBlock() const { return type == EbtInterfaceBlock; }

    void setInterfaceBlockField(const TInterfaceBlock *interfaceBlockIn, size_t fieldIndex);
    size_t getInterfaceBlockFieldIndex() const { return mInterfaceBlockFieldIndex; }

    bool isVector() const { return primarySize > 1 && secondarySize == 1; }
    bool isVectorArray() const { return primarySize > 1 && secondarySize == 1 && isArray(); }
    bool isRank0() const { return primarySize == 1 && secondarySize == 1; }
    bool isScalar() const
    {
        return primarySize == 1 && secondarySize == 1 && !mStructure && !isArray();
    }
    bool isScalarArray() const
    {
        return primarySize == 1 && secondarySize == 1 && !mStructure && isArray();
    }
    bool isScalarFloat() const { return isScalar() && type == EbtFloat; }
    bool isScalarInt() const { return isScalar() && (type == EbtInt || type == EbtUInt); }

    bool canBeConstructed() const;

    const TStructure *getStruct() const { return mStructure; }

    static constexpr char GetSizeMangledName(uint8_t primarySize, uint8_t secondarySize)
    {
        unsigned int sizeKey = (secondarySize - 1u) * 4u + primarySize - 1u;
        if (sizeKey < 10u)
        {
            return static_cast<char>('0' + sizeKey);
        }
        return static_cast<char>('A' + sizeKey - 10);
    }
    const char *getMangledName() const;

    bool sameNonArrayType(const TType &right) const;

    // Returns true if arrayType is an array made of this type.
    bool isElementTypeOf(const TType &arrayType) const;

    bool operator==(const TType &right) const
    {
        size_t numArraySizesL = getNumArraySizes();
        size_t numArraySizesR = right.getNumArraySizes();
        bool arraySizesEqual  = numArraySizesL == numArraySizesR &&
                               (numArraySizesL == 0 || mArraySizes == right.mArraySizes);
        return type == right.type && primarySize == right.primarySize &&
               secondarySize == right.secondarySize && arraySizesEqual &&
               mStructure == right.mStructure;
        // 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;
        size_t numArraySizesL = getNumArraySizes();
        size_t numArraySizesR = right.getNumArraySizes();
        if (numArraySizesL != numArraySizesR)
            return numArraySizesL < numArraySizesR;
        for (size_t i = 0; i < numArraySizesL; ++i)
        {
            if (mArraySizes[i] != right.mArraySizes[i])
                return mArraySizes[i] < right.mArraySizes[i];
        }
        if (mStructure != right.mStructure)
            return mStructure < right.mStructure;

        return false;
    }

    const char *getBasicString() const { return sh::getBasicString(type); }

    const char *getPrecisionString() const { return sh::getPrecisionString(precision); }
    const char *getQualifierString() const { return sh::getQualifierString(qualifier); }

    const char *getBuiltInTypeNameString() 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;

    bool isNamelessStruct() const;

    bool isStructureContainingArrays() const;
    bool isStructureContainingMatrices() const;
    bool isStructureContainingType(TBasicType t) const;
    bool isStructureContainingSamplers() const;
    bool isInterfaceBlockContainingType(TBasicType t) const;

    bool isStructSpecifier() const { return mIsStructSpecifier; }

    // Return true if variables of this type should be replaced with an inline constant value if
    // such is available. False will be returned in cases where output doesn't support
    // TIntermConstantUnion nodes of the type, or if the type contains a lot of fields and creating
    // several copies of it in the output code is undesirable for performance.
    bool canReplaceWithConstantUnion() const;

    // The char arrays passed in must be pool allocated or static.
    void createSamplerSymbols(const ImmutableString &namePrefix,
                              const TString &apiNamePrefix,
                              TVector<const TVariable *> *outputSymbols,
                              TMap<const TVariable *, TString> *outputSymbolsToAPINames,
                              TSymbolTable *symbolTable) const;

    // Initializes all lazily-initialized members.
    void realize();

    bool isSampler() const { return IsSampler(type); }
    bool isSamplerCube() const { return type == EbtSamplerCube; }
    bool isAtomicCounter() const { return IsAtomicCounter(type); }
    bool isSamplerVideoWEBGL() const { return type == EbtSamplerVideoWEBGL; }
    bool isImage() const { return IsImage(type); }
    bool isPixelLocal() const { return IsPixelLocal(type); }

  private:
    constexpr void invalidateMangledName() { mMangledName = nullptr; }
    const char *buildMangledName() const;
    constexpr void onArrayDimensionsChange(const TSpan<const unsigned int> &sizes)
    {
        mArraySizes = sizes;
        invalidateMangledName();
    }

    TBasicType type;
    TPrecision precision;
    TQualifier qualifier;
    bool invariant;
    bool precise;

    TMemoryQualifier memoryQualifier;
    TLayoutQualifier layoutQualifier;
    uint8_t primarySize;    // size of vector or cols matrix
    uint8_t secondarySize;  // rows of a matrix

    // Used to make an array type. Outermost array size is stored at the end of the vector. Having 0
    // in this vector means an unsized array.
    TSpan<const unsigned int> mArraySizes;
    // Storage for mArraySizes, if any.  This is usually the case, except for constexpr TTypes which
    // only have a valid mArraySizes (with mArraySizesStorage being nullptr).  Therefore, all
    // modifications to array sizes happen on the storage (and if dimensions change, mArraySizes is
    // also updated) and all reads are from mArraySizes.
    TVector<unsigned int> *mArraySizesStorage;

    // This is set only in the following two cases:
    // 1) Represents an interface block.
    // 2) Represents the member variable of an unnamed interface block.
    // It's nullptr also for members of named interface blocks.
    const TInterfaceBlock *mInterfaceBlock;

    // nullptr unless this is a struct
    const TStructure *mStructure;
    bool mIsStructSpecifier;

    // If this is a field of a nameless interface block, this would indicate which member it's
    // refering to.
    size_t mInterfaceBlockFieldIndex;

    mutable const char *mMangledName;
};

// TTypeSpecifierNonArray stores all of the necessary fields for type_specifier_nonarray from the
// grammar
struct TTypeSpecifierNonArray
{
    TBasicType type;
    uint8_t primarySize;    // size of vector or cols of matrix
    uint8_t secondarySize;  // rows of matrix
    const TStructure *userDef;
    TSourceLoc line;

    // true if the type was defined by a struct specifier rather than a reference to a type name.
    bool isStructSpecifier;

    void initialize(TBasicType aType, const TSourceLoc &aLine)
    {
        ASSERT(aType != EbtStruct);
        type              = aType;
        primarySize       = 1;
        secondarySize     = 1;
        userDef           = nullptr;
        line              = aLine;
        isStructSpecifier = false;
    }

    void initializeStruct(const TStructure *aUserDef,
                          bool aIsStructSpecifier,
                          const TSourceLoc &aLine)
    {
        type              = EbtStruct;
        primarySize       = 1;
        secondarySize     = 1;
        userDef           = aUserDef;
        line              = aLine;
        isStructSpecifier = aIsStructSpecifier;
    }

    void setAggregate(uint8_t size) { primarySize = size; }

    void setMatrix(uint8_t columns, uint8_t rows)
    {
        ASSERT(columns > 1 && rows > 1 && columns <= 4 && rows <= 4);
        primarySize   = columns;
        secondarySize = rows;
    }

    bool isMatrix() const { return primarySize > 1 && secondarySize > 1; }

    bool isVector() const { return primarySize > 1 && secondarySize == 1; }
};

//
// 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
{
    // Must have a trivial default constructor since it is used in YYSTYPE.
    TPublicType() = default;

    void initialize(const TTypeSpecifierNonArray &typeSpecifier, TQualifier q);
    void initializeBasicType(TBasicType basicType);

    TBasicType getBasicType() const { return typeSpecifierNonArray.type; }
    void setBasicType(TBasicType basicType) { typeSpecifierNonArray.type = basicType; }

    uint8_t getPrimarySize() const { return typeSpecifierNonArray.primarySize; }
    uint8_t getSecondarySize() const { return typeSpecifierNonArray.secondarySize; }

    const TStructure *getUserDef() const { return typeSpecifierNonArray.userDef; }
    const TSourceLoc &getLine() const { return typeSpecifierNonArray.line; }

    bool isStructSpecifier() const { return typeSpecifierNonArray.isStructSpecifier; }

    bool isStructureContainingArrays() const;
    bool isStructureContainingType(TBasicType t) const;
    void setArraySizes(TVector<unsigned int> *sizes);
    bool isArray() const;
    void clearArrayness();
    bool isAggregate() const;

    TTypeSpecifierNonArray typeSpecifierNonArray;
    TLayoutQualifier layoutQualifier;
    TMemoryQualifier memoryQualifier;
    TQualifier qualifier;
    bool invariant;
    bool precise;
    TPrecision precision;

    // Either nullptr or empty in case the type is not an array. The last element is the outermost
    // array size. Note that due to bison restrictions, copies of the public type created by the
    // copy constructor share the same arraySizes pointer.
    const TVector<unsigned int> *arraySizes;
};

}  // namespace sh

#endif  // COMPILER_TRANSLATOR_TYPES_H_