HLSL: Rationalize combination of type arrayness and name arrayness.
authorJohn Kessenich <cepheus@frii.com>
Tue, 27 Sep 2016 20:38:57 +0000 (14:38 -0600)
committerJohn Kessenich <cepheus@frii.com>
Thu, 29 Sep 2016 16:25:15 +0000 (10:25 -0600)
glslang/Include/revision.h
hlsl/hlslGrammar.cpp
hlsl/hlslParseHelper.cpp
hlsl/hlslParseHelper.h

index 811e161..7806c77 100644 (file)
@@ -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"
index 48698e5..85c2c69 100755 (executable)
@@ -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;
 }
index 4afbd92..34fd202 100755 (executable)
@@ -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 {
index b7d3323..7b7b95d 100755 (executable)
@@ -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);