Implement ES 2.0 (version 100) limitations for non-inductive loop detection and array...
authorJohn Kessenich <cepheus@frii.com>
Mon, 14 Oct 2013 22:42:16 +0000 (22:42 +0000)
committerJohn Kessenich <cepheus@frii.com>
Mon, 14 Oct 2013 22:42:16 +0000 (22:42 +0000)
git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@23478 e7fa87d3-cd2b-0410-9028-fcbf551c1848

15 files changed:
Test/100Limits.vert
Test/baseResults/100Limits.vert.out
Test/baseResults/100LimitsConf.vert.out
glslang.vcxproj
glslang.vcxproj.filters
glslang/Include/intermediate.h
glslang/MachineIndependent/Constant.cpp
glslang/MachineIndependent/Intermediate.cpp
glslang/MachineIndependent/Makefile
glslang/MachineIndependent/ParseHelper.cpp
glslang/MachineIndependent/ParseHelper.h
glslang/MachineIndependent/glslang.y
glslang/MachineIndependent/limits.cpp [new file with mode: 0644]
glslang/MachineIndependent/localintermediate.h
glslang/MachineIndependent/parseConst.cpp

index 7ed1ef8..d23b7e8 100644 (file)
@@ -14,32 +14,46 @@ const vec3 v3 = vec3(2.0);
 \r
 void foo(inout float a) {}\r
 \r
