Implement ES 2.0 (version 100) limitations for non-inductive loop detection and array indexes needing "constant-index-expressions" (inductive variables and constant expressions).

git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@23478 e7fa87d3-cd2b-0410-9028-fcbf551c1848
This commit is contained in:
John Kessenich 2013-10-14 22:42:16 +00:00
parent a4ea1313c3
commit 27b72e42c3
15 changed files with 856 additions and 240 deletions

View File

@ -14,32 +14,46 @@ const vec3 v3 = vec3(2.0);
void foo(inout float a) {} void foo(inout float a) {}
int bar()
{
return 1;
}
void main() void main()
{ {
while (ga < gb) { } while (ga < gb) { }
do { } while (false); do { } while (false);
for ( ga = 0; ; ); for ( ; ; ); // ERROR
for ( bool a = false; ; ); for ( ; ga==gb; ); // ERROR
for (float a = 0.0; a == sin(f); ); for ( ; ; f++); // ERROR
for ( int a = 0; a < 10; a *= 2); for ( ga = 0; ; ); // ERROR
for ( int a = 0; a <= 20; ++a) --a; for ( bool a = false; ; ); // ERROR
for (float a = 0.0; a == sin(f); ); // ERROR
for ( int a = 0; a < 10; a *= 2); // ERROR
for ( int a = 0; a <= 20; a++) --a; // ERROR
for ( int a = 0; a <= 20; a++) { if (ga==0) a = 4; } // ERROR
for (float a = 0.0; a <= 20.0; a += 2.0); for (float a = 0.0; a <= 20.0; a += 2.0);
for (float a = 0.0; a <= 20.0; a += 2.0) foo(a); for (float a = 0.0; a != 20.0; a -= 2.0) { if (ga==0) ga = 4; }
for (float a = 0.0; a == 20.0; a--) for (float a = 0.0; a == 20.0; a--); // two different 'a's, everything okay
for (float a = 0.0; a <= 20.0; a += 2.0);
for (float a = 0.0; a <= 20.0; a += 2.0);
for (float a = 0.0; a > 2.0 * 20.0; a += v3.y);
for (float a = 0.0; a >= 20.0; a += 2.0) foo(a); // ERROR
int ia[9]; int ia[9];
fsa[ga]; fsa[ga]; // ERROR
fua[ga]; fua[ga];
am3[ga]; am3[ga]; // ERROR
av2[ga]; av2[ga]; // ERROR
va[ga]; va[2+ga]; // ERROR
m2[ga]; m2[ga]; // ERROR
v3[ga]; v3[ga/2]; // ERROR
ia[ga]; ia[ga]; // ERROR
for ( int a = 3; a >= 0; --a) { for (int a = 3; a >= 0; a--) {
fsa[a]; fsa[a];
fua[a+2]; fua[a+2];
am3[3*a]; am3[3*a];
@ -48,6 +62,15 @@ void main()
m2[a/2]; m2[a/2];
v3[a]; v3[a];
ia[a]; ia[a];
ia[bar()]; // ERROR
} }
fsa[2];
fua[3];
am3[2];
av2[1];
va[1];
m2[1];
v3[1];
ia[3];
} }

View File

