Types: Fix #1290: Rationalize and correct "mixed" style array dimensioning.
There a couple functional problems, which when reduced down also led to some good simplifications and rationalization. So, this commit: - corrects "mixed" functionality: int[A] f[B] -> f[B][A] - correct multi-identifier decls: int[A] f[B], g[C] -> f and g are independently sized. - increases symmetry between different places in the code that do this - makes fewer ways to do the same thing; several methods are just gone now - makes more clear when something is copied or shared
This commit is contained in:
@@ -436,28 +436,20 @@ bool HlslGrammar::acceptDeclaration(TIntermNode*& nodeList)
|
||||
if (declaredType.getQualifier().storage == EvqTemporary && parseContext.symbolTable.atGlobalLevel())
|
||||
declaredType.getQualifier().storage = EvqUniform;
|
||||
|
||||
// recognize array_specifier
|
||||
TArraySizes* arraySizes = nullptr;
|
||||
acceptArraySpecifier(arraySizes);
|
||||
|
||||
// We can handle multiple variables per type declaration, so
|
||||
// the number of types can expand when arrayness is different.
|
||||
TType variableType;
|
||||
variableType.shallowCopy(declaredType);
|
||||
|
||||
// recognize array_specifier
|
||||
TArraySizes* arraySizes = nullptr;
|
||||
acceptArraySpecifier(arraySizes);
|
||||
|
||||
// Fix arrayness in the variableType
|
||||
if (declaredType.isImplicitlySizedArray()) {
|
||||
// Because "int[] a = int[2](...), b = int[3](...)" makes two arrays a and b
|
||||
// of different sizes, for this case sharing the shallow copy of arrayness
|
||||
// with the parseType oversubscribes it, so get a deep copy of the arrayness.
|
||||
variableType.newArraySizes(declaredType.getArraySizes());
|
||||
}
|
||||
if (arraySizes || variableType.isArray()) {
|
||||
// In the most general case, arrayness is potentially coming both from the
|
||||
// declared type and from the variable: "int[] a[];" or just one or the other.
|
||||
// Merge it all to the variableType, so all arrayness is part of the variableType.
|
||||
parseContext.arrayDimMerge(variableType, arraySizes);
|
||||
}
|
||||
// In the most general case, arrayness is potentially coming both from the
|
||||
// declared type and from the variable: "int[] a[];" or just one or the other.
|
||||
// Merge it all to the variableType, so all arrayness is part of the variableType.
|
||||
variableType.transferArraySizes(arraySizes);
|
||||
variableType.copyArrayInnerSizes(declaredType.getArraySizes());
|
||||
|
||||
// samplers accept immediate sampler state
|
||||
if (variableType.getBasicType() == EbtSampler) {
|
||||
@@ -487,8 +479,7 @@ bool HlslGrammar::acceptDeclaration(TIntermNode*& nodeList)
|
||||
else if (variableType.getBasicType() == EbtBlock) {
|
||||
if (expressionNode)
|
||||
parseContext.error(idToken.loc, "buffer aliasing not yet supported", "block initializer", "");
|
||||
parseContext.declareBlock(idToken.loc, variableType, fullName,
|
||||
variableType.isArray() ? &variableType.getArraySizes() : nullptr);
|
||||
parseContext.declareBlock(idToken.loc, variableType, fullName);
|
||||
parseContext.declareStructBufferCounter(idToken.loc, variableType, *fullName);
|
||||
} else {
|
||||
if (variableType.getQualifier().storage == EvqUniform && ! variableType.containsOpaque()) {
|
||||
@@ -1036,7 +1027,7 @@ bool HlslGrammar::acceptTessellationPatchTemplateType(TType& type)
|
||||
|
||||
TArraySizes* arraySizes = new TArraySizes;
|
||||
arraySizes->addInnerSize(size->getAsConstantUnion()->getConstArray()[0].getIConst());
|
||||
type.newArraySizes(*arraySizes);
|
||||
type.transferArraySizes(arraySizes);
|
||||
type.getQualifier().builtIn = patchType;
|
||||
|
||||
if (! acceptTokenClass(EHTokRightAngle)) {
|
||||
@@ -2295,9 +2286,9 @@ bool HlslGrammar::acceptStructBufferType(TType& type)
|
||||
|
||||
// Create an unsized array out of that type.
|
||||
// TODO: does this work if it's already an array type?
|
||||
TArraySizes unsizedArray;
|
||||
unsizedArray.addInnerSize(UnsizedArraySize);
|
||||
templateType->newArraySizes(unsizedArray);
|
||||
TArraySizes* unsizedArray = new TArraySizes;
|
||||
unsizedArray->addInnerSize(UnsizedArraySize);
|
||||
templateType->transferArraySizes(unsizedArray);
|
||||
templateType->getQualifier().storage = storage;
|
||||
|
||||
// field name is canonical for all structbuffers
|
||||
@@ -2395,7 +2386,7 @@ bool HlslGrammar::acceptStructDeclarationList(TTypeList*& typeList, TIntermNode*
|
||||
TArraySizes* arraySizes = nullptr;
|
||||
acceptArraySpecifier(arraySizes);
|
||||
if (arraySizes)
|
||||
typeList->back().type->newArraySizes(*arraySizes);
|
||||
typeList->back().type->transferArraySizes(arraySizes);
|
||||
|
||||
acceptPostDecls(member.type->getQualifier());
|
||||
|
||||
@@ -2583,7 +2574,7 @@ bool HlslGrammar::acceptParameterDeclaration(TFunction& function)
|
||||
return false;
|
||||
}
|
||||
|
||||
type->newArraySizes(*arraySizes);
|
||||
type->transferArraySizes(arraySizes);
|
||||
}
|
||||
|
||||
// post_decls
|
||||
@@ -2954,7 +2945,7 @@ bool HlslGrammar::acceptUnaryExpression(TIntermTyped*& node)
|
||||
TArraySizes* arraySizes = nullptr;
|
||||
acceptArraySpecifier(arraySizes);
|
||||
if (arraySizes != nullptr)
|
||||
castType.newArraySizes(*arraySizes);
|
||||
castType.transferArraySizes(arraySizes);
|
||||
TSourceLoc loc = token.loc;
|
||||
if (acceptTokenClass(EHTokRightParen)) {
|
||||
// We've matched "(type)" now, get the expression to cast
|
||||
|
||||
@@ -1105,7 +1105,7 @@ void HlslParseContext::splitBuiltIn(const TString& baseName, const TType& member
|
||||
TVariable* ioVar = makeInternalVariable(baseName + "." + memberType.getFieldName(), memberType);
|
||||
|
||||
if (arraySizes != nullptr && !memberType.isArray())
|
||||
ioVar->getWritableType().newArraySizes(*arraySizes);
|
||||
ioVar->getWritableType().copyArraySizes(*arraySizes);
|
||||
|
||||
splitBuiltIns[tInterstageIoData(memberType.getQualifier().builtIn, outerQualifier.storage)] = ioVar;
|
||||
if (!isClipOrCullDistance(ioVar->getType()))
|
||||
@@ -1301,7 +1301,7 @@ int HlslParseContext::flattenStruct(const TVariable& variable, const TType& type
|
||||
name + "." + dereferencedType.getFieldName(),
|
||||
linkage, outerQualifier,
|
||||
builtInArraySizes == nullptr && dereferencedType.isArray()
|
||||
? &dereferencedType.getArraySizes()
|
||||
? dereferencedType.getArraySizes()
|
||||
: builtInArraySizes);
|
||||
flattenData.offsets[pos++] = mpos;
|
||||
}
|
||||
@@ -1512,9 +1512,9 @@ void HlslParseContext::fixBuiltInIoType(TType& type)
|
||||
// Alter or set array size as needed.
|
||||
if (requiredArraySize > 0) {
|
||||
if (!type.isArray() || type.getOuterArraySize() != requiredArraySize) {
|
||||
TArraySizes arraySizes;
|
||||
arraySizes.addInnerSize(requiredArraySize);
|
||||
type.newArraySizes(arraySizes);
|
||||
TArraySizes* arraySizes = new TArraySizes;
|
||||
arraySizes->addInnerSize(requiredArraySize);
|
||||
type.transferArraySizes(arraySizes);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2273,9 +2273,9 @@ void HlslParseContext::remapEntryPointIO(TFunction& function, TVariable*& return
|
||||
outputType.shallowCopy(function.getType());
|
||||
|
||||
// vertices has necessarily already been set when handling entry point attributes.
|
||||
TArraySizes arraySizes;
|
||||
arraySizes.addInnerSize(intermediate.getVertices());
|
||||
outputType.newArraySizes(arraySizes);
|
||||
TArraySizes* arraySizes = new TArraySizes;
|
||||
arraySizes->addInnerSize(intermediate.getVertices());
|
||||
outputType.transferArraySizes(arraySizes);
|
||||
|
||||
clearUniformInputOutput(function.getWritableType().getQualifier());
|
||||
returnValue = makeIoVariable("@entryPointOutput", outputType, EvqVaryingOut);
|
||||
@@ -2512,11 +2512,11 @@ TIntermAggregate* HlslParseContext::assignClipCullDistance(const TSourceLoc& loc
|
||||
clipCullType.getQualifier() = clipCullNode->getType().getQualifier();
|
||||
|
||||
// Create required array dimension
|
||||
TArraySizes arraySizes;
|
||||
TArraySizes* arraySizes = new TArraySizes;
|
||||
if (isImplicitlyArrayed)
|
||||
arraySizes.addInnerSize(requiredOuterArraySize);
|
||||
arraySizes.addInnerSize(requiredInnerArraySize);
|
||||
clipCullType.newArraySizes(arraySizes);
|
||||
arraySizes->addInnerSize(requiredOuterArraySize);
|
||||
arraySizes->addInnerSize(requiredInnerArraySize);
|
||||
clipCullType.transferArraySizes(arraySizes);
|
||||
|
||||
// Obtain symbol name: we'll use that for the symbol we introduce.
|
||||
TIntermSymbol* sym = clipCullNode->getAsSymbolNode();
|
||||
@@ -3612,9 +3612,9 @@ TIntermConstantUnion* HlslParseContext::getSamplePosArray(int count)
|
||||
TType retType(EbtFloat, EvqConst, 2);
|
||||
|
||||
if (numSamples != 1) {
|
||||
TArraySizes arraySizes;
|
||||
arraySizes.addInnerSize(numSamples);
|
||||
retType.newArraySizes(arraySizes);
|
||||
TArraySizes* arraySizes = new TArraySizes;
|
||||
arraySizes->addInnerSize(numSamples);
|
||||
retType.transferArraySizes(arraySizes);
|
||||
}
|
||||
|
||||
return new TIntermConstantUnion(*values, retType);
|
||||
@@ -4311,9 +4311,9 @@ void HlslParseContext::decomposeSampleMethods(const TSourceLoc& loc, TIntermType
|
||||
// we construct an array from the separate args.
|
||||
if (hasOffset4) {
|
||||
TType arrayType(EbtInt, EvqTemporary, 2);
|
||||
TArraySizes arraySizes;
|
||||
arraySizes.addInnerSize(4);
|
||||
arrayType.newArraySizes(arraySizes);
|
||||
TArraySizes* arraySizes = new TArraySizes;
|
||||
arraySizes->addInnerSize(4);
|
||||
arrayType.transferArraySizes(arraySizes);
|
||||
|
||||
TIntermAggregate* initList = new TIntermAggregate(EOpNull);
|
||||
|
||||
@@ -6343,11 +6343,11 @@ bool HlslParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node
|
||||
// Types have to match, but we're still making the type.
|
||||
// Finish making the type, and the comparison is done later
|
||||
// when checking for conversion.
|
||||
TArraySizes& arraySizes = type.getArraySizes();
|
||||
TArraySizes& arraySizes = *type.getArraySizes();
|
||||
|
||||
// At least the dimensionalities have to match.
|
||||
if (! function[0].type->isArray() ||
|
||||
arraySizes.getNumDims() != function[0].type->getArraySizes().getNumDims() + 1) {
|
||||
arraySizes.getNumDims() != function[0].type->getArraySizes()->getNumDims() + 1) {
|
||||
error(loc, "array constructor argument not correct type to construct array element", "constructor", "");
|
||||
return true;
|
||||
}
|
||||
@@ -6357,7 +6357,7 @@ bool HlslParseContext::constructorError(const TSourceLoc& loc, TIntermNode* node
|
||||
// That means we need to adopt (from the first argument) the other array sizes into the type.
|
||||
for (int d = 1; d < arraySizes.getNumDims(); ++d) {
|
||||
if (arraySizes.getDimSize(d) == UnsizedArraySize) {
|
||||
arraySizes.setDimSize(d, function[0].type->getArraySizes().getDimSize(d - 1));
|
||||
arraySizes.setDimSize(d, function[0].type->getArraySizes()->getDimSize(d - 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6621,20 +6621,6 @@ void HlslParseContext::structArrayCheck(const TSourceLoc& /*loc*/, const TType&
|
||||
}
|
||||
}
|
||||
|
||||
// Merge array dimensions listed in 'sizes' onto the type's array dimensions.
|
||||
//
|
||||
// From the spec: "vec4[2] a[3]; // size-3 array of size-2 array of vec4"
|
||||
//
|
||||
// That means, the 'sizes' go in front of the 'type' as outermost sizes.
|
||||
// 'type' is the type part of the declaration (to the left)
|
||||
// 'sizes' is the arrayness tagged on the identifier (to the right)
|
||||
//
|
||||
void HlslParseContext::arrayDimMerge(TType& type, const TArraySizes* sizes)
|
||||
{
|
||||
if (sizes)
|
||||
type.addArrayOuterSizes(*sizes);
|
||||
}
|
||||
|
||||
//
|
||||
// Do all the semantic checking for declaring or redeclaring an array, with and
|
||||
// without a size, and make the right changes to the symbol table.
|
||||
@@ -7946,8 +7932,10 @@ TIntermNode* HlslParseContext::executeInitializer(const TSourceLoc& loc, TInterm
|
||||
variable->getType().getArraySizes()->getNumDims()) {
|
||||
// adopt unsized sizes from the initializer's sizes
|
||||
for (int d = 1; d < variable->getType().getArraySizes()->getNumDims(); ++d) {
|
||||
if (variable->getType().getArraySizes()->getDimSize(d) == UnsizedArraySize)
|
||||
variable->getWritableType().getArraySizes().setDimSize(d, initializer->getType().getArraySizes()->getDimSize(d));
|
||||
if (variable->getType().getArraySizes()->getDimSize(d) == UnsizedArraySize) {
|
||||
variable->getWritableType().getArraySizes()->setDimSize(d,
|
||||
initializer->getType().getArraySizes()->getDimSize(d));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8034,7 +8022,7 @@ TIntermTyped* HlslParseContext::convertInitializerList(const TSourceLoc& loc, co
|
||||
// Later on, initializer execution code will deal with array size logic.
|
||||
TType arrayType;
|
||||
arrayType.shallowCopy(type); // sharing struct stuff is fine
|
||||
arrayType.newArraySizes(*type.getArraySizes()); // but get a fresh copy of the array information, to edit below
|
||||
arrayType.copyArraySizes(*type.getArraySizes()); // but get a fresh copy of the array information, to edit below
|
||||
|
||||
// edit array sizes to fill in unsized dimensions
|
||||
if (type.isImplicitlySizedArray())
|
||||
@@ -8044,10 +8032,10 @@ TIntermTyped* HlslParseContext::convertInitializerList(const TSourceLoc& loc, co
|
||||
if (arrayType.isArrayOfArrays() && initList->getSequence().size() > 0) {
|
||||
TIntermTyped* firstInit = initList->getSequence()[0]->getAsTyped();
|
||||
if (firstInit->getType().isArray() &&
|
||||
arrayType.getArraySizes().getNumDims() == firstInit->getType().getArraySizes()->getNumDims() + 1) {
|
||||
for (int d = 1; d < arrayType.getArraySizes().getNumDims(); ++d) {
|
||||
if (arrayType.getArraySizes().getDimSize(d) == UnsizedArraySize)
|
||||
arrayType.getArraySizes().setDimSize(d, firstInit->getType().getArraySizes()->getDimSize(d - 1));
|
||||
arrayType.getArraySizes()->getNumDims() == firstInit->getType().getArraySizes()->getNumDims() + 1) {
|
||||
for (int d = 1; d < arrayType.getArraySizes()->getNumDims(); ++d) {
|
||||
if (arrayType.getArraySizes()->getDimSize(d) == UnsizedArraySize)
|
||||
arrayType.getArraySizes()->setDimSize(d, firstInit->getType().getArraySizes()->getDimSize(d - 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8539,7 +8527,7 @@ TIntermTyped* HlslParseContext::constructAggregate(TIntermNode* node, const TTyp
|
||||
//
|
||||
// Do everything needed to add an interface block.
|
||||
//
|
||||
void HlslParseContext::declareBlock(const TSourceLoc& loc, TType& type, const TString* instanceName, TArraySizes* arraySizes)
|
||||
void HlslParseContext::declareBlock(const TSourceLoc& loc, TType& type, const TString* instanceName)
|
||||
{
|
||||
assert(type.getWritableStruct() != nullptr);
|
||||
|
||||
@@ -8667,8 +8655,8 @@ void HlslParseContext::declareBlock(const TSourceLoc& loc, TType& type, const TS
|
||||
const TString& interfaceName = (instanceName && !instanceName->empty()) ? *instanceName : type.getTypeName();
|
||||
|
||||
TType blockType(&typeList, interfaceName, type.getQualifier());
|
||||
if (arraySizes)
|
||||
blockType.newArraySizes(*arraySizes);
|
||||
if (type.isArray())
|
||||
blockType.transferArraySizes(type.getArraySizes());
|
||||
|
||||
// Add the variable, as anonymous or named instanceName.
|
||||
// Make an anonymous variable if no name was provided.
|
||||
|
||||
@@ -126,7 +126,6 @@ public:
|
||||
void arraySizeCheck(const TSourceLoc&, TIntermTyped* expr, TArraySize&);
|
||||
void arraySizeRequiredCheck(const TSourceLoc&, const TArraySizes&);
|
||||
void structArrayCheck(const TSourceLoc&, const TType& structure);
|
||||
void arrayDimMerge(TType& type, const TArraySizes* sizes);
|
||||
bool voidErrorCheck(const TSourceLoc&, const TString&, TBasicType);
|
||||
void globalQualifierFix(const TSourceLoc&, TQualifier&);
|
||||
bool structQualifierErrorCheck(const TSourceLoc&, const TPublicType& pType);
|
||||
@@ -154,7 +153,7 @@ public:
|
||||
TIntermTyped* convertArray(TIntermTyped*, const TType&);
|
||||
TIntermTyped* constructAggregate(TIntermNode*, const TType&, int, const TSourceLoc&);
|
||||
TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermTyped*, const TSourceLoc&, bool subset);
|
||||
void declareBlock(const TSourceLoc&, TType&, const TString* instanceName = 0, TArraySizes* arraySizes = 0);
|
||||
void declareBlock(const TSourceLoc&, TType&, const TString* instanceName = 0);
|
||||
void declareStructBufferCounter(const TSourceLoc& loc, const TType& bufferType, const TString& name);
|
||||
void fixBlockLocations(const TSourceLoc&, TQualifier&, TTypeList&, bool memberWithLocation, bool memberWithoutLocation);
|
||||
void fixBlockXfbOffsets(TQualifier&, TTypeList&);
|
||||
|
||||
Reference in New Issue
Block a user