From e82061de0838e759403b8eb9a178c6d375934ca6 Mon Sep 17 00:00:00 2001 From: John Kessenich Date: Tue, 27 Sep 2016 14:38:57 -0600 Subject: [PATCH] HLSL: Rationalize combination of type arrayness and name arrayness. --- glslang/Include/revision.h | 4 +-- hlsl/hlslGrammar.cpp | 54 +++++++++++++++++++++++++------------- hlsl/hlslParseHelper.cpp | 28 +++----------------- hlsl/hlslParseHelper.h | 2 +- 4 files changed, 43 insertions(+), 45 deletions(-) diff --git a/glslang/Include/revision.h b/glslang/Include/revision.h index 811e161b..7806c77c 100644 --- a/glslang/Include/revision.h +++ b/glslang/Include/revision.h @@ -2,5 +2,5 @@ // For the version, it uses the latest git tag followed by the number of commits. // For the date, it uses the current date (when then script is run). -#define GLSLANG_REVISION "Overload400-PrecQual.1507" -#define GLSLANG_DATE "25-Sep-2016" +#define GLSLANG_REVISION "Overload400-PrecQual.1523" +#define GLSLANG_DATE "27-Sep-2016" diff --git a/hlsl/hlslGrammar.cpp b/hlsl/hlslGrammar.cpp index 48698e5a..85c2c697 100755 --- a/hlsl/hlslGrammar.cpp +++ b/hlsl/hlslGrammar.cpp @@ -271,7 +271,7 @@ bool HlslGrammar::acceptDeclaration(TIntermNode*& node) // typedef bool typedefDecl = acceptTokenClass(EHTokTypedef); - TType type; + TType declaredType; // DX9 sampler declaration use a different syntax // DX9 shaders need to run through HLSL compiler (fxc) via a back compat mode, it isn't going to @@ -280,21 +280,21 @@ bool HlslGrammar::acceptDeclaration(TIntermNode*& node) // As such, the sampler keyword in D3D10+ turns into an automatic sampler type, and is commonly used // For that reason, this line is commented out - // if (acceptSamplerDeclarationDX9(type)) + // if (acceptSamplerDeclarationDX9(declaredType)) // return true; // fully_specified_type - if (! acceptFullySpecifiedType(type)) + if (! acceptFullySpecifiedType(declaredType)) return false; - if (type.getQualifier().storage == EvqTemporary && parseContext.symbolTable.atGlobalLevel()) { - if (type.getBasicType() == EbtSampler) { + if (declaredType.getQualifier().storage == EvqTemporary && parseContext.symbolTable.atGlobalLevel()) { + if (declaredType.getBasicType() == EbtSampler) { // Sampler/textures are uniform by default (if no explicit qualifier is present) in // HLSL. This line silently converts samplers *explicitly* declared static to uniform, // which is incorrect but harmless. - type.getQualifier().storage = EvqUniform; + declaredType.getQualifier().storage = EvqUniform; } else { - type.getQualifier().storage = EvqGlobal; + declaredType.getQualifier().storage = EvqGlobal; } } @@ -302,7 +302,7 @@ bool HlslGrammar::acceptDeclaration(TIntermNode*& node) HlslToken idToken; while (acceptIdentifier(idToken)) { // function_parameters - TFunction& function = *new TFunction(idToken.string, type); + TFunction& function = *new TFunction(idToken.string, declaredType); if (acceptFunctionParameters(function)) { // post_decls acceptPostDecls(function.getWritableType().getQualifier()); @@ -320,20 +320,38 @@ bool HlslGrammar::acceptDeclaration(TIntermNode*& node) parseContext.handleFunctionDeclarator(idToken.loc, function, true); } } else { - // a variable declaration + // A variable declaration. + // We can handle multiple variables per type declaration, so + // the number of types can expand when arrayness is different. + TType variableType; + variableType.shallowCopy(declaredType); - // array_specifier + // 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); + } + // samplers accept immediate sampler state - if (type.getBasicType() == EbtSampler) { + if (variableType.getBasicType() == EbtSampler) { if (! acceptSamplerState()) return false; } // post_decls - acceptPostDecls(type.getQualifier()); + acceptPostDecls(variableType.getQualifier()); // EQUAL assignment_expression TIntermTyped* expressionNode = nullptr; @@ -347,16 +365,16 @@ bool HlslGrammar::acceptDeclaration(TIntermNode*& node) } if (typedefDecl) - parseContext.declareTypedef(idToken.loc, *idToken.string, type, arraySizes); - else if (type.getBasicType() == EbtBlock) - parseContext.declareBlock(idToken.loc, type, idToken.string); + parseContext.declareTypedef(idToken.loc, *idToken.string, variableType, arraySizes); + else if (variableType.getBasicType() == EbtBlock) + parseContext.declareBlock(idToken.loc, variableType, idToken.string); else { // Declare the variable and add any initializer code to the AST. // The top-level node is always made into an aggregate, as that's // historically how the AST has been. node = intermediate.growAggregate(node, - parseContext.declareVariable(idToken.loc, *idToken.string, type, - arraySizes, expressionNode), + parseContext.declareVariable(idToken.loc, *idToken.string, variableType, + expressionNode), idToken.loc); } } @@ -412,7 +430,7 @@ bool HlslGrammar::acceptControlDeclaration(TIntermNode*& node) return false; } - node = parseContext.declareVariable(idToken.loc, *idToken.string, type, 0, expressionNode); + node = parseContext.declareVariable(idToken.loc, *idToken.string, type, expressionNode); return true; } diff --git a/hlsl/hlslParseHelper.cpp b/hlsl/hlslParseHelper.cpp index 4afbd924..34fd2025 100755 --- a/hlsl/hlslParseHelper.cpp +++ b/hlsl/hlslParseHelper.cpp @@ -4160,11 +4160,6 @@ void HlslParseContext::declareTypedef(const TSourceLoc& loc, TString& identifier TType type; type.deepCopy(parseType); - // Arrayness is potentially coming both from the type and from the - // variable: "int[] a[];" or just one or the other. - // Merge it all to the type, so all arrayness is part of the type. - arrayDimMerge(type, arraySizes); - TVariable* typeSymbol = new TVariable(&identifier, type, true); if (! symbolTable.insert(*typeSymbol)) error(loc, "name already defined", "typedef", identifier.c_str()); @@ -4181,7 +4176,7 @@ void HlslParseContext::declareTypedef(const TSourceLoc& loc, TString& identifier // 'parseType' is the type part of the declaration (to the left) // 'arraySizes' is the arrayness tagged on the identifier (to the right) // -TIntermNode* HlslParseContext::declareVariable(const TSourceLoc& loc, TString& identifier, const TType& parseType, TArraySizes* arraySizes, TIntermTyped* initializer) +TIntermNode* HlslParseContext::declareVariable(const TSourceLoc& loc, TString& identifier, TType& type, TIntermTyped* initializer) { // TODO: things scoped within an annotation need their own name space; // haven't done that yet @@ -4189,18 +4184,9 @@ TIntermNode* HlslParseContext::declareVariable(const TSourceLoc& loc, TString& i return nullptr; // TODO: strings are not yet handled - if (parseType.getBasicType() == EbtString) + if (type.getBasicType() == EbtString) return nullptr; - TType type; - type.shallowCopy(parseType); - if (type.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. - type.newArraySizes(*parseType.getArraySizes()); - } - if (voidErrorCheck(loc, identifier, type.getBasicType())) return nullptr; @@ -4213,16 +4199,10 @@ TIntermNode* HlslParseContext::declareVariable(const TSourceLoc& loc, TString& i bool flattenVar = false; // Declare the variable - if (arraySizes || type.isArray()) { - // Arrayness is potentially coming both from the type and from the - // variable: "int[] a[];" or just one or the other. - // Merge it all to the type, so all arrayness is part of the type. - arrayDimMerge(type, arraySizes); // Safe if there are no arraySizes - + if (type.isArray()) { + // array case declareArray(loc, identifier, type, symbol, newDeclaration); - flattenVar = shouldFlatten(type); - if (flattenVar) flatten(loc, *symbol->getAsVariable()); } else { diff --git a/hlsl/hlslParseHelper.h b/hlsl/hlslParseHelper.h index b7d33237..7b7b95dc 100755 --- a/hlsl/hlslParseHelper.h +++ b/hlsl/hlslParseHelper.h @@ -140,7 +140,7 @@ public: const TFunction* findFunction(const TSourceLoc& loc, const TFunction& call, bool& builtIn); void declareTypedef(const TSourceLoc&, TString& identifier, const TType&, TArraySizes* typeArray = 0); - TIntermNode* declareVariable(const TSourceLoc&, TString& identifier, const TType&, TArraySizes* typeArray = 0, TIntermTyped* initializer = 0); + TIntermNode* declareVariable(const TSourceLoc&, TString& identifier, TType&, TIntermTyped* initializer = 0); TIntermTyped* addConstructor(const TSourceLoc&, TIntermNode*, const TType&); TIntermTyped* constructAggregate(TIntermNode*, const TType&, int, const TSourceLoc&); TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermTyped*, const TSourceLoc&, bool subset);