@ -2,218 +2,424 @@
0:15 Function Definition: foo(f1; (void) 0:15 Function Definition: foo(f1; (void)
0:15 Function Parameters: 0:15 Function Parameters:
0:15 'a' (inout highp float) 0:15 'a' (inout highp float)
0:17 Function Definition: main( (void) 0:17 Function Definition: bar( (highp int)
0:17 Function Parameters: 0:17 Function Parameters:
0:19 Sequence 0:19 Sequence
0:19 Loop with condition tested first 0:19 Branch: Return with expression
0:19 Loop Condition 0:19 Constant:
0:19 Compare Less Than (bool) 0:19 1 (const int)
0:19 'ga' (highp int) 0:22 Function Definition: main( (void)
0:19 'gb' (highp int) 0:22 Function Parameters:
0:19 No loop body 0:24 Sequence
0:21 Loop with condition not tested first 0:24 Loop with condition tested first
0:21 Loop Condition 0:24 Loop Condition
0:21 Constant: 0:24 Compare Less Than (bool)
0:21 false (const bool) 0:24 'ga' (highp int)
0:21 No loop body 0:24 'gb' (highp int)
0:23 Sequence 0:24 No loop body
0:23 move second child to first child (highp int) 0:26 Loop with condition not tested first
0:23 'ga' (highp int) 0:26 Loop Condition
0:23 Constant: 0:26 Constant:
0:23 0 (const int) 0:26 false (const bool)
0:23 Loop with condition tested first 0:26 No loop body
0:23 No loop condition
0:23 No loop body
0:24 Sequence
0:24 Sequence
0:24 move second child to first child (bool)
0:24 'a' (bool)
0:24 Constant:
0:24 false (const bool)
0:24 Loop with condition tested first
0:24 No loop condition
0:24 No loop body
0:25 Sequence
0:25 Sequence
0:25 move second child to first child (highp float)
0:25 'a' (highp float)
0:25 Constant:
0:25 0.000000
0:25 Loop with condition tested first
0:25 Loop Condition
0:25 Compare Equal (bool)
0:25 'a' (highp float)
0:25 sine (highp float)
0:25 'f' (highp float)
0:25 No loop body
0:26 Sequence
0:26 Sequence
0:26 move second child to first child (highp int)
0:26 'a' (highp int)
0:26 Constant:
0:26 0 (const int)
0:26 Loop with condition tested first
0:26 Loop Condition
0:26 Compare Less Than (bool)
0:26 'a' (highp int)
0:26 Constant:
0:26 10 (const int)
0:26 No loop body
0:26 Loop Terminal Expression
0:26 multiply second child into first child (highp int)
0:26 'a' (highp int)
0:26 Constant:
0:26 2 (const int)
0:27 Sequence
0:27 Sequence
0:27 move second child to first child (highp int)
0:27 'a' (highp int)
0:27 Constant:
0:27 0 (const int)
0:27 Loop with condition tested first
0:27 Loop Condition
0:27 Compare Less Than or Equal (bool)
0:27 'a' (highp int)
0:27 Constant:
0:27 20 (const int)
0:27 Loop Body
0:27 Pre-Decrement (highp int)
0:27 'a' (highp int)
0:27 Loop Terminal Expression
0:27 Pre-Increment (highp int)
0:27 'a' (highp int)
0:28 Sequence 0:28 Sequence
0:28 Sequence
0:28 move second child to first child (highp float)
0:28 'a' (highp float)
0:28 Constant:
0:28 0.000000
0:28 Loop with condition tested first 0:28 Loop with condition tested first
0:28 Loop Condition 0:28 No loop condition
0:28 Compare Less Than or Equal (bool)
0:28 'a' (highp float)
0:28 Constant:
0:28 20.000000
0:28 No loop body 0:28 No loop body
0:28 Loop Terminal Expression
0:28 add second child into first child (highp float)
0:28 'a' (highp float)
0:28 Constant:
0:28 2.000000
0:29 Sequence 0:29 Sequence
0:29 Sequence
0:29 move second child to first child (highp float)
0:29 'a' (highp float)
0:29 Constant:
0:29 0.000000
0:29 Loop with condition tested first 0:29 Loop with condition tested first
0:29 Loop Condition 0:29 Loop Condition
0:29 Compare Less Than or Equal (bool) 0:29 Compare Equal (bool)
0:29 'a' (highp float) 0:29 'ga' (highp int)
0:29 Constant: 0:29 'gb' (highp int)
0:29 20.000000 0:29 No loop body
0:29 Loop Body 0:30 Sequence
0:29 Function Call: foo(f1; (void) 0:30 Loop with condition tested first
0:29 'a' (highp float) 0:30 No loop condition
0:29 Loop Terminal Expression 0:30 No loop body
0:29 add second child into first child (highp float) 0:30 Loop Terminal Expression
0:29 'a' (highp float) 0:30 Post-Increment (highp float)
0:29 Constant: 0:30 'f' (highp float)
0:29 2.000000 0:31 Sequence
0:33 indirect index (uniform lowp sampler2D) 0:31 move second child to first child (highp int)
0:33 'fsa' (uniform 3-element array of lowp sampler2D) 0:31 'ga' (highp int)
0:33 'ga' (highp int) 0:31 Constant:
0:34 indirect index (uniform highp float) 0:31 0 (const int)
0:34 'fua' (uniform 10-element array of highp float) 0:31 Loop with condition tested first
0:34 'ga' (highp int) 0:31 No loop condition
0:35 indirect index (in highp 3-component vector of float) 0:31 No loop body
0:35 'am3' (in highp 3X3 matrix of float) 0:32 Sequence
0:35 'ga' (highp int) 0:32 Sequence
0:36 indirect index (in highp float) 0:32 move second child to first child (bool)
0:36 'av2' (in highp 2-component vector of float) 0:32 'a' (bool)
0:36 'ga' (highp int) 0:32 Constant:
0:37 indirect index (smooth out highp 4-component vector of float) 0:32 false (const bool)
0:37 'va' (smooth out 4-element array of highp 4-component vector of float) 0:32 Loop with condition tested first
0:37 'ga' (highp int) 0:32 No loop condition
0:38 indirect index (const highp 2-component vector of float) 0:32 No loop body
0:38 Constant: 0:33 Sequence
0:38 1.000000 0:33 Sequence
0:38 0.000000 0:33 move second child to first child (highp float)
0:38 0.000000 0:33 'a' (highp float)
0:38 1.000000 0:33 Constant:
0:38 'ga' (highp int) 0:33 0.000000
0:39 indirect index (const highp float) 0:33 Loop with condition tested first
0:39 Constant: 0:33 Loop Condition
0:39 2.000000 0:33 Compare Equal (bool)
0:39 2.000000 0:33 'a' (highp float)
0:39 2.000000 0:33 sine (highp float)
0:39 'ga' (highp int) 0:33 'f' (highp float)
0:40 indirect index (highp int) 0:33 No loop body
0:40 'ia' (9-element array of highp int) 0:34 Sequence
0:40 'ga' (highp int) 0:34 Sequence
0:34 move second child to first child (highp int)
0:34 'a' (highp int)
0:34 Constant:
0:34 0 (const int)
0:34 Loop with condition tested first
0:34 Loop Condition
0:34 Compare Less Than (bool)
0:34 'a' (highp int)
0:34 Constant:
0:34 10 (const int)
0:34 No loop body
0:34 Loop Terminal Expression
0:34 multiply second child into first child (highp int)
0:34 'a' (highp int)
0:34 Constant:
0:34 2 (const int)
0:35 Sequence
0:35 Sequence
0:35 move second child to first child (highp int)
0:35 'a' (highp int)
0:35 Constant:
0:35 0 (const int)
0:35 Loop with condition tested first
0:35 Loop Condition
0:35 Compare Less Than or Equal (bool)
0:35 'a' (highp int)
0:35 Constant:
0:35 20 (const int)
0:35 Loop Body
0:35 Pre-Decrement (highp int)
0:35 'a' (highp int)
0:35 Loop Terminal Expression
0:35 Post-Increment (highp int)
0:35 'a' (highp int)
0:36 Sequence
0:36 Sequence
0:36 move second child to first child (highp int)
0:36 'a' (highp int)
0:36 Constant:
0:36 0 (const int)
0:36 Loop with condition tested first
0:36 Loop Condition
0:36 Compare Less Than or Equal (bool)
0:36 'a' (highp int)
0:36 Constant:
0:36 20 (const int)
0:36 Loop Body
0:36 Sequence
0:36 Test condition and select (void)
0:36 Condition
0:36 Compare Equal (bool)
0:36 'ga' (highp int)
0:36 Constant:
0:36 0 (const int)
0:36 true case
0:36 move second child to first child (highp int)
0:36 'a' (highp int)
0:36 Constant:
0:36 4 (const int)
0:36 Loop Terminal Expression
0:36 Post-Increment (highp int)
0:36 'a' (highp int)
0:37 Sequence
0:37 Sequence
0:37 move second child to first child (highp float)
0:37 'a' (highp float)
0:37 Constant:
0:37 0.000000
0:37 Loop with condition tested first
0:37 Loop Condition
0:37 Compare Less Than or Equal (bool)
0:37 'a' (highp float)
0:37 Constant:
0:37 20.000000
0:37 No loop body
0:37 Loop Terminal Expression
0:37 add second child into first child (highp float)
0:37 'a' (highp float)
0:37 Constant:
0:37 2.000000
0:38 Sequence
0:38 Sequence
0:38 move second child to first child (highp float)
0:38 'a' (highp float)
0:38 Constant:
0:38 0.000000
0:38 Loop with condition tested first
0:38 Loop Condition
0:38 Compare Not Equal (bool)
0:38 'a' (highp float)
0:38 Constant:
0:38 20.000000
0:38 Loop Body
0:38 Sequence
0:38 Test condition and select (void)
0:38 Condition
0:38 Compare Equal (bool)
0:38 'ga' (highp int)
0:38 Constant:
0:38 0 (const int)
0:38 true case
0:38 move second child to first child (highp int)
0:38 'ga' (highp int)
0:38 Constant:
0:38 4 (const int)
0:38 Loop Terminal Expression
0:38 subtract second child into first child (highp float)
0:38 'a' (highp float)
0:38 Constant:
0:38 2.000000
0:39 Sequence
0:39 Sequence
0:39 move second child to first child (highp float)
0:39 'a' (highp float)
0:39 Constant:
0:39 0.000000
0:39 Loop with condition tested first
0:39 Loop Condition
0:39 Compare Equal (bool)
0:39 'a' (highp float)
0:39 Constant:
0:39 20.000000
0:39 Loop Body
0:39 Sequence
0:39 Sequence
0:39 move second child to first child (highp float)
0:39 'a' (highp float)
0:39 Constant:
0:39 0.000000
0:39 Loop with condition tested first
0:39 Loop Condition
0:39 Compare Equal (bool)
0:39 'a' (highp float)
0:39 Constant:
0:39 20.000000
0:39 No loop body
0:39 Loop Terminal Expression
0:39 Post-Decrement (highp float)
0:39 'a' (highp float)
0:39 Loop Terminal Expression
0:39 Post-Decrement (highp float)
0:39 'a' (highp float)
0:40 Sequence
0:40 Sequence
0:40 move second child to first child (highp float)
0:40 'a' (highp float)
0:40 Constant:
0:40 0.000000
0:40 Loop with condition tested first
0:40 Loop Condition
0:40 Compare Less Than or Equal (bool)
0:40 'a' (highp float)
0:40 Constant:
0:40 20.000000
0:40 No loop body
0:40 Loop Terminal Expression
0:40 add second child into first child (highp float)
0:40 'a' (highp float)
0:40 Constant:
0:40 2.000000
0:41 Sequence
0:41 Sequence
0:41 move second child to first child (highp float)
0:41 'a' (highp float)
0:41 Constant:
0:41 0.000000
0:41 Loop with condition tested first
0:41 Loop Condition
0:41 Compare Less Than or Equal (bool)
0:41 'a' (highp float)
0:41 Constant:
0:41 20.000000
0:41 No loop body
0:41 Loop Terminal Expression
0:41 add second child into first child (highp float)
0:41 'a' (highp float)
0:41 Constant:
0:41 2.000000
0:42 Sequence 0:42 Sequence
0:42 Sequence 0:42 Sequence
0:42 move second child to first child (highp int) 0:42 move second child to first child (highp float)
0:42 'a' (highp int) 0:42 'a' (highp float)
0:42 Constant: 0:42 Constant:
0:42 3 (const int) 0:42 0.000000
0:42 Loop with condition tested first 0:42 Loop with condition tested first
0:42 Loop Condition 0:42 Loop Condition
0:42 Compare Greater Than or Equal (bool) 0:42 Compare Greater Than (bool)
0:42 'a' (highp int) 0:42 'a' (highp float)
0:42 Constant: 0:42 Constant:
0:42 0 (const int) 0:42 40.000000
0:42 Loop Body 0:42 No loop body
0:43 Sequence
0:43 indirect index (uniform lowp sampler2D)
0:43 'fsa' (uniform 3-element array of lowp sampler2D)
0:43 'a' (highp int)
0:44 indirect index (uniform highp float)
0:44 'fua' (uniform 10-element array of highp float)
0:44 add (highp int)
0:44 'a' (highp int)
0:44 Constant:
0:44 2 (const int)
0:45 indirect index (in highp 3-component vector of float)
0:45 'am3' (in highp 3X3 matrix of float)
0:45 component-wise multiply (highp int)
0:45 Constant:
0:45 3 (const int)
0:45 'a' (highp int)
0:46 indirect index (in highp float)
0:46 'av2' (in highp 2-component vector of float)
0:46 component-wise multiply (highp int)
0:46 Constant:
0:46 3 (const int)
0:46 'a' (highp int)
0:47 indirect index (smooth out highp 4-component vector of float)
0:47 'va' (smooth out 4-element array of highp 4-component vector of float)
0:47 subtract (highp int)
0:47 'a' (highp int)
0:47 Constant:
0:47 1 (const int)
0:48 indirect index (const highp 2-component vector of float)
0:48 Constant:
0:48 1.000000
0:48 0.000000
0:48 0.000000
0:48 1.000000
0:48 divide (highp int)
0:48 'a' (highp int)
0:48 Constant:
0:48 2 (const int)
0:49 indirect index (const highp float)
0:49 Constant:
0:49 2.000000
0:49 2.000000
0:49 2.000000
0:49 'a' (highp int)
0:50 indirect index (highp int)
0:50 'ia' (9-element array of highp int)
0:50 'a' (highp int)
0:42 Loop Terminal Expression 0:42 Loop Terminal Expression
0:42 Pre-Decrement (highp int) 0:42 add second child into first child (highp float)
0:42 'a' (highp int) 0:42 'a' (highp float)
0:42 Constant:
0:42 2.000000
0:43 Sequence
0:43 Sequence
0:43 move second child to first child (highp float)
0:43 'a' (highp float)
0:43 Constant:
0:43 0.000000
0:43 Loop with condition tested first
0:43 Loop Condition
0:43 Compare Greater Than or Equal (bool)
0:43 'a' (highp float)
0:43 Constant:
0:43 20.000000
0:43 Loop Body
0:43 Function Call: foo(f1; (void)
0:43 'a' (highp float)
0:43 Loop Terminal Expression
0:43 add second child into first child (highp float)
0:43 'a' (highp float)
0:43 Constant:
0:43 2.000000
0:47 indirect index (uniform lowp sampler2D)
0:47 'fsa' (uniform 3-element array of lowp sampler2D)
0:47 'ga' (highp int)
0:48 indirect index (uniform highp float)
0:48 'fua' (uniform 10-element array of highp float)
0:48 'ga' (highp int)
0:49 indirect index (in highp 3-component vector of float)
0:49 'am3' (in highp 3X3 matrix of float)
0:49 'ga' (highp int)
0:50 indirect index (in highp float)
0:50 'av2' (in highp 2-component vector of float)
0:50 'ga' (highp int)
0:51 indirect index (smooth out highp 4-component vector of float)
0:51 'va' (smooth out 4-element array of highp 4-component vector of float)
0:51 add (highp int)
0:51 Constant:
0:51 2 (const int)
0:51 'ga' (highp int)
0:52 indirect index (const highp 2-component vector of float)
0:52 Constant:
0:52 1.000000
0:52 0.000000
0:52 0.000000
0:52 1.000000
0:52 'ga' (highp int)
0:53 indirect index (const highp float)
0:53 Constant:
0:53 2.000000
0:53 2.000000
0:53 2.000000
0:53 divide (highp int)
0:53 'ga' (highp int)
0:53 Constant:
0:53 2 (const int)
0:54 indirect index (highp int)
0:54 'ia' (9-element array of highp int)
0:54 'ga' (highp int)
0:56 Sequence
0:56 Sequence
0:56 move second child to first child (highp int)
0:56 'a' (highp int)
0:56 Constant:
0:56 3 (const int)
0:56 Loop with condition tested first
0:56 Loop Condition
0:56 Compare Greater Than or Equal (bool)
0:56 'a' (highp int)
0:56 Constant:
0:56 0 (const int)
0:56 Loop Body
0:57 Sequence
0:57 indirect index (uniform lowp sampler2D)
0:57 'fsa' (uniform 3-element array of lowp sampler2D)
0:57 'a' (highp int)
0:58 indirect index (uniform highp float)
0:58 'fua' (uniform 10-element array of highp float)
0:58 add (highp int)
0:58 'a' (highp int)
0:58 Constant:
0:58 2 (const int)
0:59 indirect index (in highp 3-component vector of float)
0:59 'am3' (in highp 3X3 matrix of float)
0:59 component-wise multiply (highp int)
0:59 Constant:
0:59 3 (const int)
0:59 'a' (highp int)
0:60 indirect index (in highp float)
0:60 'av2' (in highp 2-component vector of float)
0:60 component-wise multiply (highp int)
0:60 Constant:
0:60 3 (const int)
0:60 'a' (highp int)
0:61 indirect index (smooth out highp 4-component vector of float)
0:61 'va' (smooth out 4-element array of highp 4-component vector of float)
0:61 subtract (highp int)
0:61 'a' (highp int)
0:61 Constant:
0:61 1 (const int)
0:62 indirect index (const highp 2-component vector of float)
0:62 Constant:
0:62 1.000000
0:62 0.000000
0:62 0.000000
0:62 1.000000
0:62 divide (highp int)
0:62 'a' (highp int)
0:62 Constant:
0:62 2 (const int)
0:63 indirect index (const highp float)
0:63 Constant:
0:63 2.000000
0:63 2.000000
0:63 2.000000
0:63 'a' (highp int)
0:64 indirect index (highp int)
0:64 'ia' (9-element array of highp int)
0:64 'a' (highp int)
0:65 indirect index (highp int)
0:65 'ia' (9-element array of highp int)
0:65 Function Call: bar( (highp int)
0:56 Loop Terminal Expression
0:56 Post-Decrement (highp int)
0:56 'a' (highp int)
0:68 direct index (uniform lowp sampler2D)
0:68 'fsa' (uniform 3-element array of lowp sampler2D)
0:68 Constant:
0:68 2 (const int)
0:69 direct index (uniform highp float)
0:69 'fua' (uniform 10-element array of highp float)
0:69 Constant:
0:69 3 (const int)
0:70 direct index (in highp 3-component vector of float)
0:70 'am3' (in highp 3X3 matrix of float)
0:70 Constant:
0:70 2 (const int)
0:71 direct index (in highp float)
0:71 'av2' (in highp 2-component vector of float)
0:71 Constant:
0:71 1 (const int)
0:72 direct index (smooth out highp 4-component vector of float)
0:72 'va' (smooth out 4-element array of highp 4-component vector of float)
0:72 Constant:
0:72 1 (const int)
0:73 Constant:
0:73 0.000000
0:73 1.000000
0:74 Constant:
0:74 2.000000
0:75 direct index (highp int)
0:75 'ia' (9-element array of highp int)
0:75 Constant:
0:75 3 (const int)
0:? Linker Objects 0:? Linker Objects
0:? 'ga' (highp int) 0:? 'ga' (highp int)
0:? 'gb' (highp int) 0:? 'gb' (highp int)

View File

@ -1,5 +1,23 @@
ERROR: 0:19: 'limitation' : while loops not available ERROR: 0:24: 'limitation' : while loops not available
ERROR: 0:21: 'limitation' : do-while loops not available ERROR: 0:26: 'limitation' : do-while loops not available
ERROR: 2 compilation errors. No code generated. ERROR: 0:28: 'limitations' : inductive-loop init-declaration requires the form "type-specifier loop-index = constant-expression"
ERROR: 0:29: 'limitations' : inductive-loop init-declaration requires the form "type-specifier loop-index = constant-expression"
ERROR: 0:30: 'limitations' : inductive-loop init-declaration requires the form "type-specifier loop-index = constant-expression"
ERROR: 0:31: 'limitations' : inductive-loop init-declaration requires the form "type-specifier loop-index = constant-expression"
ERROR: 0:32: 'limitations' : inductive loop requires a scalar 'int' or 'float' loop index
ERROR: 0:33: 'limitations' : inductive-loop condition requires the form "loop-index <comparison-op> constant-expression"
ERROR: 0:34: 'limitations' : inductive-loop termination requires the form "loop-index++, loop-index--, loop-index += constant-expression, or loop-index -= constant-expression"
ERROR: 0:35: 'limitations' : inductive loop index modified
ERROR: 0:36: 'limitations' : inductive loop index modified
ERROR: 0:43: 'limitations' : inductive loop index modified
ERROR: 0:47: 'limitations' : Non-constant-index-expression
ERROR: 0:49: 'limitations' : Non-constant-index-expression
ERROR: 0:50: 'limitations' : Non-constant-index-expression
ERROR: 0:51: 'limitations' : Non-constant-index-expression
ERROR: 0:52: 'limitations' : Non-constant-index-expression
ERROR: 0:53: 'limitations' : Non-constant-index-expression
ERROR: 0:54: 'limitations' : Non-constant-index-expression
ERROR: 0:65: 'limitations' : Non-constant-index-expression
ERROR: 20 compilation errors. No code generated.

View File

@ -156,6 +156,7 @@ xcopy /y $(IntDir)$(TargetName)$(TargetExt) Test</Command>
</ClCompile> </ClCompile>
<ClCompile Include="glslang\MachineIndependent\InfoSink.cpp" /> <ClCompile Include="glslang\MachineIndependent\InfoSink.cpp" />
<ClCompile Include="glslang\MachineIndependent\Initialize.cpp" /> <ClCompile Include="glslang\MachineIndependent\Initialize.cpp" />
<ClCompile Include="glslang\MachineIndependent\limits.cpp" />
<ClCompile Include="glslang\MachineIndependent\preprocessor\Pp.cpp" /> <ClCompile Include="glslang\MachineIndependent\preprocessor\Pp.cpp" />
<ClCompile Include="glslang\MachineIndependent\preprocessor\PpAtom.cpp" /> <ClCompile Include="glslang\MachineIndependent\preprocessor\PpAtom.cpp" />
<ClCompile Include="glslang\MachineIndependent\preprocessor\PpMemory.cpp" /> <ClCompile Include="glslang\MachineIndependent\preprocessor\PpMemory.cpp" />

View File

@ -109,6 +109,9 @@
<ClCompile Include="glslang\MachineIndependent\preprocessor\PpContext.cpp"> <ClCompile Include="glslang\MachineIndependent\preprocessor\PpContext.cpp">
<Filter>Machine Independent\Preprocessor</Filter> <Filter>Machine Independent\Preprocessor</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="glslang\MachineIndependent\limits.cpp">
<Filter>Machine Independent</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="glslang\MachineIndependent\Initialize.h"> <ClInclude Include="glslang\MachineIndependent\Initialize.h">

View File

@ -316,6 +316,7 @@ enum TOperator {
}; };
class TIntermTraverser; class TIntermTraverser;
class TIntermOperator;
class TIntermAggregate; class TIntermAggregate;
class TIntermUnary; class TIntermUnary;
class TIntermBinary; class TIntermBinary;
@ -342,16 +343,17 @@ public:
virtual glslang::TSourceLoc getLoc() const { return loc; } virtual glslang::TSourceLoc getLoc() const { return loc; }
virtual void setLoc(glslang::TSourceLoc l) { loc = l; } virtual void setLoc(glslang::TSourceLoc l) { loc = l; }
virtual void traverse(glslang::TIntermTraverser*) = 0; virtual void traverse(glslang::TIntermTraverser*) = 0;
virtual glslang::TIntermTyped* getAsTyped() { return 0; } virtual glslang::TIntermTyped* getAsTyped() { return 0; }
virtual glslang::TIntermConstantUnion* getAsConstantUnion() { return 0; } virtual glslang::TIntermOperator* getAsOperator() { return 0; }
virtual glslang::TIntermAggregate* getAsAggregate() { return 0; } virtual glslang::TIntermConstantUnion* getAsConstantUnion() { return 0; }
virtual glslang::TIntermUnary* getAsUnaryNode() { return 0; } virtual glslang::TIntermAggregate* getAsAggregate() { return 0; }
virtual glslang::TIntermBinary* getAsBinaryNode() { return 0; } virtual glslang::TIntermUnary* getAsUnaryNode() { return 0; }
virtual glslang::TIntermSelection* getAsSelectionNode() { return 0; } virtual glslang::TIntermBinary* getAsBinaryNode() { return 0; }
virtual glslang::TIntermSwitch* getAsSwitchNode() { return 0; } virtual glslang::TIntermSelection* getAsSelectionNode() { return 0; }
virtual glslang::TIntermMethod* getAsMethodNode() { return 0; } virtual glslang::TIntermSwitch* getAsSwitchNode() { return 0; }
virtual glslang::TIntermSymbol* getAsSymbolNode() { return 0; } virtual glslang::TIntermMethod* getAsMethodNode() { return 0; }
virtual glslang::TIntermBranch* getAsBranchNode() { return 0; } virtual glslang::TIntermSymbol* getAsSymbolNode() { return 0; }
virtual glslang::TIntermBranch* getAsBranchNode() { return 0; }
virtual ~TIntermNode() { } virtual ~TIntermNode() { }
protected: protected:
glslang::TSourceLoc loc; glslang::TSourceLoc loc;
@ -478,7 +480,7 @@ public:
TIntermConstantUnion(const TConstUnionArray& ua, const TType& t) : TIntermTyped(t), unionArray(ua) { } TIntermConstantUnion(const TConstUnionArray& ua, const TType& t) : TIntermTyped(t), unionArray(ua) { }
const TConstUnionArray& getConstArray() const { return unionArray; } const TConstUnionArray& getConstArray() const { return unionArray; }
virtual TIntermConstantUnion* getAsConstantUnion() { return this; } virtual TIntermConstantUnion* getAsConstantUnion() { return this; }
virtual void traverse(TIntermTraverser* ); virtual void traverse(TIntermTraverser*);
virtual TIntermTyped* fold(TOperator, TIntermTyped*); virtual TIntermTyped* fold(TOperator, TIntermTyped*);
virtual TIntermTyped* fold(TOperator, const TType&); virtual TIntermTyped* fold(TOperator, const TType&);
protected: protected:
@ -490,6 +492,7 @@ protected:
// //
class TIntermOperator : public TIntermTyped { class TIntermOperator : public TIntermTyped {
public: public:
TIntermOperator* getAsOperator() { return this; }
TOperator getOp() { return op; } TOperator getOp() { return op; }
bool modifiesState() const; bool modifiesState() const;
bool isConstructor() const; bool isConstructor() const;

View File

@ -713,9 +713,9 @@ TIntermTyped* TIntermediate::foldConstructor(TIntermAggregate* aggrNode)
TConstUnionArray unionArray(aggrNode->getType().getObjectSize()); TConstUnionArray unionArray(aggrNode->getType().getObjectSize());
if (aggrNode->getSequence().size() == 1) 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 else
error = parseConstTree(aggrNode->getLoc(), aggrNode, unionArray, aggrNode->getOp(), aggrNode->getType()); error = parseConstTree(aggrNode, unionArray, aggrNode->getOp(), aggrNode->getType());
if (error) if (error)
return aggrNode; return aggrNode;

View File

@ -809,11 +809,11 @@ TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, TSourceLoc loc)
// //
// Create loop nodes. // 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); node->setLoc(loc);
return node; return node;
} }

View File

@ -11,7 +11,7 @@ LIBCODEGEN=./../GenericCodeGen/libCodeGen.a
OBJECTS= Initialize.o IntermTraverse.o \ OBJECTS= Initialize.o IntermTraverse.o \
Intermediate.o ParseHelper.o PoolAlloc.o QualifierAlive.o \ Intermediate.o ParseHelper.o PoolAlloc.o QualifierAlive.o \
RemoveTree.o ShaderLang.o intermOut.o parseConst.o SymbolTable.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 \ SRCS= gen_glslang_tab.cpp Initialize.cpp IntermTraverse.cpp \
Intermediate.cpp ParseHelper.cpp PoolAlloc.cp QualifierAlive.cpp \ Intermediate.cpp ParseHelper.cpp PoolAlloc.cp QualifierAlive.cpp \
@ -146,3 +146,4 @@ parseConst.o: ../Public/ShaderLang.h
InfoSink.o: ../Include/InfoSink.h InfoSink.o: ../Include/InfoSink.h
Versions.o: ParseHelper.h Versions.h ../Include/ShHandle.h SymbolTable.h localintermediate.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 Constant.o: localintermediate.h ../Include/intermediate.h ../Public/ShaderLang.h SymbolTable.h Versions.h
limits.o: ParseHelper.h

View File

@ -154,8 +154,17 @@ bool TParseContext::parseShaderStrings(TPpContext& ppContext, char* strings[], s
return true; return true;
} }
anyIndexLimits = ! limits.generalAttributeMatrixVectorIndexing ||
! limits.generalConstantMatrixVectorIndexing ||
! limits.generalSamplerIndexing ||
! limits.generalUniformIndexing ||
! limits.generalVariableIndexing ||
! limits.generalVaryingIndexing;
yyparse((void*)this); yyparse((void*)this);
finalize();
return numErrors == 0; return numErrors == 0;
} }
@ -510,6 +519,23 @@ TIntermTyped* TParseContext::handleBracketDereference(TSourceLoc loc, TIntermTyp
newType.getQualifier().storage = EvqConst; newType.getQualifier().storage = EvqConst;
newType.dereference(); newType.dereference();
result->setType(newType); 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; return result;
@ -1914,6 +1940,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. // Layout qualifier stuff.
// //

View File

@ -53,6 +53,8 @@ struct TPragma {
class TScanContext; class TScanContext;
class TPpContext; class TPpContext;
typedef std::set<int> TIdSetType;
// //
// The following are extra variables needed during parsing, grouped together so // The following are extra variables needed during parsing, grouped together so
// they can be passed to the parser without needing a global. // they can be passed to the parser without needing a global.
@ -116,6 +118,9 @@ public:
void nestedBlockCheck(TSourceLoc); void nestedBlockCheck(TSourceLoc);
void nestedStructCheck(TSourceLoc); void nestedStructCheck(TSourceLoc);
void arrayObjectCheck(TSourceLoc, const TType&, const char* op); 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&);
void setLayoutQualifier(TSourceLoc, TPublicType&, TString&, int); void setLayoutQualifier(TSourceLoc, TPublicType&, TString&, int);
@ -167,6 +172,7 @@ protected:
void declareArray(TSourceLoc, TString& identifier, const TType&, TSymbol*&, bool& newDeclaration); void declareArray(TSourceLoc, TString& identifier, const TType&, TSymbol*&, bool& newDeclaration);
TIntermNode* executeInitializer(TSourceLoc, TString& identifier, TIntermTyped* initializer, TVariable* variable); TIntermNode* executeInitializer(TSourceLoc, TString& identifier, TIntermTyped* initializer, TVariable* variable);
TOperator mapTypeToConstructorOp(const TType&); TOperator mapTypeToConstructorOp(const TType&);
void finalize();
public: public:
// //
@ -213,6 +219,9 @@ protected:
TQualifier globalInputDefaults; TQualifier globalInputDefaults;
TQualifier globalOutputDefaults; TQualifier globalOutputDefaults;
TString currentCaller; TString currentCaller;
TIdSetType inductiveLoopIds;
bool anyIndexLimits;
TVector<TIntermTyped*> needsIndexLimitationChecking;
// TODO: desktop functionality: track use of gl_FragDepth before redeclaration // TODO: desktop functionality: track use of gl_FragDepth before redeclaration
}; };

View File

@ -2278,10 +2278,10 @@ iteration_statement
for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope { for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope {
parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]); parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]);
$$ = parseContext.intermediate.makeAggregate($4, $2.loc); $$ = parseContext.intermediate.makeAggregate($4, $2.loc);
$$ = parseContext.intermediate.growAggregate( TIntermLoop* forLoop = parseContext.intermediate.addLoop($7, reinterpret_cast<TIntermTyped*>($5.node1), reinterpret_cast<TIntermTyped*>($5.node2), true, $1.loc);
$$, if (! parseContext.limits.nonInductiveForLoops)
parseContext.intermediate.addLoop($7, reinterpret_cast<TIntermTyped*>($5.node1), reinterpret_cast<TIntermTyped*>($5.node2), true, $1.loc), parseContext.inductiveLoopCheck($1.loc, $4, forLoop);
$1.loc); $$ = parseContext.intermediate.growAggregate($$, forLoop, $1.loc);
$$->getAsAggregate()->setOperator(EOpSequence); $$->getAsAggregate()->setOperator(EOpSequence);
--parseContext.loopNestingLevel; --parseContext.loopNestingLevel;
} }

