TType: Store array sizes vector as a pointer.
This makes TType a literal type, and thus is something that could be
constexpr.
Work started by jmadill here: https://crrev.com/c/776278
Bug: angleproject:1432
Change-Id: I707ddf81eaf029f49d62d2836b7166d265cbdfa1
Reviewed-on: https://chromium-review.googlesource.com/786316
Commit-Queue: Kai Ninomiya <kainino@chromium.org>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/compiler/translator/CollectVariables.cpp b/src/compiler/translator/CollectVariables.cpp
index 1fa86bb..bd8cbc9 100644
--- a/src/compiler/translator/CollectVariables.cpp
+++ b/src/compiler/translator/CollectVariables.cpp
@@ -262,8 +262,11 @@
info->name = name;
info->mappedName = name;
info->type = GLVariableType(type);
- info->arraySizes.assign(type.getArraySizes().begin(), type.getArraySizes().end());
info->precision = GLVariablePrecision(type);
+ if (auto *arraySizes = type.getArraySizes())
+ {
+ info->arraySizes.assign(arraySizes->begin(), arraySizes->end());
+ }
}
void CollectVariablesTraverser::recordBuiltInVaryingUsed(const char *name,
@@ -581,7 +584,10 @@
variableOut->name = name.getString().c_str();
variableOut->mappedName = getMappedName(name);
- variableOut->arraySizes.assign(type.getArraySizes().begin(), type.getArraySizes().end());
+ if (auto *arraySizes = type.getArraySizes())
+ {
+ variableOut->arraySizes.assign(arraySizes->begin(), arraySizes->end());
+ }
}
Attribute CollectVariablesTraverser::recordAttribute(const TIntermSymbol &variable) const
diff --git a/src/compiler/translator/OutputHLSL.cpp b/src/compiler/translator/OutputHLSL.cpp
index bb18beb..d5ff761 100644
--- a/src/compiler/translator/OutputHLSL.cpp
+++ b/src/compiler/translator/OutputHLSL.cpp
@@ -38,9 +38,12 @@
{
TStringStream fnName;
fnName << prefix << "_";
- for (unsigned int arraySize : type.getArraySizes())
+ if (type.isArray())
{
- fnName << arraySize << "_";
+ for (unsigned int arraySize : *type.getArraySizes())
+ {
+ fnName << arraySize << "_";
+ }
}
fnName << TypeString(type);
return fnName.str();
diff --git a/src/compiler/translator/ParseContext.cpp b/src/compiler/translator/ParseContext.cpp
index 67207ca..c97f91d 100644
--- a/src/compiler/translator/ParseContext.cpp
+++ b/src/compiler/translator/ParseContext.cpp
@@ -1928,7 +1928,8 @@
// will default to setting array sizes to 1. We have not checked yet whether the initializer
// actually is an array or not. Having a non-array initializer for an unsized array will
// result in an error later, so we don't generate an error message here.
- type.sizeUnsizedArrays(initializer->getType().getArraySizes());
+ auto *arraySizes = initializer->getType().getArraySizes();
+ type.sizeUnsizedArrays(arraySizes);
}
if (!declareVariable(line, identifier, type, &variable))
{
@@ -3493,7 +3494,7 @@
if (arrayType->isUnsizedArray())
{
error(line, errorMessage, token);
- arrayType->sizeUnsizedArrays(TVector<unsigned int>());
+ arrayType->sizeUnsizedArrays(nullptr);
}
}
@@ -3546,13 +3547,13 @@
{
TIntermTyped *element = arg->getAsTyped();
ASSERT(element);
- size_t dimensionalityFromElement = element->getType().getArraySizes().size() + 1u;
- if (dimensionalityFromElement > type.getArraySizes().size())
+ size_t dimensionalityFromElement = element->getType().getNumArraySizes() + 1u;
+ if (dimensionalityFromElement > type.getNumArraySizes())
{
error(line, "constructing from a non-dereferenced array", "constructor");
return false;
}
- else if (dimensionalityFromElement < type.getArraySizes().size())
+ else if (dimensionalityFromElement < type.getNumArraySizes())
{
if (dimensionalityFromElement == 1u)
{
@@ -3585,7 +3586,7 @@
{
if (!checkUnsizedArrayConstructorArgumentDimensionality(arguments, type, line))
{
- type.sizeUnsizedArrays(TVector<unsigned int>());
+ type.sizeUnsizedArrays(nullptr);
return CreateZeroNode(type);
}
TIntermTyped *firstElement = arguments->at(0)->getAsTyped();
@@ -3594,11 +3595,11 @@
{
type.sizeOutermostUnsizedArray(static_cast<unsigned int>(arguments->size()));
}
- for (size_t i = 0; i < firstElement->getType().getArraySizes().size(); ++i)
+ for (size_t i = 0; i < firstElement->getType().getNumArraySizes(); ++i)
{
- if (type.getArraySizes()[i] == 0u)
+ if ((*type.getArraySizes())[i] == 0u)
{
- type.setArraySize(i, firstElement->getType().getArraySizes().at(i));
+ type.setArraySize(i, (*firstElement->getType().getArraySizes())[i]);
}
}
ASSERT(!type.isUnsizedArray());
@@ -4758,18 +4759,22 @@
for (TField *declarator : *declaratorList)
{
- auto declaratorArraySizes = declarator->type()->getArraySizes();
// Don't allow arrays of arrays in ESSL < 3.10.
- if (!declaratorArraySizes.empty())
+ if (declarator->type()->isArray())
{
checkArrayElementIsNotArray(typeSpecifier.getLine(), typeSpecifier);
}
+ auto *declaratorArraySizes = declarator->type()->getArraySizes();
+
TType *type = declarator->type();
*type = TType(typeSpecifier);
- for (unsigned int arraySize : declaratorArraySizes)
+ if (declaratorArraySizes != nullptr)
{
- type->makeArray(arraySize);
+ for (unsigned int arraySize : *declaratorArraySizes)
+ {
+ type->makeArray(arraySize);
+ }
}
checkIsBelowStructNestingLimit(typeSpecifier.getLine(), *declarator);
@@ -5062,20 +5067,21 @@
}
}
- if (left->isArray() || right->isArray())
+ if (left->isArray() != right->isArray())
{
+ error(loc, "array / non-array mismatch", GetOperatorString(op));
+ return false;
+ }
+
+ if (left->isArray())
+ {
+ ASSERT(right->isArray());
if (mShaderVersion < 300)
{
error(loc, "Invalid operation for arrays", GetOperatorString(op));
return false;
}
- if (left->isArray() != right->isArray())
- {
- error(loc, "array / non-array mismatch", GetOperatorString(op));
- return false;
- }
-
switch (op)
{
case EOpEqual:
@@ -5088,7 +5094,7 @@
return false;
}
// At this point, size of implicitly sized arrays should be resolved.
- if (left->getType().getArraySizes() != right->getType().getArraySizes())
+ if (*left->getType().getArraySizes() != *right->getType().getArraySizes())
{
error(loc, "array size mismatch", GetOperatorString(op));
return false;
diff --git a/src/compiler/translator/Types.cpp b/src/compiler/translator/Types.cpp
index d59a3d8..530ffe3 100644
--- a/src/compiler/translator/Types.cpp
+++ b/src/compiler/translator/Types.cpp
@@ -123,6 +123,7 @@
layoutQualifier(TLayoutQualifier::Create()),
primarySize(0),
secondarySize(0),
+ mArraySizes(nullptr),
mInterfaceBlock(nullptr),
mStructure(nullptr),
mIsStructSpecifier(false),
@@ -139,8 +140,9 @@
layoutQualifier(TLayoutQualifier::Create()),
primarySize(ps),
secondarySize(ss),
- mInterfaceBlock(0),
- mStructure(0),
+ mArraySizes(nullptr),
+ mInterfaceBlock(nullptr),
+ mStructure(nullptr),
mIsStructSpecifier(false),
mMangledName(nullptr)
{
@@ -155,8 +157,9 @@
layoutQualifier(TLayoutQualifier::Create()),
primarySize(ps),
secondarySize(ss),
- mInterfaceBlock(0),
- mStructure(0),
+ mArraySizes(nullptr),
+ mInterfaceBlock(nullptr),
+ mStructure(nullptr),
mIsStructSpecifier(false),
mMangledName(nullptr)
{
@@ -171,6 +174,7 @@
layoutQualifier(p.layoutQualifier),
primarySize(p.getPrimarySize()),
secondarySize(p.getSecondarySize()),
+ mArraySizes(nullptr),
mInterfaceBlock(nullptr),
mStructure(nullptr),
mIsStructSpecifier(false),
@@ -180,7 +184,7 @@
ASSERT(secondarySize <= 4);
if (p.isArray())
{
- mArraySizes = *p.arraySizes;
+ mArraySizes = new TVector<unsigned int>(*p.arraySizes);
}
if (p.getUserDef())
{
@@ -198,6 +202,7 @@
layoutQualifier(TLayoutQualifier::Create()),
primarySize(1),
secondarySize(1),
+ mArraySizes(nullptr),
mInterfaceBlock(nullptr),
mStructure(userDef),
mIsStructSpecifier(false),
@@ -216,6 +221,7 @@
layoutQualifier(layoutQualifierIn),
primarySize(1),
secondarySize(1),
+ mArraySizes(nullptr),
mInterfaceBlock(interfaceBlockIn),
mStructure(0),
mIsStructSpecifier(false),
@@ -223,12 +229,41 @@
{
}
-TType::TType(const TType &) = default;
-
-TType::~TType()
+TType::TType(const TType &t)
+ : type(t.type),
+ precision(t.precision),
+ qualifier(t.qualifier),
+ invariant(t.invariant),
+ memoryQualifier(t.memoryQualifier),
+ layoutQualifier(t.layoutQualifier),
+ primarySize(t.primarySize),
+ secondarySize(t.secondarySize),
+ mArraySizes(t.mArraySizes ? new TVector<unsigned int>(*t.mArraySizes) : nullptr),
+ mInterfaceBlock(t.mInterfaceBlock),
+ mStructure(t.mStructure),
+ mIsStructSpecifier(t.mIsStructSpecifier),
+ mMangledName(t.mMangledName)
{
}
+TType &TType::operator=(const TType &t)
+{
+ type = t.type;
+ precision = t.precision;
+ qualifier = t.qualifier;
+ invariant = t.invariant;
+ memoryQualifier = t.memoryQualifier;
+ layoutQualifier = t.layoutQualifier;
+ primarySize = t.primarySize;
+ secondarySize = t.secondarySize;
+ mArraySizes = t.mArraySizes ? new TVector<unsigned int>(*t.mArraySizes) : nullptr;
+ mInterfaceBlock = t.mInterfaceBlock;
+ mStructure = t.mStructure;
+ mIsStructSpecifier = t.mIsStructSpecifier;
+ mMangledName = t.mMangledName;
+ return *this;
+}
+
bool TType::canBeConstructed() const
{
switch (type)
@@ -370,10 +405,13 @@
stream << getQualifierString() << " ";
if (precision != EbpUndefined)
stream << getPrecisionString() << " ";
- for (auto arraySizeIter = mArraySizes.rbegin(); arraySizeIter != mArraySizes.rend();
- ++arraySizeIter)
+ if (mArraySizes)
{
- stream << "array[" << (*arraySizeIter) << "] of ";
+ for (auto arraySizeIter = mArraySizes->rbegin(); arraySizeIter != mArraySizes->rend();
+ ++arraySizeIter)
+ {
+ stream << "array[" << (*arraySizeIter) << "] of ";
+ }
}
if (isMatrix())
stream << getCols() << "X" << getRows() << " matrix of ";
@@ -536,13 +574,16 @@
mangledName += static_cast<char>('0' + getNominalSize());
}
- for (unsigned int arraySize : mArraySizes)
+ if (mArraySizes)
{
- char buf[20];
- snprintf(buf, sizeof(buf), "%d", arraySize);
- mangledName += '[';
- mangledName += buf;
- mangledName += ']';
+ for (unsigned int arraySize : *mArraySizes)
+ {
+ char buf[20];
+ snprintf(buf, sizeof(buf), "%d", arraySize);
+ mangledName += '[';
+ mangledName += buf;
+ mangledName += ']';
+ }
}
mangledName += ';';
@@ -566,12 +607,15 @@
if (totalSize == 0)
return 0;
- for (size_t arraySize : mArraySizes)
+ if (mArraySizes)
{
- if (arraySize > INT_MAX / totalSize)
- totalSize = INT_MAX;
- else
- totalSize *= arraySize;
+ for (size_t arraySize : *mArraySizes)
+ {
+ if (arraySize > INT_MAX / totalSize)
+ totalSize = INT_MAX;
+ else
+ totalSize *= arraySize;
+ }
}
return totalSize;
@@ -591,15 +635,18 @@
return 0;
}
- for (unsigned int arraySize : mArraySizes)
+ if (mArraySizes)
{
- if (arraySize > static_cast<unsigned int>(std::numeric_limits<int>::max() / count))
+ for (unsigned int arraySize : *mArraySizes)
{
- count = std::numeric_limits<int>::max();
- }
- else
- {
- count *= static_cast<int>(arraySize);
+ if (arraySize > static_cast<unsigned int>(std::numeric_limits<int>::max() / count))
+ {
+ count = std::numeric_limits<int>::max();
+ }
+ else
+ {
+ count *= static_cast<int>(arraySize);
+ }
}
}
@@ -608,8 +655,12 @@
unsigned int TType::getArraySizeProduct() const
{
+ if (!mArraySizes)
+ return 1u;
+
unsigned int product = 1u;
- for (unsigned int arraySize : mArraySizes)
+
+ for (unsigned int arraySize : *mArraySizes)
{
product *= arraySize;
}
@@ -618,7 +669,10 @@
bool TType::isUnsizedArray() const
{
- for (unsigned int arraySize : mArraySizes)
+ if (!mArraySizes)
+ return false;
+
+ for (unsigned int arraySize : *mArraySizes)
{
if (arraySize == 0u)
{
@@ -640,33 +694,38 @@
{
return false;
}
- if (arrayType.mArraySizes.size() != mArraySizes.size() + 1u)
+ if (arrayType.getNumArraySizes() != getNumArraySizes() + 1u)
{
return false;
}
- for (size_t i = 0; i < mArraySizes.size(); ++i)
+ if (isArray())
{
- if (mArraySizes[i] != arrayType.mArraySizes[i])
+ for (size_t i = 0; i < mArraySizes->size(); ++i)
{
- return false;
+ if ((*mArraySizes)[i] != (*arrayType.mArraySizes)[i])
+ {
+ return false;
+ }
}
}
return true;
}
-void TType::sizeUnsizedArrays(const TVector<unsigned int> &arraySizes)
+void TType::sizeUnsizedArrays(const TVector<unsigned int> *newArraySizes)
{
- for (size_t i = 0u; i < mArraySizes.size(); ++i)
+ size_t newArraySizesSize = newArraySizes ? newArraySizes->size() : 0;
+ for (size_t i = 0u; i < getNumArraySizes(); ++i)
{
- if (mArraySizes[i] == 0)
+ if ((*mArraySizes)[i] == 0)
{
- if (i < arraySizes.size())
+ if (i < newArraySizesSize)
{
- mArraySizes[i] = arraySizes[i];
+ ASSERT(newArraySizes != nullptr);
+ (*mArraySizes)[i] = (*newArraySizes)[i];
}
else
{
- mArraySizes[i] = 1u;
+ (*mArraySizes)[i] = 1u;
}
}
}
@@ -676,8 +735,8 @@
void TType::sizeOutermostUnsizedArray(unsigned int arraySize)
{
ASSERT(isArray());
- ASSERT(mArraySizes.back() == 0u);
- mArraySizes.back() = arraySize;
+ ASSERT(mArraySizes->back() == 0u);
+ mArraySizes->back() = arraySize;
}
void TType::setBasicType(TBasicType t)
@@ -711,31 +770,39 @@
void TType::makeArray(unsigned int s)
{
- mArraySizes.push_back(s);
+ if (!mArraySizes)
+ mArraySizes = new TVector<unsigned int>();
+
+ mArraySizes->push_back(s);
invalidateMangledName();
}
void TType::makeArrays(const TVector<unsigned int> &sizes)
{
- mArraySizes.insert(mArraySizes.end(), sizes.begin(), sizes.end());
+ if (!mArraySizes)
+ mArraySizes = new TVector<unsigned int>();
+
+ mArraySizes->insert(mArraySizes->end(), sizes.begin(), sizes.end());
invalidateMangledName();
}
void TType::setArraySize(size_t arrayDimension, unsigned int s)
{
- ASSERT(arrayDimension < mArraySizes.size());
- if (mArraySizes.at(arrayDimension) != s)
+ ASSERT(mArraySizes != nullptr);
+ ASSERT(arrayDimension < mArraySizes->size());
+ if (mArraySizes->at(arrayDimension) != s)
{
- mArraySizes[arrayDimension] = s;
+ (*mArraySizes)[arrayDimension] = s;
invalidateMangledName();
}
}
void TType::toArrayElementType()
{
- if (mArraySizes.size() > 0)
+ ASSERT(mArraySizes != nullptr);
+ if (mArraySizes->size() > 0)
{
- mArraySizes.pop_back();
+ mArraySizes->pop_back();
invalidateMangledName();
}
}
diff --git a/src/compiler/translator/Types.h b/src/compiler/translator/Types.h
index 63d6242..7dc84c5 100644
--- a/src/compiler/translator/Types.h
+++ b/src/compiler/translator/Types.h
@@ -194,10 +194,8 @@
TType(TInterfaceBlock *interfaceBlockIn,
TQualifier qualifierIn,
TLayoutQualifier layoutQualifierIn);
- ~TType();
-
- TType(const TType &);
- TType &operator=(const TType &) = default;
+ TType(const TType &t);
+ TType &operator=(const TType &t);
TBasicType getBasicType() const { return type; }
void setBasicType(TBasicType t);
@@ -241,22 +239,27 @@
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; }
- const TVector<unsigned int> &getArraySizes() const { return mArraySizes; }
+ bool isArray() const { return mArraySizes != nullptr && !mArraySizes->empty(); }
+ bool isArrayOfArrays() const { return isArray() && mArraySizes->size() > 1u; }
+ size_t getNumArraySizes() const { return isArray() ? mArraySizes->size() : 0; }
+ const TVector<unsigned int> *getArraySizes() const { return mArraySizes; }
unsigned int getArraySizeProduct() const;
bool isUnsizedArray() const;
- unsigned int getOutermostArraySize() const { return mArraySizes.back(); }
-
+ unsigned int getOutermostArraySize() const {
+ ASSERT(isArray());
+ return mArraySizes->back();
+ }
void makeArray(unsigned int s);
+
// sizes contain new outermost array sizes.
void makeArrays(const TVector<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 arraySizes. In case there are more unsized arrays
- // than there are sizes in arraySizes, defaults to setting array sizes to 1.
- void sizeUnsizedArrays(const TVector<unsigned int> &arraySizes);
+ // 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 TVector<unsigned int> *newArraySizes);
// Will size the outermost array according to arraySize.
void sizeOutermostUnsizedArray(unsigned int arraySize);
@@ -291,8 +294,12 @@
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 && mArraySizes == right.mArraySizes &&
+ secondarySize == right.secondarySize && arraySizesEqual &&
mStructure == right.mStructure;
// don't check the qualifier, it's not ever what's being sought after
}
@@ -305,12 +312,14 @@
return primarySize < right.primarySize;
if (secondarySize != right.secondarySize)
return secondarySize < right.secondarySize;
- if (mArraySizes.size() != right.mArraySizes.size())
- return mArraySizes.size() < right.mArraySizes.size();
- for (size_t i = 0; i < mArraySizes.size(); ++i)
+ 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 ((*mArraySizes)[i] != (*right.mArraySizes)[i])
+ return (*mArraySizes)[i] < (*right.mArraySizes)[i];
}
if (mStructure != right.mStructure)
return mStructure < right.mStructure;
@@ -384,7 +393,7 @@
// 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.
- TVector<unsigned int> mArraySizes;
+ TVector<unsigned int> *mArraySizes;
// This is set only in the following two cases:
// 1) Represents an interface block.
diff --git a/src/compiler/translator/util.cpp b/src/compiler/translator/util.cpp
index fdd04cb..9738370 100644
--- a/src/compiler/translator/util.cpp
+++ b/src/compiler/translator/util.cpp
@@ -456,7 +456,10 @@
TString ArrayString(const TType &type)
{
TStringStream arrayString;
- const TVector<unsigned int> &arraySizes = type.getArraySizes();
+ if (!type.isArray())
+ return arrayString.str();
+
+ const TVector<unsigned int> &arraySizes = *type.getArraySizes();
for (auto arraySizeIter = arraySizes.rbegin(); arraySizeIter != arraySizes.rend();
++arraySizeIter)
{