+int bar()\r
+{\r
+    return 1;\r
+}\r
+\r
 void main()\r
 {\r
     while (ga < gb) { }\r
 \r
     do { } while (false);\r
-    \r
-    for (     ga = 0;              ;         );\r
-    for ( bool a = false;          ;         );\r
-    for (float a = 0.0; a == sin(f);         );\r
-    for (  int a = 0;       a  < 10;   a *= 2);\r
-    for (  int a = 0;       a <= 20;      ++a)  --a;\r
+\r
+    for (           ;              ;         );           // ERROR\r
+    for (           ;        ga==gb;         );           // ERROR\r
+    for (           ;              ;      f++);           // ERROR\r
+    for (     ga = 0;              ;         );           // ERROR\r
+    for ( bool a = false;          ;         );           // ERROR\r
+    for (float a = 0.0; a == sin(f);         );           // ERROR\r
+    for (  int a = 0;       a  < 10;   a *= 2);           // ERROR\r
+    for (  int a = 0;       a <= 20;      a++)  --a;      // ERROR\r
+    for (  int a = 0;       a <= 20;      a++)  { if (ga==0) a = 4; } // ERROR\r
     for (float a = 0.0;   a <= 20.0; a += 2.0);\r
-    for (float a = 0.0;   a <= 20.0; a += 2.0) foo(a);\r
+    for (float a = 0.0;   a != 20.0; a -= 2.0)  { if (ga==0) ga = 4; }\r
+    for (float a = 0.0;   a == 20.0;      a--) for (float a = 0.0;   a == 20.0;      a--);  // two different 'a's, everything okay\r
+    for (float a = 0.0;   a <= 20.0; a += 2.0);\r
+    for (float a = 0.0;   a <= 20.0; a += 2.0);\r
+    for (float a = 0.0;   a > 2.0 * 20.0; a += v3.y);\r
+    for (float a = 0.0;   a >= 20.0; a += 2.0) foo(a);    // ERROR\r
 \r
     int ia[9];\r
 \r
-    fsa[ga];\r
+    fsa[ga];  // ERROR\r
     fua[ga];\r
-    am3[ga];\r
-    av2[ga];\r
-    va[ga];\r
-    m2[ga];\r
-    v3[ga];\r
-    ia[ga];\r
-\r
-    for (  int a = 3; a >= 0; --a) {\r
+    am3[ga];  // ERROR\r
+    av2[ga];  // ERROR\r
+    va[2+ga]; // ERROR\r
+    m2[ga];   // ERROR\r
+    v3[ga/2]; // ERROR\r
+    ia[ga];   // ERROR\r
+\r
+    for (int a = 3; a >= 0; a--) {\r
         fsa[a];\r
         fua[a+2];\r
         am3[3*a];\r
@@ -48,6 +62,15 @@ void main()
         m2[a/2];\r
         v3[a];\r
         ia[a];\r
+        ia[bar()];  // ERROR\r
     }\r
 \r
+    fsa[2];\r
+    fua[3];\r
+    am3[2];\r
+    av2[1];\r
+    va[1];\r
+    m2[1];\r
+    v3[1];\r
+    ia[3];\r
 }\r
index fe68fd5..4ee83d1 100644 (file)
 0:15  Function Definition: foo(f1; (void)\r
 0:15    Function Parameters: \r
 0:15      'a' (inout highp float)\r
-0:17  Function Definition: main( (void)\r
+0:17  Function Definition: bar( (highp int)\r
 0:17    Function Parameters: \r
 0:19    Sequence\r
-0:19      Loop with condition tested first\r
-0:19        Loop Condition\r
-0:19        Compare Less Than (bool)\r
-0:19          'ga' (highp int)\r
-0:19          'gb' (highp int)\r
-0:19        No loop body\r
-0:21      Loop with condition not tested first\r
-0:21        Loop Condition\r
-0:21        Constant:\r
-0:21          false (const bool)\r
-0:21        No loop body\r
-0:23      Sequence\r
-0:23        move second child to first child (highp int)\r
-0:23          'ga' (highp int)\r
-0:23          Constant:\r
-0:23            0 (const int)\r
-0:23        Loop with condition tested first\r
-0:23          No loop condition\r
-0:23          No loop body\r
-0:24      Sequence\r
-0:24        Sequence\r
-0:24          move second child to first child (bool)\r
-0:24            'a' (bool)\r
-0:24            Constant:\r
-0:24              false (const bool)\r
-0:24        Loop with condition tested first\r
-0:24          No loop condition\r
-0:24          No loop body\r
-0:25      Sequence\r
-0:25        Sequence\r
-0:25          move second child to first child (highp float)\r
-0:25            'a' (highp float)\r
-0:25            Constant:\r
-0:25              0.000000\r
-0:25        Loop with condition tested first\r
-0:25          Loop Condition\r
-0:25          Compare Equal (bool)\r
-0:25            'a' (highp float)\r
-0:25            sine (highp float)\r
-0:25              'f' (highp float)\r
-0:25          No loop body\r
-0:26      Sequence\r
-0:26        Sequence\r
-0:26          move second child to first child (highp int)\r
-0:26            'a' (highp int)\r
-0:26            Constant:\r
-0:26              0 (const int)\r
-0:26        Loop with condition tested first\r
-0:26          Loop Condition\r
-0:26          Compare Less Than (bool)\r
-0:26            'a' (highp int)\r
-0:26            Constant:\r
-0:26              10 (const int)\r
-0:26          No loop body\r
-0:26          Loop Terminal Expression\r
-0:26          multiply second child into first child (highp int)\r
-0:26            'a' (highp int)\r
-0:26            Constant:\r
-0:26              2 (const int)\r
-0:27      Sequence\r
-0:27        Sequence\r
-0:27          move second child to first child (highp int)\r
-0:27            'a' (highp int)\r
-0:27            Constant:\r
-0:27              0 (const int)\r
-0:27        Loop with condition tested first\r
-0:27          Loop Condition\r
-0:27          Compare Less Than or Equal (bool)\r
-0:27            'a' (highp int)\r
-0:27            Constant:\r
-0:27              20 (const int)\r
-0:27          Loop Body\r
-0:27          Pre-Decrement (highp int)\r
-0:27            'a' (highp int)\r
-0:27          Loop Terminal Expression\r
-0:27          Pre-Increment (highp int)\r
-0:27            'a' (highp int)\r
+0:19      Branch: Return with expression\r
+0:19        Constant:\r
+0:19          1 (const int)\r
+0:22  Function Definition: main( (void)\r
+0:22    Function Parameters: \r
+0:24    Sequence\r
+0:24      Loop with condition tested first\r
+0:24        Loop Condition\r
+0:24        Compare Less Than (bool)\r
+0:24          'ga' (highp int)\r
+0:24          'gb' (highp int)\r
+0:24        No loop body\r
+0:26      Loop with condition not tested first\r
+0:26        Loop Condition\r
+0:26        Constant:\r
+0:26          false (const bool)\r
+0:26        No loop body\r
 0:28      Sequence\r
-0:28        Sequence\r
-0:28          move second child to first child (highp float)\r
-0:28            'a' (highp float)\r
-0:28            Constant:\r
-0:28              0.000000\r
 0:28        Loop with condition tested first\r
-0:28          Loop Condition\r
-0:28          Compare Less Than or Equal (bool)\r
-0:28            'a' (highp float)\r
-0:28            Constant:\r
-0:28              20.000000\r
+0:28          No loop condition\r
 0:28          No loop body\r
-0:28          Loop Terminal Expression\r
-0:28          add second child into first child (highp float)\r
-0:28            'a' (highp float)\r
-0:28            Constant:\r
-0:28              2.000000\r
 0:29      Sequence\r
-0:29        Sequence\r
-0:29          move second child to first child (highp float)\r
-0:29            'a' (highp float)\r
-0:29            Constant:\r
-0:29              0.000000\r
 0:29        Loop with condition tested first\r
 0:29          Loop Condition\r
-0:29          Compare Less Than or Equal (bool)\r
-0:29            'a' (highp float)\r
-0:29            Constant:\r
-0:29              20.000000\r
-0:29          Loop Body\r
-0:29          Function Call: foo(f1; (void)\r
-0:29            'a' (highp float)\r
-0:29          Loop Terminal Expression\r
-0:29          add second child into first child (highp float)\r
-0:29            'a' (highp float)\r
-0:29            Constant:\r
-0:29              2.000000\r
-0:33      indirect index (uniform lowp sampler2D)\r
-0:33        'fsa' (uniform 3-element array of lowp sampler2D)\r
-0:33        'ga' (highp int)\r
-0:34      indirect index (uniform highp float)\r
-0:34        'fua' (uniform 10-element array of highp float)\r
-0:34        'ga' (highp int)\r
-0:35      indirect index (in highp 3-component vector of float)\r
-0:35        'am3' (in highp 3X3 matrix of float)\r
-0:35        'ga' (highp int)\r
-0:36      indirect index (in highp float)\r
-0:36        'av2' (in highp 2-component vector of float)\r
-0:36        'ga' (highp int)\r
-0:37      indirect index (smooth out highp 4-component vector of float)\r
-0:37        'va' (smooth out 4-element array of highp 4-component vector of float)\r
-0:37        'ga' (highp int)\r
-0:38      indirect index (const highp 2-component vector of float)\r
-0:38        Constant:\r
-0:38          1.000000\r
-0:38          0.000000\r
-0:38          0.000000\r
-0:38          1.000000\r
-0:38        'ga' (highp int)\r
-0:39      indirect index (const highp float)\r
-0:39        Constant:\r
-0:39          2.000000\r
-0:39          2.000000\r
-0:39          2.000000\r
-0:39        'ga' (highp int)\r
-0:40      indirect index (highp int)\r
-0:40        'ia' (9-element array of highp int)\r
-0:40        'ga' (highp int)\r
+0:29          Compare Equal (bool)\r
+0:29            'ga' (highp int)\r
+0:29            'gb' (highp int)\r
+0:29          No loop body\r
+0:30      Sequence\r
+0:30        Loop with condition tested first\r
+0:30          No loop condition\r
+0:30          No loop body\r
+0:30          Loop Terminal Expression\r
+0:30          Post-Increment (highp float)\r
+0:30            'f' (highp float)\r
+0:31      Sequence\r
+0:31        move second child to first child (highp int)\r
+0:31          'ga' (highp int)\r
+0:31          Constant:\r
+0:31            0 (const int)\r
+0:31        Loop with condition tested first\r
+0:31          No loop condition\r
+0:31          No loop body\r
+0:32      Sequence\r
+0:32        Sequence\r
+0:32          move second child to first child (bool)\r
+0:32            'a' (bool)\r
+0:32            Constant:\r
+0:32              false (const bool)\r
+0:32        Loop with condition tested first\r
+0:32          No loop condition\r
+0:32          No loop body\r
+0:33      Sequence\r
+0:33        Sequence\r
+0:33          move second child to first child (highp float)\r
+0:33            'a' (highp float)\r
+0:33            Constant:\r
+0:33              0.000000\r
+0:33        Loop with condition tested first\r
+0:33          Loop Condition\r
+0:33          Compare Equal (bool)\r
+0:33            'a' (highp float)\r
+0:33            sine (highp float)\r
+0:33              'f' (highp float)\r
+0:33          No loop body\r
+0:34      Sequence\r
+0:34        Sequence\r
+0:34          move second child to first child (highp int)\r
+0:34            'a' (highp int)\r
+0:34            Constant:\r
+0:34              0 (const int)\r
+0:34        Loop with condition tested first\r
+0:34          Loop Condition\r
+0:34          Compare Less Than (bool)\r
+0:34            'a' (highp int)\r
+0:34            Constant:\r
+0:34              10 (const int)\r
+0:34          No loop body\r
+0:34          Loop Terminal Expression\r
+0:34          multiply second child into first child (highp int)\r
+0:34            'a' (highp int)\r
+0:34            Constant:\r
+0:34              2 (const int)\r
+0:35      Sequence\r
+0:35        Sequence\r
+0:35          move second child to first child (highp int)\r
+0:35            'a' (highp int)\r
+0:35            Constant:\r
+0:35              0 (const int)\r
+0:35        Loop with condition tested first\r
+0:35          Loop Condition\r
+0:35          Compare Less Than or Equal (bool)\r
+0:35            'a' (highp int)\r
+0:35            Constant:\r
+0:35              20 (const int)\r
+0:35          Loop Body\r
+0:35          Pre-Decrement (highp int)\r
+0:35            'a' (highp int)\r
+0:35          Loop Terminal Expression\r
+0:35          Post-Increment (highp int)\r
+0:35            'a' (highp int)\r
+0:36      Sequence\r
+0:36        Sequence\r
+0:36          move second child to first child (highp int)\r
+0:36            'a' (highp int)\r
+0:36            Constant:\r
+0:36              0 (const int)\r
+0:36        Loop with condition tested first\r
+0:36          Loop Condition\r
+0:36          Compare Less Than or Equal (bool)\r
+0:36            'a' (highp int)\r
+0:36            Constant:\r
+0:36              20 (const int)\r
+0:36          Loop Body\r
+0:36          Sequence\r
+0:36            Test condition and select (void)\r
+0:36              Condition\r
+0:36              Compare Equal (bool)\r
+0:36                'ga' (highp int)\r
+0:36                Constant:\r
+0:36                  0 (const int)\r
+0:36              true case\r
+0:36              move second child to first child (highp int)\r
+0:36                'a' (highp int)\r
+0:36                Constant:\r
+0:36                  4 (const int)\r
+0:36          Loop Terminal Expression\r
+0:36          Post-Increment (highp int)\r
+0:36            'a' (highp int)\r
+0:37      Sequence\r
+0:37        Sequence\r
+0:37          move second child to first child (highp float)\r
+0:37            'a' (highp float)\r
+0:37            Constant:\r
+0:37              0.000000\r
+0:37        Loop with condition tested first\r
+0:37          Loop Condition\r
+0:37          Compare Less Than or Equal (bool)\r
+0:37            'a' (highp float)\r
+0:37            Constant:\r
+0:37              20.000000\r
+0:37          No loop body\r
+0:37          Loop Terminal Expression\r
+0:37          add second child into first child (highp float)\r
+0:37            'a' (highp float)\r
+0:37            Constant:\r
+0:37              2.000000\r
+0:38      Sequence\r
+0:38        Sequence\r
+0:38          move second child to first child (highp float)\r
+0:38            'a' (highp float)\r
+0:38            Constant:\r
+0:38              0.000000\r
+0:38        Loop with condition tested first\r
+0:38          Loop Condition\r
+0:38          Compare Not Equal (bool)\r
+0:38            'a' (highp float)\r
+0:38            Constant:\r
+0:38              20.000000\r
+0:38          Loop Body\r
+0:38          Sequence\r
+0:38            Test condition and select (void)\r
+0:38              Condition\r
+0:38              Compare Equal (bool)\r
+0:38                'ga' (highp int)\r
+0:38                Constant:\r
+0:38                  0 (const int)\r
+0:38              true case\r
+0:38              move second child to first child (highp int)\r
+0:38                'ga' (highp int)\r
+0:38                Constant:\r
+0:38                  4 (const int)\r
+0:38          Loop Terminal Expression\r
+0:38          subtract second child into first child (highp float)\r
+0:38            'a' (highp float)\r
+0:38            Constant:\r
+0:38              2.000000\r
+0:39      Sequence\r
+0:39        Sequence\r
+0:39          move second child to first child (highp float)\r
+0:39            'a' (highp float)\r
+0:39            Constant:\r
+0:39              0.000000\r
+0:39        Loop with condition tested first\r
+0:39          Loop Condition\r
+0:39          Compare Equal (bool)\r
+0:39            'a' (highp float)\r
+0:39            Constant:\r
+0:39              20.000000\r
+0:39          Loop Body\r
+0:39          Sequence\r
+0:39            Sequence\r
+0:39              move second child to first child (highp float)\r
+0:39                'a' (highp float)\r
+0:39                Constant:\r
+0:39                  0.000000\r
+0:39            Loop with condition tested first\r
+0:39              Loop Condition\r
+0:39              Compare Equal (bool)\r
+0:39                'a' (highp float)\r
+0:39                Constant:\r
+0:39                  20.000000\r
+0:39              No loop body\r
+0:39              Loop Terminal Expression\r
+0:39              Post-Decrement (highp float)\r
+0:39                'a' (highp float)\r
+0:39          Loop Terminal Expression\r
+0:39          Post-Decrement (highp float)\r
+0:39            'a' (highp float)\r
+0:40      Sequence\r
+0:40        Sequence\r
+0:40          move second child to first child (highp float)\r
+0:40            'a' (highp float)\r
+0:40            Constant:\r
+0:40              0.000000\r
+0:40        Loop with condition tested first\r
+0:40          Loop Condition\r
+0:40          Compare Less Than or Equal (bool)\r
+0:40            'a' (highp float)\r
+0:40            Constant:\r
+0:40              20.000000\r
+0:40          No loop body\r
+0:40          Loop Terminal Expression\r
+0:40          add second child into first child (highp float)\r
+0:40            'a' (highp float)\r
+0:40            Constant:\r
+0:40              2.000000\r
+0:41      Sequence\r
+0:41        Sequence\r
+0:41          move second child to first child (highp float)\r
+0:41            'a' (highp float)\r
+0:41            Constant:\r
+0:41              0.000000\r
+0:41        Loop with condition tested first\r
+0:41          Loop Condition\r
+0:41          Compare Less Than or Equal (bool)\r
+0:41            'a' (highp float)\r
+0:41            Constant:\r
+0:41              20.000000\r
+0:41          No loop body\r
+0:41          Loop Terminal Expression\r
+0:41          add second child into first child (highp float)\r
+0:41            'a' (highp float)\r
+0:41            Constant:\r
+0:41              2.000000\r
 0:42      Sequence\r
 0:42        Sequence\r
-0:42          move second child to first child (highp int)\r
-0:42            'a' (highp int)\r
+0:42          move second child to first child (highp float)\r
+0:42            'a' (highp float)\r
 0:42            Constant:\r
-0:42              3 (const int)\r
+0:42              0.000000\r
 0:42        Loop with condition tested first\r
 0:42          Loop Condition\r
-0:42          Compare Greater Than or Equal (bool)\r
-0:42            'a' (highp int)\r
+0:42          Compare Greater Than (bool)\r
+0:42            'a' (highp float)\r
 0:42            Constant:\r
-0:42              0 (const int)\r
-0:42          Loop Body\r
-0:43          Sequence\r
-0:43            indirect index (uniform lowp sampler2D)\r
-0:43              'fsa' (uniform 3-element array of lowp sampler2D)\r
-0:43              'a' (highp int)\r
-0:44            indirect index (uniform highp float)\r
-0:44              'fua' (uniform 10-element array of highp float)\r
-0:44              add (highp int)\r
-0:44                'a' (highp int)\r
-0:44                Constant:\r
-0:44                  2 (const int)\r
-0:45            indirect index (in highp 3-component vector of float)\r
-0:45              'am3' (in highp 3X3 matrix of float)\r
-0:45              component-wise multiply (highp int)\r
-0:45                Constant:\r
-0:45                  3 (const int)\r
-0:45                'a' (highp int)\r
-0:46            indirect index (in highp float)\r
-0:46              'av2' (in highp 2-component vector of float)\r
-0:46              component-wise multiply (highp int)\r
-0:46                Constant:\r
-0:46                  3 (const int)\r
-0:46                'a' (highp int)\r
-0:47            indirect index (smooth out highp 4-component vector of float)\r
-0:47              'va' (smooth out 4-element array of highp 4-component vector of float)\r
-0:47              subtract (highp int)\r
-0:47                'a' (highp int)\r
-0:47                Constant:\r
-0:47                  1 (const int)\r
-0:48            indirect index (const highp 2-component vector of float)\r
-0:48              Constant:\r
-0:48                1.000000\r
-0:48                0.000000\r
-0:48                0.000000\r
-0:48                1.000000\r
-0:48              divide (highp int)\r
-0:48                'a' (highp int)\r
-0:48                Constant:\r
-0:48                  2 (const int)\r
-0:49            indirect index (const highp float)\r
-0:49              Constant:\r
-0:49                2.000000\r
-0:49                2.000000\r
-0:49                2.000000\r
-0:49              'a' (highp int)\r
-0:50            indirect index (highp int)\r
-0:50              'ia' (9-element array of highp int)\r
-0:50              'a' (highp int)\r
+0:42              40.000000\r
+0:42          No loop body\r
 0:42          Loop Terminal Expression\r
-0:42          Pre-Decrement (highp int)\r
-0:42            'a' (highp int)\r
+0:42          add second child into first child (highp float)\r
+0:42            'a' (highp float)\r
+0:42            Constant:\r
+0:42              2.000000\r
+0:43      Sequence\r
+0:43        Sequence\r
+0:43          move second child to first child (highp float)\r
+0:43            'a' (highp float)\r
+0:43            Constant:\r
+0:43              0.000000\r
+0:43        Loop with condition tested first\r
+0:43          Loop Condition\r
+0:43          Compare Greater Than or Equal (bool)\r
+0:43            'a' (highp float)\r
+0:43            Constant:\r
+0:43              20.000000\r
+0:43          Loop Body\r
+0:43          Function Call: foo(f1; (void)\r
+0:43            'a' (highp float)\r
+0:43          Loop Terminal Expression\r
+0:43          add second child into first child (highp float)\r
+0:43            'a' (highp float)\r
+0:43            Constant:\r
+0:43              2.000000\r
+0:47      indirect index (uniform lowp sampler2D)\r
+0:47        'fsa' (uniform 3-element array of lowp sampler2D)\r
+0:47        'ga' (highp int)\r
+0:48      indirect index (uniform highp float)\r
+0:48        'fua' (uniform 10-element array of highp float)\r
+0:48        'ga' (highp int)\r
+0:49      indirect index (in highp 3-component vector of float)\r
+0:49        'am3' (in highp 3X3 matrix of float)\r
+0:49        'ga' (highp int)\r
+0:50      indirect index (in highp float)\r
+0:50        'av2' (in highp 2-component vector of float)\r
+0:50        'ga' (highp int)\r
+0:51      indirect index (smooth out highp 4-component vector of float)\r
+0:51        'va' (smooth out 4-element array of highp 4-component vector of float)\r
+0:51        add (highp int)\r
+0:51          Constant:\r
+0:51            2 (const int)\r
+0:51          'ga' (highp int)\r
+0:52      indirect index (const highp 2-component vector of float)\r
+0:52        Constant:\r
+0:52          1.000000\r
+0:52          0.000000\r
+0:52          0.000000\r
+0:52          1.000000\r
+0:52        'ga' (highp int)\r
+0:53      indirect index (const highp float)\r
+0:53        Constant:\r
+0:53          2.000000\r
+0:53          2.000000\r
+0:53          2.000000\r
+0:53        divide (highp int)\r
+0:53          'ga' (highp int)\r
+0:53          Constant:\r
+0:53            2 (const int)\r
+0:54      indirect index (highp int)\r
+0:54        'ia' (9-element array of highp int)\r
+0:54        'ga' (highp int)\r
+0:56      Sequence\r
+0:56        Sequence\r
+0:56          move second child to first child (highp int)\r
+0:56            'a' (highp int)\r
+0:56            Constant:\r
+0:56              3 (const int)\r
+0:56        Loop with condition tested first\r
+0:56          Loop Condition\r
+0:56          Compare Greater Than or Equal (bool)\r
+0:56            'a' (highp int)\r
+0:56            Constant:\r
+0:56              0 (const int)\r
+0:56          Loop Body\r
+0:57          Sequence\r
+0:57            indirect index (uniform lowp sampler2D)\r
+0:57              'fsa' (uniform 3-element array of lowp sampler2D)\r
+0:57              'a' (highp int)\r
+0:58            indirect index (uniform highp float)\r
+0:58              'fua' (uniform 10-element array of highp float)\r
+0:58              add (highp int)\r
+0:58                'a' (highp int)\r
+0:58                Constant:\r
+0:58                  2 (const int)\r
+0:59            indirect index (in highp 3-component vector of float)\r
+0:59              'am3' (in highp 3X3 matrix of float)\r
+0:59              component-wise multiply (highp int)\r
+0:59                Constant:\r
+0:59                  3 (const int)\r
+0:59                'a' (highp int)\r
+0:60            indirect index (in highp float)\r
+0:60              'av2' (in highp 2-component vector of float)\r
+0:60              component-wise multiply (highp int)\r
+0:60                Constant:\r
+0:60                  3 (const int)\r
+0:60                'a' (highp int)\r
+0:61            indirect index (smooth out highp 4-component vector of float)\r
+0:61              'va' (smooth out 4-element array of highp 4-component vector of float)\r
+0:61              subtract (highp int)\r
+0:61                'a' (highp int)\r
+0:61                Constant:\r
+0:61                  1 (const int)\r
+0:62            indirect index (const highp 2-component vector of float)\r
+0:62              Constant:\r
+0:62                1.000000\r
+0:62                0.000000\r
+0:62                0.000000\r
+0:62                1.000000\r
+0:62              divide (highp int)\r
+0:62                'a' (highp int)\r
+0:62                Constant:\r
+0:62                  2 (const int)\r
+0:63            indirect index (const highp float)\r
+0:63              Constant:\r
+0:63                2.000000\r
+0:63                2.000000\r
+0:63                2.000000\r
+0:63              'a' (highp int)\r
+0:64            indirect index (highp int)\r
+0:64              'ia' (9-element array of highp int)\r
+0:64              'a' (highp int)\r
+0:65            indirect index (highp int)\r
+0:65              'ia' (9-element array of highp int)\r
+0:65              Function Call: bar( (highp int)\r
+0:56          Loop Terminal Expression\r
+0:56          Post-Decrement (highp int)\r
+0:56            'a' (highp int)\r
+0:68      direct index (uniform lowp sampler2D)\r
+0:68        'fsa' (uniform 3-element array of lowp sampler2D)\r
+0:68        Constant:\r
+0:68          2 (const int)\r
+0:69      direct index (uniform highp float)\r
+0:69        'fua' (uniform 10-element array of highp float)\r
+0:69        Constant:\r
+0:69          3 (const int)\r
+0:70      direct index (in highp 3-component vector of float)\r
+0:70        'am3' (in highp 3X3 matrix of float)\r
+0:70        Constant:\r
+0:70          2 (const int)\r
+0:71      direct index (in highp float)\r
+0:71        'av2' (in highp 2-component vector of float)\r
+0:71        Constant:\r
+0:71          1 (const int)\r
+0:72      direct index (smooth out highp 4-component vector of float)\r
+0:72        'va' (smooth out 4-element array of highp 4-component vector of float)\r
+0:72        Constant:\r
+0:72          1 (const int)\r
+0:73      Constant:\r
+0:73        0.000000\r
+0:73        1.000000\r
+0:74      Constant:\r
+0:74        2.000000\r
+0:75      direct index (highp int)\r
+0:75        'ia' (9-element array of highp int)\r
+0:75        Constant:\r
+0:75          3 (const int)\r
 0:?   Linker Objects\r
 0:?     'ga' (highp int)\r
 0:?     'gb' (highp int)\r
index 0d51c81..1a87ea8 100644 (file)
@@ -1,5 +1,23 @@
-ERROR: 0:19: 'limitation' : while loops not available \r
-ERROR: 0:21: 'limitation' : do-while loops not available \r
-ERROR: 2 compilation errors.  No code generated.\r
+ERROR: 0:24: 'limitation' : while loops not available \r
+ERROR: 0:26: 'limitation' : do-while loops not available \r
+ERROR: 0:28: 'limitations' : inductive-loop init-declaration requires the form "type-specifier loop-index = constant-expression" \r
+ERROR: 0:29: 'limitations' : inductive-loop init-declaration requires the form "type-specifier loop-index = constant-expression" \r
+ERROR: 0:30: 'limitations' : inductive-loop init-declaration requires the form "type-specifier loop-index = constant-expression" \r
+ERROR: 0:31: 'limitations' : inductive-loop init-declaration requires the form "type-specifier loop-index = constant-expression" \r
+ERROR: 0:32: 'limitations' : inductive loop requires a scalar 'int' or 'float' loop index \r
+ERROR: 0:33: 'limitations' : inductive-loop condition requires the form "loop-index <comparison-op> constant-expression" \r
+ERROR: 0:34: 'limitations' : inductive-loop termination requires the form "loop-index++, loop-index--, loop-index += constant-expression, or loop-index -= constant-expression" \r
+ERROR: 0:35: 'limitations' : inductive loop index modified \r
+ERROR: 0:36: 'limitations' : inductive loop index modified \r
+ERROR: 0:43: 'limitations' : inductive loop index modified \r
+ERROR: 0:47: 'limitations' : Non-constant-index-expression \r
+ERROR: 0:49: 'limitations' : Non-constant-index-expression \r
+ERROR: 0:50: 'limitations' : Non-constant-index-expression \r
+ERROR: 0:51: 'limitations' : Non-constant-index-expression \r
+ERROR: 0:52: 'limitations' : Non-constant-index-expression \r
+ERROR: 0:53: 'limitations' : Non-constant-index-expression \r
+ERROR: 0:54: 'limitations' : Non-constant-index-expression \r
+ERROR: 0:65: 'limitations' : Non-constant-index-expression \r
+ERROR: 20 compilation errors.  No code generated.\r
 \r
 \r
index dd6f5bb..f54d85d 100644 (file)
@@ -156,6 +156,7 @@ xcopy /y $(IntDir)$(TargetName)$(TargetExt) Test</Command>
     </ClCompile>\r
     <ClCompile Include="glslang\MachineIndependent\InfoSink.cpp" />\r
     <ClCompile Include="glslang\MachineIndependent\Initialize.cpp" />\r
+    <ClCompile Include="glslang\MachineIndependent\limits.cpp" />\r
     <ClCompile Include="glslang\MachineIndependent\preprocessor\Pp.cpp" />\r
     <ClCompile Include="glslang\MachineIndependent\preprocessor\PpAtom.cpp" />\r
     <ClCompile Include="glslang\MachineIndependent\preprocessor\PpMemory.cpp" />\r
index 8e98fe6..9f12741 100644 (file)
     <ClCompile Include="glslang\MachineIndependent\preprocessor\PpContext.cpp">\r
       <Filter>Machine Independent\Preprocessor</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="glslang\MachineIndependent\limits.cpp">\r
+      <Filter>Machine Independent</Filter>\r
+    </ClCompile>\r
   </ItemGroup>\r
   <ItemGroup>\r
     <ClInclude Include="glslang\MachineIndependent\Initialize.h">\r
index 549ec86..a1e012e 100644 (file)
@@ -316,6 +316,7 @@ enum TOperator {
 };
 
 class TIntermTraverser;
+class TIntermOperator;
 class TIntermAggregate;
 class TIntermUnary;
 class TIntermBinary;
@@ -342,16 +343,17 @@ public:
     virtual glslang::TSourceLoc getLoc() const { return loc; }
     virtual void setLoc(glslang::TSourceLoc l) { loc = l; }
     virtual void traverse(glslang::TIntermTraverser*) = 0;
-    virtual glslang::TIntermTyped*     getAsTyped()         { return 0; }
-    virtual glslang::TIntermConstantUnion*     getAsConstantUnion()         { return 0; }
-    virtual glslang::TIntermAggregate* getAsAggregate()     { return 0; }
-    virtual glslang::TIntermUnary*     getAsUnaryNode()     { return 0; }
-    virtual glslang::TIntermBinary*    getAsBinaryNode()    { return 0; }
-    virtual glslang::TIntermSelection* getAsSelectionNode() { return 0; }
-    virtual glslang::TIntermSwitch*    getAsSwitchNode()    { return 0; }
-    virtual glslang::TIntermMethod*    getAsMethodNode()    { return 0; }
-    virtual glslang::TIntermSymbol*    getAsSymbolNode()    { return 0; }
-    virtual glslang::TIntermBranch*    getAsBranchNode()    { return 0; }
+    virtual glslang::TIntermTyped*         getAsTyped()         { return 0; }
+    virtual glslang::TIntermOperator*      getAsOperator()      { return 0; }
+    virtual glslang::TIntermConstantUnion* getAsConstantUnion() { return 0; }
+    virtual glslang::TIntermAggregate*     getAsAggregate()     { return 0; }
+    virtual glslang::TIntermUnary*         getAsUnaryNode()     { return 0; }
+    virtual glslang::TIntermBinary*        getAsBinaryNode()    { return 0; }
+    virtual glslang::TIntermSelection*     getAsSelectionNode() { return 0; }
+    virtual glslang::TIntermSwitch*        getAsSwitchNode()    { return 0; }
+    virtual glslang::TIntermMethod*        getAsMethodNode()    { return 0; }
+    virtual glslang::TIntermSymbol*        getAsSymbolNode()    { return 0; }
+    virtual glslang::TIntermBranch*        getAsBranchNode()    { return 0; }
     virtual ~TIntermNode() { }
 protected:
     glslang::TSourceLoc loc;
@@ -478,7 +480,7 @@ public:
     TIntermConstantUnion(const TConstUnionArray& ua, const TType& t) : TIntermTyped(t), unionArray(ua) { }
     const TConstUnionArray& getConstArray() const { return unionArray; }
     virtual TIntermConstantUnion* getAsConstantUnion()  { return this; }
-    virtual void traverse(TIntermTraverser* );
+    virtual void traverse(TIntermTraverser*);
     virtual TIntermTyped* fold(TOperator, TIntermTyped*);
     virtual TIntermTyped* fold(TOperator, const TType&);
 protected:
@@ -490,6 +492,7 @@ protected:
 //
 class TIntermOperator : public TIntermTyped {
 public:
+    TIntermOperator* getAsOperator() { return this; }
     TOperator getOp() { return op; }
     bool modifiesState() const;
     bool isConstructor() const;
index 218fe94..3559a92 100644 (file)
@@ -713,9 +713,9 @@ TIntermTyped* TIntermediate::foldConstructor(TIntermAggregate* aggrNode)
 
     TConstUnionArray unionArray(aggrNode->getType().getObjectSize());
     if (aggrNode->getSequence().size() == 1)
-        error = parseConstTree(aggrNode->getLoc(), aggrNode, unionArray, aggrNode->getOp(), aggrNode->getType(), true);
+        error = parseConstTree(aggrNode, unionArray, aggrNode->getOp(), aggrNode->getType(), true);
     else
-        error = parseConstTree(aggrNode->getLoc(), aggrNode, unionArray, aggrNode->getOp(), aggrNode->getType());
+        error = parseConstTree(aggrNode, unionArray, aggrNode->getOp(), aggrNode->getType());
 
     if (error)
         return aggrNode;
index 9c18414..0088dcd 100644 (file)
@@ -809,11 +809,11 @@ TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, TSourceLoc loc)
 //
 // Create loop nodes.
 //
-TIntermNode* TIntermediate::addLoop(TIntermNode* body, TIntermTyped* test, TIntermTyped* terminal, bool testFirst, TSourceLoc loc)
+TIntermLoop* TIntermediate::addLoop(TIntermNode* body, TIntermTyped* test, TIntermTyped* terminal, bool testFirst, TSourceLoc loc)
 {
-    TIntermNode* node = new TIntermLoop(body, test, terminal, testFirst);
+    TIntermLoop* node = new TIntermLoop(body, test, terminal, testFirst);
     node->setLoc(loc);
-    
+
     return node;
 }
 
index 2ed8365..1b6c404 100644 (file)
@@ -11,7 +11,7 @@ LIBCODEGEN=./../GenericCodeGen/libCodeGen.a
 OBJECTS= Initialize.o IntermTraverse.o \
        Intermediate.o ParseHelper.o PoolAlloc.o QualifierAlive.o \
        RemoveTree.o ShaderLang.o intermOut.o parseConst.o SymbolTable.o \
-       InfoSink.o Versions.o Constant.o Scan.o
+       InfoSink.o Versions.o Constant.o Scan.o limits.o
 
 SRCS= gen_glslang_tab.cpp Initialize.cpp IntermTraverse.cpp \
        Intermediate.cpp ParseHelper.cpp PoolAlloc.cp QualifierAlive.cpp \
@@ -146,3 +146,4 @@ parseConst.o: ../Public/ShaderLang.h
 InfoSink.o: ../Include/InfoSink.h
 Versions.o: ParseHelper.h  Versions.h ../Include/ShHandle.h SymbolTable.h localintermediate.h
 Constant.o: localintermediate.h ../Include/intermediate.h ../Public/ShaderLang.h SymbolTable.h Versions.h
+limits.o:  ParseHelper.h
index b0de06a..6fb2c8d 100644 (file)
@@ -154,8 +154,17 @@ bool TParseContext::parseShaderStrings(TPpContext& ppContext, char* strings[], s
             return true;
     }
 
+    anyIndexLimits = ! limits.generalAttributeMatrixVectorIndexing ||
+                     ! limits.generalConstantMatrixVectorIndexing ||
+                     ! limits.generalSamplerIndexing ||
+                     ! limits.generalUniformIndexing ||
+                     ! limits.generalVariableIndexing ||
+                     ! limits.generalVaryingIndexing;
+
     yyparse((void*)this);
 
+    finalize();
+
     return numErrors == 0;
 }
 
@@ -510,6 +519,23 @@ TIntermTyped* TParseContext::handleBracketDereference(TSourceLoc loc, TIntermTyp
             newType.getQualifier().storage = EvqConst;
         newType.dereference();
         result->setType(newType);
+
+        if (anyIndexLimits) {
+            // for ES 2.0 (version 100) limitations for almost all index operations except vertex-shader uniforms
+            if ((! limits.generalSamplerIndexing && base->getBasicType() == EbtSampler) ||
+                (! limits.generalUniformIndexing && base->getQualifier().isUniform() && language != EShLangVertex) ||
+                (! limits.generalAttributeMatrixVectorIndexing && base->getQualifier().isPipeInput() && language == EShLangVertex && (base->getType().isMatrix() || base->getType().isVector())) ||
+                (! limits.generalConstantMatrixVectorIndexing && base->getAsConstantUnion()) ||
+                (! limits.generalVariableIndexing && ! base->getType().getQualifier().isUniform() && 
+                                                     ! base->getType().getQualifier().isPipeInput() && 
+                                                     ! base->getType().getQualifier().isPipeOutput() &&
+                                                       base->getType().getQualifier().storage != EvqConst) ||
+                (! limits.generalVaryingIndexing && (base->getType().getQualifier().isPipeInput() || 
+                                                     base->getType().getQualifier().isPipeOutput()))) {            
+                // it's too early to know what the inductive variables are, save it for post processing
+                needsIndexLimitationChecking.push_back(index);
+            }
+        }
     }
 
     return result;
@@ -1915,6 +1941,133 @@ void TParseContext::arrayObjectCheck(TSourceLoc loc, const TType& type, const ch
 }
 
 //
+// See if this loop satisfies the limitations for ES 2.0 (version 100) for loops in Appendex A:
+//
+// "The loop index has type int or float.
+//
+// "The for statement has the form:
+//     for ( init-declaration ; condition ; expression ) 
+//     init-declaration has the form: type-specifier identifier = constant-expression
+//     condition has the form:  loop-index relational_operator constant-expression
+//         where relational_operator is one of: > >= < <= == or !=
+//     expression [sic] has one of the following forms:
+//         loop-index++
+//         loop-index--
+//         loop-index += constant-expression
+//         loop-index -= constant-expression
+//
+// The body is handled in an AST traversal.
+//
+void TParseContext::inductiveLoopCheck(TSourceLoc loc, TIntermNode* init, TIntermLoop* loop)
+{
+    // loop index init must exist and be a declaration, which shows up in the AST as an aggregate of size 1 of the declaration
+    bool badInit = false;
+    if (! init || ! init->getAsAggregate() || ! init->getAsAggregate()->getSequence().size() == 1)
+        badInit = true;
+    TIntermBinary* binaryInit;
+    if (! badInit) {
+        // get the declaration assignment
+        binaryInit = init->getAsAggregate()->getSequence()[0]->getAsBinaryNode();
+        if (! binaryInit)
+            badInit = true;
+    }
+    if (badInit) {
+        error(loc, "inductive-loop init-declaration requires the form \"type-specifier loop-index = constant-expression\"", "limitations", "");
+        return;
+    }
+
+    // loop index must be type int or float
+    if (! binaryInit->getType().isScalar() || (binaryInit->getBasicType() != EbtInt && binaryInit->getBasicType() != EbtFloat)) {
+        error(loc, "inductive loop requires a scalar 'int' or 'float' loop index", "limitations", "");
+        return;
+    }
+
+    // init is the form "loop-index = constant"
+    if (binaryInit->getOp() != EOpAssign || ! binaryInit->getLeft()->getAsSymbolNode() || ! binaryInit->getRight()->getAsConstantUnion()) {
+        error(loc, "inductive-loop init-declaration requires the form \"type-specifier loop-index = constant-expression\"", "limitations", "");
+        return;
+    }
+    
+    // get the unique id of the loop index
+    int loopIndex = binaryInit->getLeft()->getAsSymbolNode()->getId();
+    inductiveLoopIds.insert(loopIndex);
+    
+    // condition's form must be "loop-index relational-operator constant-expression"
+    bool badCond = ! loop->getTest();
+    if (! badCond) {
+        TIntermBinary* binaryCond = loop->getTest()->getAsBinaryNode();
+        badCond = ! binaryCond;
+        if (! badCond) {
+            switch (binaryCond->getOp()) {
+            case EOpGreaterThan:
+            case EOpGreaterThanEqual:
+            case EOpLessThan:
+            case EOpLessThanEqual:
+            case EOpEqual:
+            case EOpNotEqual:
+                break;
+            default:
+                badCond = true;
+            }
+        }
+        if (binaryCond && (! binaryCond->getLeft()->getAsSymbolNode() ||
+                           binaryCond->getLeft()->getAsSymbolNode()->getId() != loopIndex ||
+                           ! binaryCond->getRight()->getAsConstantUnion()))
+            badCond = true;
+    }
+    if (badCond) {
+        error(loc, "inductive-loop condition requires the form \"loop-index <comparison-op> constant-expression\"", "limitations", "");
+        return;
+    }
+
+    // loop-index++
+    // loop-index--
+    // loop-index += constant-expression
+    // loop-index -= constant-expression
+    bool badTerminal = ! loop->getTerminal();
+    if (! badTerminal) {
+        TIntermUnary* unaryTerminal = loop->getTerminal()->getAsUnaryNode();
+        TIntermBinary* binaryTerminal = loop->getTerminal()->getAsBinaryNode();
+        if (unaryTerminal || binaryTerminal) {
+            switch(loop->getTerminal()->getAsOperator()->getOp()) {
+            case EOpPostDecrement:
+            case EOpPostIncrement:
+            case EOpAddAssign:
+            case EOpSubAssign:
+                break;
+            default:
+                badTerminal = true;
+            }
+        } else
+            badTerminal = true;
+        if (binaryTerminal && (! binaryTerminal->getLeft()->getAsSymbolNode() ||
+                               binaryTerminal->getLeft()->getAsSymbolNode()->getId() != loopIndex ||
+                               ! binaryTerminal->getRight()->getAsConstantUnion()))
+            badTerminal = true;
+        if (unaryTerminal && (! unaryTerminal->getOperand()->getAsSymbolNode() ||
+                              unaryTerminal->getOperand()->getAsSymbolNode()->getId() != loopIndex))
+            badTerminal = true;
+    }
+    if (badTerminal) {
+        error(loc, "inductive-loop termination requires the form \"loop-index++, loop-index--, loop-index += constant-expression, or loop-index -= constant-expression\"", "limitations", "");
+        return;
+    }
+
+    // the body
+    inductiveLoopBodyCheck(loop->getBody(), loopIndex, symbolTable);
+}
+
+//
+// Do any additional error checking, etc., once we know the parsing is done.
+//
+void TParseContext::finalize()
+{
+    // Check on array indexes for ES 2.0 (version 100) limitations.
+    for (size_t i = 0; i < needsIndexLimitationChecking.size(); ++i)
+        constantIndexExpressionCheck(needsIndexLimitationChecking[i]);
+}
+
+//
 // Layout qualifier stuff.
 //
 
index 57b99b8..4e8d7d8 100644 (file)
@@ -53,6 +53,8 @@ struct TPragma {
 class TScanContext;
 class TPpContext;
 
+typedef std::set<int> TIdSetType;
+
 //
 // The following are extra variables needed during parsing, grouped together so
 // they can be passed to the parser without needing a global.
@@ -116,6 +118,9 @@ public:
     void nestedBlockCheck(TSourceLoc);
     void nestedStructCheck(TSourceLoc);
     void arrayObjectCheck(TSourceLoc, const TType&, const char* op);
+    void inductiveLoopCheck(TSourceLoc, TIntermNode* init, TIntermLoop* loop);
+    void inductiveLoopBodyCheck(TIntermNode*, int loopIndexId, TSymbolTable&);
+    void constantIndexExpressionCheck(TIntermNode*);
 
     void setLayoutQualifier(TSourceLoc, TPublicType&, TString&);
     void setLayoutQualifier(TSourceLoc, TPublicType&, TString&, int);
@@ -167,6 +172,7 @@ protected:
     void declareArray(TSourceLoc, TString& identifier, const TType&, TSymbol*&, bool& newDeclaration);
     TIntermNode* executeInitializer(TSourceLoc, TString& identifier, TIntermTyped* initializer, TVariable* variable);
     TOperator mapTypeToConstructorOp(const TType&);
+    void finalize();
 
 public:
     //
@@ -213,6 +219,9 @@ protected:
     TQualifier globalInputDefaults;
     TQualifier globalOutputDefaults;
     TString currentCaller;
+    TIdSetType inductiveLoopIds;
+    bool anyIndexLimits;
+    TVector<TIntermTyped*> needsIndexLimitationChecking;
     // TODO: desktop functionality: track use of gl_FragDepth before redeclaration
 };
 
index 460742d..e9a4b37 100644 (file)
@@ -2278,10 +2278,10 @@ iteration_statement
       for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope {\r
         parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]);\r
         $$ = parseContext.intermediate.makeAggregate($4, $2.loc);\r
-        $$ = parseContext.intermediate.growAggregate(\r
-                $$,\r
-                parseContext.intermediate.addLoop($7, reinterpret_cast<TIntermTyped*>($5.node1), reinterpret_cast<TIntermTyped*>($5.node2), true, $1.loc),\r
-                $1.loc);\r
+        TIntermLoop* forLoop = parseContext.intermediate.addLoop($7, reinterpret_cast<TIntermTyped*>($5.node1), reinterpret_cast<TIntermTyped*>($5.node2), true, $1.loc);\r
+        if (! parseContext.limits.nonInductiveForLoops)\r
+            parseContext.inductiveLoopCheck($1.loc, $4, forLoop);\r
+        $$ = parseContext.intermediate.growAggregate($$, forLoop, $1.loc);\r
         $$->getAsAggregate()->setOperator(EOpSequence);\r
         --parseContext.loopNestingLevel;\r
     }\r
diff --git a/glslang/MachineIndependent/limits.cpp b/glslang/MachineIndependent/limits.cpp
new file mode 100644 (file)
index 0000000..0c660a8
--- /dev/null
@@ -0,0 +1,199 @@
+//\r
+//Copyright (C) 2013 LunarG, Inc.\r
+//\r
+//All rights reserved.\r
+//\r
+//Redistribution and use in source and binary forms, with or without\r
+//modification, are permitted provided that the following conditions\r
+//are met:\r
+//\r
+//    Redistributions of source code must retain the above copyright\r
+//    notice, this list of conditions and the following disclaimer.\r
+//\r
+//    Redistributions in binary form must reproduce the above\r
+//    copyright notice, this list of conditions and the following\r
+//    disclaimer in the documentation and/or other materials provided\r
+//    with the distribution.\r
+//\r
+//    Neither the name of 3Dlabs Inc. Ltd. nor the names of its\r
+//    contributors may be used to endorse or promote products derived\r
+//    from this software without specific prior written permission.\r
+//\r
+//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r
+//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\r
+//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS\r
+//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE\r
+//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\r
+//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,\r
+//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\r
+//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\r
+//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\r
+//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\r
+//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+//POSSIBILITY OF SUCH DAMAGE.\r
+//\r
+\r
+//\r
+// Do sub tree walks for\r
+// 1) inductive loop bodies to see if the inductive variable is modified\r
+// 2) array-index expressions to see if they are "constant-index-expression"\r
+//\r
+// These are per Appendix A of ES 2.0:\r
+//\r
+// "Within the body of the loop, the loop index is not statically assigned to nor is it used as the\r
+// argument to a function out or inout parameter."\r
+//\r
+// "The following are constant-index-expressions:\r
+//  - Constant expressions\r
+//  - Loop indices as defined in section 4\r
+//  - Expressions composed of both of the above"\r
+//\r
+// N.B.: assuming the last rule excludes function calls\r
+//\r
+\r
+#include "ParseHelper.h"\r
+\r
+namespace glslang {\r
+\r
+//\r
+// The inductive loop-body traverser.\r
+//\r
+// Just look at things that might modify the loop index.\r
+//\r
+\r
+class TInductiveTraverser : public TIntermTraverser {\r
+public:\r
+    TInductiveTraverser(int id, TSymbolTable& st) : loopId(id), symbolTable(st), bad(false)  { }\r
+    int loopId;           // unique ID of the symbol that's the loop inductive variable\r
+    TSymbolTable& symbolTable;\r
+    bool bad;\r
+    TSourceLoc badLoc;\r
+};\r
+\r
+// check binary operations for those modifying the loop index\r
+bool InductiveBinary(bool /* preVisit */, TIntermBinary* node, TIntermTraverser* it)\r
+{\r
+    TInductiveTraverser* oit = static_cast<TInductiveTraverser*>(it);\r
+\r
+    if (node->modifiesState() && node->getLeft()->getAsSymbolNode() && \r
+                                 node->getLeft()->getAsSymbolNode()->getId() == oit->loopId) {\r
+        oit->bad = true;\r
+        oit->badLoc = node->getLoc();\r
+    }\r
+\r
+    return true;\r
+}\r
+\r
+// check unary operations for those modifying the loop index\r
+bool InductiveUnary(bool /* preVisit */, TIntermUnary* node, TIntermTraverser* it)\r
+{\r
+    TInductiveTraverser* oit = static_cast<TInductiveTraverser*>(it);\r
+\r
+    if (node->modifiesState() && node->getOperand()->getAsSymbolNode() && \r
+                                 node->getOperand()->getAsSymbolNode()->getId() == oit->loopId) {\r
+        oit->bad = true;\r
+        oit->badLoc = node->getLoc();\r
+    }\r
+\r
+    return true;\r
+}\r
+\r
+// check function calls for arguments modifying the loop index\r
+bool InductiveAggregate(bool /* preVisit */, TIntermAggregate* node, TIntermTraverser* it)\r
+{\r
+    TInductiveTraverser* oit = static_cast<TInductiveTraverser*>(it);\r
+\r
+    if (node->getOp() == EOpFunctionCall) {\r
+        // see if an out or inout argument is the loop index\r
+        const TIntermSequence& args = node->getSequence();\r
+        for (size_t i = 0; i < args.size(); ++i) {\r
+            if (args[i]->getAsSymbolNode() && args[i]->getAsSymbolNode()->getId() == oit->loopId) {\r
+                TSymbol* function = oit->symbolTable.find(node->getName());\r
+                const TType* type = (*function->getAsFunction())[i].type;\r
+                if (type->getQualifier().storage == EvqOut ||\r
+                    type->getQualifier().storage == EvqInOut) {\r
+                    oit->bad = true;\r
+                    oit->badLoc = node->getLoc();\r
+                }\r
+            }\r
+        }\r
+    }\r
+\r
+    return true;\r
+}\r
+\r
+//\r
+// External function to call for loop check.\r
+//\r
+void TParseContext::inductiveLoopBodyCheck(TIntermNode* body, int loopId, TSymbolTable& symbolTable)\r
+{\r
+    TInductiveTraverser it(loopId, symbolTable);\r
+\r
+    if (! body)\r
+        return;\r
+\r
+    it.visitAggregate = InductiveAggregate;\r
+    it.visitBinary = InductiveBinary;\r
+    it.visitUnary = InductiveUnary;\r
+\r
+    body->traverse(&it);\r
+\r
+    if (it.bad)\r
+        error(it.badLoc, "inductive loop index modified", "limitations", "");\r
+}\r
+\r
+//\r
+// The "constant-index-expression" tranverser.\r
+//\r
+// Just look at things that can form an index.  \r
+//\r
+\r
+class TIndexTraverser : public TIntermTraverser {\r
+public:\r
+    TIndexTraverser(const TIdSetType& ids) : inductiveLoopIds(ids), bad(false) { }\r
+    const TIdSetType& inductiveLoopIds;\r
+    bool bad;\r
+    TSourceLoc badLoc;\r
+};\r
+\r
+// make sure symbols are inductive-loop indexes\r
+void IndexSymbol(TIntermSymbol* symbol, TIntermTraverser* it)\r
+{\r
+    TIndexTraverser* oit = static_cast<TIndexTraverser*>(it);\r
+\r
+    if (oit->inductiveLoopIds.find(symbol->getId()) == oit->inductiveLoopIds.end()) {\r
+        oit->bad = true;\r
+        oit->badLoc = symbol->getLoc();\r
+    }\r
+}\r
+\r
+// check for function calls, assuming they are bad; spec. doesn't really say\r
+bool IndexAggregate(bool /* preVisit */, TIntermAggregate* node, TIntermTraverser* it)\r
+{\r
+    TIndexTraverser* oit = static_cast<TIndexTraverser*>(it);\r
+\r
+    if (node->getOp() == EOpFunctionCall) {\r
+        oit->bad = true;\r
+        oit->badLoc = node->getLoc();\r
+    }\r
+\r
+    return true;\r
+}\r
+\r
+//\r
+// External function to call for loop check.\r
+//\r
+void TParseContext::constantIndexExpressionCheck(TIntermNode* index)\r
+{\r
+    TIndexTraverser it(inductiveLoopIds);\r
+\r
+    it.visitSymbol = IndexSymbol;\r
+    it.visitAggregate = IndexAggregate;\r
+\r
+    index->traverse(&it);\r
+\r
+    if (it.bad)\r
+        error(it.badLoc, "Non-constant-index-expression", "limitations", "");\r
+}\r
+\r
+} // end namespace glslang\r
index b8c3727..f038211 100644 (file)
@@ -89,8 +89,8 @@ public:
     TIntermTyped* addMethod(TIntermTyped*, const TType&, const TString*, TSourceLoc);
     TIntermConstantUnion* addConstantUnion(const TConstUnionArray&, const TType&, TSourceLoc);
     TIntermTyped* promoteConstantUnion(TBasicType, TIntermConstantUnion*) ;
-    bool parseConstTree(TSourceLoc, TIntermNode*, TConstUnionArray, TOperator, const TType&, bool singleConstantParam = false);
-    TIntermNode* addLoop(TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, TSourceLoc);
+    bool parseConstTree(TIntermNode*, TConstUnionArray, TOperator, const TType&, bool singleConstantParam = false);
+    TIntermLoop* addLoop(TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, TSourceLoc);
     TIntermBranch* addBranch(TOperator, TSourceLoc);
     TIntermBranch* addBranch(TOperator, TIntermTyped*, TSourceLoc);
     TIntermTyped* addSwizzle(TVectorFields&, TSourceLoc);
index e77b96f..872607b 100644 (file)
@@ -45,7 +45,7 @@ class TConstTraverser : public TIntermTraverser {
 public:
     TConstTraverser(const TConstUnionArray& cUnion, bool singleConstParam, TOperator constructType, const TType& t) : unionArray(cUnion), type(t),
         constructorType(constructType), singleConstantParam(singleConstParam), error(false), isMatrix(false), 
-        matrixCols(0), matrixRows(0) {  index = 0; tOp = EOpNull;}
+        matrixCols(0), matrixRows(0) {  index = 0; tOp = EOpNull; }
     int index;
     TConstUnionArray unionArray;
     TOperator tOp;
@@ -170,7 +170,7 @@ void ParseConstantUnion(TIntermConstantUnion* node, TIntermTraverser* it)
     }
 }
 
-bool TIntermediate::parseConstTree(TSourceLoc line, TIntermNode* root, TConstUnionArray unionArray, TOperator constructorType, const TType& t, bool singleConstantParam)
+bool TIntermediate::parseConstTree(TIntermNode* root, TConstUnionArray unionArray, TOperator constructorType, const TType& t, bool singleConstantParam)
 {
     if (root == 0)
         return false;