View File

@ -0,0 +1,199 @@
//
//Copyright (C) 2013 LunarG, Inc.
//
//All rights reserved.
//
//Redistribution and use in source and binary forms, with or without
//modification, are permitted provided that the following conditions
//are met:
//
// Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
//
// Neither the name of 3Dlabs Inc. Ltd. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
//COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
//LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
//POSSIBILITY OF SUCH DAMAGE.
//
//
// Do sub tree walks for
// 1) inductive loop bodies to see if the inductive variable is modified
// 2) array-index expressions to see if they are "constant-index-expression"
//
// These are per Appendix A of ES 2.0:
//
// "Within the body of the loop, the loop index is not statically assigned to nor is it used as the
// argument to a function out or inout parameter."
//
// "The following are constant-index-expressions:
// - Constant expressions
// - Loop indices as defined in section 4
// - Expressions composed of both of the above"
//
// N.B.: assuming the last rule excludes function calls
//
#include "ParseHelper.h"
namespace glslang {
//
// The inductive loop-body traverser.
//
// Just look at things that might modify the loop index.
//
class TInductiveTraverser : public TIntermTraverser {
public:
TInductiveTraverser(int id, TSymbolTable& st) : loopId(id), symbolTable(st), bad(false) { }
int loopId; // unique ID of the symbol that's the loop inductive variable
TSymbolTable& symbolTable;
bool bad;
TSourceLoc badLoc;
};
// check binary operations for those modifying the loop index
bool InductiveBinary(bool /* preVisit */, TIntermBinary* node, TIntermTraverser* it)
{
TInductiveTraverser* oit = static_cast<TInductiveTraverser*>(it);
if (node->modifiesState() && node->getLeft()->getAsSymbolNode() &&
node->getLeft()->getAsSymbolNode()->getId() == oit->loopId) {
oit->bad = true;
oit->badLoc = node->getLoc();
}
return true;
}
// check unary operations for those modifying the loop index
bool InductiveUnary(bool /* preVisit */, TIntermUnary* node, TIntermTraverser* it)
{
TInductiveTraverser* oit = static_cast<TInductiveTraverser*>(it);
if (node->modifiesState() && node->getOperand()->getAsSymbolNode() &&
node->getOperand()->getAsSymbolNode()->getId() == oit->loopId) {
oit->bad = true;
oit->badLoc = node->getLoc();
}
return true;
}
// check function calls for arguments modifying the loop index
bool InductiveAggregate(bool /* preVisit */, TIntermAggregate* node, TIntermTraverser* it)
{
TInductiveTraverser* oit = static_cast<TInductiveTraverser*>(it);
if (node->getOp() == EOpFunctionCall) {
// see if an out or inout argument is the loop index
const TIntermSequence& args = node->getSequence();
for (size_t i = 0; i < args.size(); ++i) {
if (args[i]->getAsSymbolNode() && args[i]->getAsSymbolNode()->getId() == oit->loopId) {
TSymbol* function = oit->symbolTable.find(node->getName());
const TType* type = (*function->getAsFunction())[i].type;
if (type->getQualifier().storage == EvqOut ||
type->getQualifier().storage == EvqInOut) {
oit->bad = true;
oit->badLoc = node->getLoc();
}
}
}
}
return true;
}
//
// External function to call for loop check.
//
void TParseContext::inductiveLoopBodyCheck(TIntermNode* body, int loopId, TSymbolTable& symbolTable)
{
TInductiveTraverser it(loopId, symbolTable);
if (! body)
return;
it.visitAggregate = InductiveAggregate;
it.visitBinary = InductiveBinary;
it.visitUnary = InductiveUnary;
body->traverse(&it);
if (it.bad)
error(it.badLoc, "inductive loop index modified", "limitations", "");
}
//
// The "constant-index-expression" tranverser.
//
// Just look at things that can form an index.
//
class TIndexTraverser : public TIntermTraverser {
public:
TIndexTraverser(const TIdSetType& ids) : inductiveLoopIds(ids), bad(false) { }
const TIdSetType& inductiveLoopIds;
bool bad;
TSourceLoc badLoc;
};
// make sure symbols are inductive-loop indexes
void IndexSymbol(TIntermSymbol* symbol, TIntermTraverser* it)
{
TIndexTraverser* oit = static_cast<TIndexTraverser*>(it);
if (oit->inductiveLoopIds.find(symbol->getId()) == oit->inductiveLoopIds.end()) {
oit->bad = true;
oit->badLoc = symbol->getLoc();
}
}
// check for function calls, assuming they are bad; spec. doesn't really say
bool IndexAggregate(bool /* preVisit */, TIntermAggregate* node, TIntermTraverser* it)
{
TIndexTraverser* oit = static_cast<TIndexTraverser*>(it);
if (node->getOp() == EOpFunctionCall) {
oit->bad = true;
oit->badLoc = node->getLoc();
}
return true;
}
//
// External function to call for loop check.
//
void TParseContext::constantIndexExpressionCheck(TIntermNode* index)
{
TIndexTraverser it(inductiveLoopIds);
it.visitSymbol = IndexSymbol;
it.visitAggregate = IndexAggregate;
index->traverse(&it);
if (it.bad)
error(it.badLoc, "Non-constant-index-expression", "limitations", "");
}
} // end namespace glslang

