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:
parent
a4ea1313c3
commit
27b72e42c3
@ -14,32 +14,46 @@ const vec3 v3 = vec3(2.0);
|
||||
|
||||
void foo(inout float a) {}
|
||||
|
||||
int bar()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
while (ga < gb) { }
|
||||
|
||||
do { } while (false);
|
||||
|
||||
for ( ga = 0; ; );
|
||||
for ( bool a = false; ; );
|
||||
for (float a = 0.0; a == sin(f); );
|
||||
for ( int a = 0; a < 10; a *= 2);
|
||||
for ( int a = 0; a <= 20; ++a) --a;
|
||||
for ( ; ; ); // ERROR
|
||||
for ( ; ga==gb; ); // ERROR
|
||||
for ( ; ; f++); // ERROR
|
||||
for ( ga = 0; ; ); // ERROR
|
||||
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) 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];
|
||||
|
||||
fsa[ga];
|
||||
fsa[ga]; // ERROR
|
||||
fua[ga];
|
||||
am3[ga];
|
||||
av2[ga];
|
||||
va[ga];
|
||||
m2[ga];
|
||||
v3[ga];
|
||||
ia[ga];
|
||||
am3[ga]; // ERROR
|
||||
av2[ga]; // ERROR
|
||||
va[2+ga]; // ERROR
|
||||
m2[ga]; // ERROR
|
||||
v3[ga/2]; // ERROR
|
||||
ia[ga]; // ERROR
|
||||
|
||||
for ( int a = 3; a >= 0; --a) {
|
||||
for (int a = 3; a >= 0; a--) {
|
||||
fsa[a];
|
||||
fua[a+2];
|
||||
am3[3*a];
|
||||
@ -48,6 +62,15 @@ void main()
|
||||
m2[a/2];
|
||||
v3[a];
|
||||
ia[a];
|
||||
ia[bar()]; // ERROR
|
||||
}
|
||||
|
||||
fsa[2];
|
||||
fua[3];
|
||||
am3[2];
|
||||
av2[1];
|
||||
va[1];
|
||||
m2[1];
|
||||
v3[1];
|
||||
ia[3];
|
||||
}
|
||||
|
@ -2,218 +2,424 @@
|
||||
0:15 Function Definition: foo(f1; (void)
|
||||
0:15 Function Parameters:
|
||||
0:15 'a' (inout highp float)
|
||||
0:17 Function Definition: main( (void)
|
||||
0:17 Function Definition: bar( (highp int)
|
||||
0:17 Function Parameters:
|
||||
0:19 Sequence
|
||||
0:19 Loop with condition tested first
|
||||
0:19 Loop Condition
|
||||
0:19 Compare Less Than (bool)
|
||||
0:19 'ga' (highp int)
|
||||
0:19 'gb' (highp int)
|
||||
0:19 No loop body
|
||||
0:21 Loop with condition not tested first
|
||||
0:21 Loop Condition
|
||||
0:21 Constant:
|
||||
0:21 false (const bool)
|
||||
0:21 No loop body
|
||||
0:23 Sequence
|
||||
0:23 move second child to first child (highp int)
|
||||
0:23 'ga' (highp int)
|
||||
0:23 Constant:
|
||||
0:23 0 (const int)
|
||||
0:23 Loop with condition tested first
|
||||
0:23 No loop condition
|
||||
0:23 No loop body
|
||||
0:19 Branch: Return with expression
|
||||
0:19 Constant:
|
||||
0:19 1 (const int)
|
||||
0:22 Function Definition: main( (void)
|
||||
0:22 Function Parameters:
|
||||
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 Loop Condition
|
||||
0:24 Compare Less Than (bool)
|
||||
0:24 'ga' (highp int)
|
||||
0:24 'gb' (highp int)
|
||||
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 with condition not 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 false (const bool)
|
||||
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 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 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 condition
|
||||
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 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 Condition
|
||||
0:29 Compare Less Than or Equal (bool)
|
||||
0:29 'a' (highp float)
|
||||
0:29 Constant:
|
||||
0:29 20.000000
|
||||
0:29 Loop Body
|
||||
0:29 Function Call: foo(f1; (void)
|
||||
0:29 'a' (highp float)
|
||||
0:29 Loop Terminal Expression
|
||||
0:29 add second child into first child (highp float)
|
||||
0:29 'a' (highp float)
|
||||
0:29 Constant:
|
||||
0:29 2.000000
|
||||
0:33 indirect index (uniform lowp sampler2D)
|
||||
0:33 'fsa' (uniform 3-element array of lowp sampler2D)
|
||||
0:33 'ga' (highp int)
|
||||
0:34 indirect index (uniform highp float)
|
||||
0:34 'fua' (uniform 10-element array of highp float)
|
||||
0:34 'ga' (highp int)
|
||||
0:35 indirect index (in highp 3-component vector of float)
|
||||
0:35 'am3' (in highp 3X3 matrix of float)
|
||||
0:35 'ga' (highp int)
|
||||
0:36 indirect index (in highp float)
|
||||
0:36 'av2' (in highp 2-component vector of float)
|
||||
0:29 Compare Equal (bool)
|
||||
0:29 'ga' (highp int)
|
||||
0:29 'gb' (highp int)
|
||||
0:29 No loop body
|
||||
0:30 Sequence
|
||||
0:30 Loop with condition tested first
|
||||
0:30 No loop condition
|
||||
0:30 No loop body
|
||||
0:30 Loop Terminal Expression
|
||||
0:30 Post-Increment (highp float)
|
||||
0:30 'f' (highp float)
|
||||
0:31 Sequence
|
||||
0:31 move second child to first child (highp int)
|
||||
0:31 'ga' (highp int)
|
||||
0:31 Constant:
|
||||
0:31 0 (const int)
|
||||
0:31 Loop with condition tested first
|
||||
0:31 No loop condition
|
||||
0:31 No loop body
|
||||
0:32 Sequence
|
||||
0:32 Sequence
|
||||
0:32 move second child to first child (bool)
|
||||
0:32 'a' (bool)
|
||||
0:32 Constant:
|
||||
0:32 false (const bool)
|
||||
0:32 Loop with condition tested first
|
||||
0:32 No loop condition
|
||||
0:32 No loop body
|
||||
0:33 Sequence
|
||||
0:33 Sequence
|
||||
0:33 move second child to first child (highp float)
|
||||
0:33 'a' (highp float)
|
||||
0:33 Constant:
|
||||
0:33 0.000000
|
||||
0:33 Loop with condition tested first
|
||||
0:33 Loop Condition
|
||||
0:33 Compare Equal (bool)
|
||||
0:33 'a' (highp float)
|
||||
0:33 sine (highp float)
|
||||
0:33 'f' (highp float)
|
||||
0:33 No loop body
|
||||
0:34 Sequence
|
||||
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:37 indirect index (smooth out highp 4-component vector of float)
|
||||
0:37 'va' (smooth out 4-element array of highp 4-component vector of float)
|
||||
0:37 'ga' (highp int)
|
||||
0:38 indirect index (const highp 2-component vector of float)
|
||||
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 1.000000
|
||||
0:38 0.000000
|
||||
0:38 0.000000
|
||||
0:38 1.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:39 indirect index (const highp float)
|
||||
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 2.000000
|
||||
0:39 2.000000
|
||||
0:39 2.000000
|
||||
0:39 'ga' (highp int)
|
||||
0:40 indirect index (highp int)
|
||||
0:40 'ia' (9-element array of highp int)
|
||||
0:40 'ga' (highp int)
|
||||
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 move second child to first child (highp int)
|
||||
0:42 'a' (highp int)
|
||||
0:42 move second child to first child (highp float)
|
||||
0:42 'a' (highp float)
|
||||
0:42 Constant:
|
||||
0:42 3 (const int)
|
||||
0:42 0.000000
|
||||
0:42 Loop with condition tested first
|
||||
0:42 Loop Condition
|
||||
0:42 Compare Greater Than or Equal (bool)
|
||||
0:42 'a' (highp int)
|
||||
0:42 Compare Greater Than (bool)
|
||||
0:42 'a' (highp float)
|
||||
0:42 Constant:
|
||||
0:42 0 (const int)
|
||||
0:42 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 40.000000
|
||||
0:42 No loop body
|
||||
0:42 Loop Terminal Expression
|
||||
0:42 Pre-Decrement (highp int)
|
||||
0:42 'a' (highp int)
|
||||
0:42 add second child into first child (highp float)
|
||||
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:? 'ga' (highp int)
|
||||
0:? 'gb' (highp int)
|
||||
|
@ -1,5 +1,23 @@
|
||||
ERROR: 0:19: 'limitation' : while loops not available
|
||||
ERROR: 0:21: 'limitation' : do-while loops not available
|
||||
ERROR: 2 compilation errors. No code generated.
|
||||
ERROR: 0:24: 'limitation' : while loops not available
|
||||
ERROR: 0:26: 'limitation' : do-while loops not available
|
||||
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.
|
||||
|
||||
|
||||
|
@ -156,6 +156,7 @@ xcopy /y $(IntDir)$(TargetName)$(TargetExt) Test</Command>
|
||||
</ClCompile>
|
||||
<ClCompile Include="glslang\MachineIndependent\InfoSink.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\PpAtom.cpp" />
|
||||
<ClCompile Include="glslang\MachineIndependent\preprocessor\PpMemory.cpp" />
|
||||
|
@ -109,6 +109,9 @@
|
||||
<ClCompile Include="glslang\MachineIndependent\preprocessor\PpContext.cpp">
|
||||
<Filter>Machine Independent\Preprocessor</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="glslang\MachineIndependent\limits.cpp">
|
||||
<Filter>Machine Independent</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="glslang\MachineIndependent\Initialize.h">
|
||||
|
@ -316,6 +316,7 @@ enum TOperator {
|
||||
};
|
||||
|
||||
class TIntermTraverser;
|
||||
class TIntermOperator;
|
||||
class TIntermAggregate;
|
||||
class TIntermUnary;
|
||||
class TIntermBinary;
|
||||
@ -343,6 +344,7 @@ public:
|
||||
virtual void setLoc(glslang::TSourceLoc l) { loc = l; }
|
||||
virtual void traverse(glslang::TIntermTraverser*) = 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; }
|
||||
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -809,9 +809,9 @@ 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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
@ -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.
|
||||
//
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
|
@ -2278,10 +2278,10 @@ iteration_statement
|
||||
for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope {
|
||||
parseContext.symbolTable.pop(&parseContext.defaultPrecision[0]);
|
||||
$$ = parseContext.intermediate.makeAggregate($4, $2.loc);
|
||||
$$ = parseContext.intermediate.growAggregate(
|
||||
$$,
|
||||
parseContext.intermediate.addLoop($7, reinterpret_cast<TIntermTyped*>($5.node1), reinterpret_cast<TIntermTyped*>($5.node2), true, $1.loc),
|
||||
$1.loc);
|
||||
TIntermLoop* forLoop = parseContext.intermediate.addLoop($7, reinterpret_cast<TIntermTyped*>($5.node1), reinterpret_cast<TIntermTyped*>($5.node2), true, $1.loc);
|
||||
if (! parseContext.limits.nonInductiveForLoops)
|
||||
parseContext.inductiveLoopCheck($1.loc, $4, forLoop);
|
||||
$$ = parseContext.intermediate.growAggregate($$, forLoop, $1.loc);
|
||||
$$->getAsAggregate()->setOperator(EOpSequence);
|
||||
--parseContext.loopNestingLevel;
|
||||
}
|
||||
|
199
glslang/MachineIndependent/limits.cpp
Normal file
199
glslang/MachineIndependent/limits.cpp
Normal 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
|
@ -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);
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user