View File

@ -89,8 +89,8 @@ public:
TIntermTyped* addMethod(TIntermTyped*, const TType&, const TString*, TSourceLoc); TIntermTyped* addMethod(TIntermTyped*, const TType&, const TString*, TSourceLoc);
TIntermConstantUnion* addConstantUnion(const TConstUnionArray&, const TType&, TSourceLoc); TIntermConstantUnion* addConstantUnion(const TConstUnionArray&, const TType&, TSourceLoc);
TIntermTyped* promoteConstantUnion(TBasicType, TIntermConstantUnion*) ; TIntermTyped* promoteConstantUnion(TBasicType, TIntermConstantUnion*) ;
bool parseConstTree(TSourceLoc, TIntermNode*, TConstUnionArray, TOperator, const TType&, bool singleConstantParam = false); bool parseConstTree(TIntermNode*, TConstUnionArray, TOperator, const TType&, bool singleConstantParam = false);
TIntermNode* addLoop(TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, TSourceLoc); TIntermLoop* addLoop(TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, TSourceLoc);
TIntermBranch* addBranch(TOperator, TSourceLoc); TIntermBranch* addBranch(TOperator, TSourceLoc);
TIntermBranch* addBranch(TOperator, TIntermTyped*, TSourceLoc); TIntermBranch* addBranch(TOperator, TIntermTyped*, TSourceLoc);
TIntermTyped* addSwizzle(TVectorFields&, TSourceLoc); TIntermTyped* addSwizzle(TVectorFields&, TSourceLoc);

View File

@ -45,7 +45,7 @@ class TConstTraverser : public TIntermTraverser {
public: public:
TConstTraverser(const TConstUnionArray& cUnion, bool singleConstParam, TOperator constructType, const TType& t) : unionArray(cUnion), type(t), TConstTraverser(const TConstUnionArray& cUnion, bool singleConstParam, TOperator constructType, const TType& t) : unionArray(cUnion), type(t),
constructorType(constructType), singleConstantParam(singleConstParam), error(false), isMatrix(false), 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; int index;
TConstUnionArray unionArray; TConstUnionArray unionArray;
TOperator tOp; 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) if (root == 0)
return false; return false;