From 27b72e42c3d5a160b098b8d841f56a74cb11383b Mon Sep 17 00:00:00 2001 From: John Kessenich Date: Mon, 14 Oct 2013 22:42:16 +0000 Subject: [PATCH] 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 --- Test/100Limits.vert | 55 ++- Test/baseResults/100Limits.vert.out | 600 +++++++++++++++++-------- Test/baseResults/100LimitsConf.vert.out | 24 +- glslang.vcxproj | 1 + glslang.vcxproj.filters | 3 + glslang/Include/intermediate.h | 25 +- glslang/MachineIndependent/Constant.cpp | 4 +- glslang/MachineIndependent/Intermediate.cpp | 6 +- glslang/MachineIndependent/Makefile | 3 +- glslang/MachineIndependent/ParseHelper.cpp | 153 +++++++ glslang/MachineIndependent/ParseHelper.h | 9 + glslang/MachineIndependent/glslang.y | 8 +- glslang/MachineIndependent/limits.cpp | 199 ++++++++ glslang/MachineIndependent/localintermediate.h | 4 +- glslang/MachineIndependent/parseConst.cpp | 4 +- 15 files changed, 857 insertions(+), 241 deletions(-) create mode 100644 glslang/MachineIndependent/limits.cpp diff --git a/Test/100Limits.vert b/Test/100Limits.vert index 7ed1ef8..d23b7e8 100644 --- a/Test/100Limits.vert +++ b/Test/100Limits.vert @@ -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]; - - for ( int a = 3; a >= 0; --a) { + 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--) { 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]; } diff --git a/Test/baseResults/100Limits.vert.out b/Test/baseResults/100Limits.vert.out index fe68fd5..4ee83d1 100644 --- a/Test/baseResults/100Limits.vert.out +++ b/Test/baseResults/100Limits.vert.out @@ -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: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: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 Loop with condition tested first +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:26 Loop with condition not tested first +0:26 Loop Condition +0:26 Constant: +0:26 false (const bool) +0:26 No loop body 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: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:38 Constant: -0:38 1.000000 -0:38 0.000000 -0:38 0.000000 -0:38 1.000000 -0:38 'ga' (highp int) -0:39 indirect index (const 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: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: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 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) diff --git a/Test/baseResults/100LimitsConf.vert.out b/Test/baseResults/100LimitsConf.vert.out index 0d51c81..1a87ea8 100644 --- a/Test/baseResults/100LimitsConf.vert.out +++ b/Test/baseResults/100LimitsConf.vert.out @@ -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 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. diff --git a/glslang.vcxproj b/glslang.vcxproj index dd6f5bb..f54d85d 100644 --- a/glslang.vcxproj +++ b/glslang.vcxproj @@ -156,6 +156,7 @@ xcopy /y $(IntDir)$(TargetName)$(TargetExt) Test + diff --git a/glslang.vcxproj.filters b/glslang.vcxproj.filters index 8e98fe6..9f12741 100644 --- a/glslang.vcxproj.filters +++ b/glslang.vcxproj.filters @@ -109,6 +109,9 @@ Machine Independent\Preprocessor + + Machine Independent + diff --git a/glslang/Include/intermediate.h b/glslang/Include/intermediate.h index 549ec86..a1e012e 100644 --- a/glslang/Include/intermediate.h +++ b/glslang/Include/intermediate.h @@ -316,6 +316,7 @@ enum TOperator { }; class TIntermTraverser; +class TIntermOperator; class TIntermAggregate; class TIntermUnary; class TIntermBinary; @@ -342,16 +343,17 @@ public: virtual glslang::TSourceLoc getLoc() const { return loc; } virtual void setLoc(glslang::TSourceLoc l) { loc = l; } virtual void traverse(glslang::TIntermTraverser*) = 0; - virtual glslang::TIntermTyped* getAsTyped() { return 0; } - virtual glslang::TIntermConstantUnion* getAsConstantUnion() { return 0; } - virtual glslang::TIntermAggregate* getAsAggregate() { return 0; } - virtual glslang::TIntermUnary* getAsUnaryNode() { return 0; } - virtual glslang::TIntermBinary* getAsBinaryNode() { return 0; } - virtual glslang::TIntermSelection* getAsSelectionNode() { return 0; } - virtual glslang::TIntermSwitch* getAsSwitchNode() { return 0; } - virtual glslang::TIntermMethod* getAsMethodNode() { return 0; } - virtual glslang::TIntermSymbol* getAsSymbolNode() { return 0; } - virtual glslang::TIntermBranch* getAsBranchNode() { return 0; } + virtual glslang::TIntermTyped* getAsTyped() { return 0; } + virtual glslang::TIntermOperator* getAsOperator() { return 0; } + virtual glslang::TIntermConstantUnion* getAsConstantUnion() { return 0; } + virtual glslang::TIntermAggregate* getAsAggregate() { return 0; } + virtual glslang::TIntermUnary* getAsUnaryNode() { return 0; } + virtual glslang::TIntermBinary* getAsBinaryNode() { return 0; } + virtual glslang::TIntermSelection* getAsSelectionNode() { return 0; } + virtual glslang::TIntermSwitch* getAsSwitchNode() { return 0; } + virtual glslang::TIntermMethod* getAsMethodNode() { return 0; } + virtual glslang::TIntermSymbol* getAsSymbolNode() { return 0; } + virtual glslang::TIntermBranch* getAsBranchNode() { return 0; } virtual ~TIntermNode() { } protected: glslang::TSourceLoc loc; @@ -478,7 +480,7 @@ public: TIntermConstantUnion(const TConstUnionArray& ua, const TType& t) : TIntermTyped(t), unionArray(ua) { } const TConstUnionArray& getConstArray() const { return unionArray; } virtual TIntermConstantUnion* getAsConstantUnion() { return this; } - virtual void traverse(TIntermTraverser* ); + virtual void traverse(TIntermTraverser*); virtual TIntermTyped* fold(TOperator, TIntermTyped*); virtual TIntermTyped* fold(TOperator, const TType&); protected: @@ -490,6 +492,7 @@ protected: // class TIntermOperator : public TIntermTyped { public: + TIntermOperator* getAsOperator() { return this; } TOperator getOp() { return op; } bool modifiesState() const; bool isConstructor() const; diff --git a/glslang/MachineIndependent/Constant.cpp b/glslang/MachineIndependent/Constant.cpp index 218fe94..3559a92 100644 --- a/glslang/MachineIndependent/Constant.cpp +++ b/glslang/MachineIndependent/Constant.cpp @@ -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; diff --git a/glslang/MachineIndependent/Intermediate.cpp b/glslang/MachineIndependent/Intermediate.cpp index 9c18414..0088dcd 100644 --- a/glslang/MachineIndependent/Intermediate.cpp +++ b/glslang/MachineIndependent/Intermediate.cpp @@ -809,11 +809,11 @@ TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, TSourceLoc loc) // // Create loop nodes. // -TIntermNode* TIntermediate::addLoop(TIntermNode* body, TIntermTyped* test, TIntermTyped* terminal, bool testFirst, TSourceLoc loc) +TIntermLoop* TIntermediate::addLoop(TIntermNode* body, TIntermTyped* test, TIntermTyped* terminal, bool testFirst, TSourceLoc loc) { - TIntermNode* node = new TIntermLoop(body, test, terminal, testFirst); + TIntermLoop* node = new TIntermLoop(body, test, terminal, testFirst); node->setLoc(loc); - + return node; } diff --git a/glslang/MachineIndependent/Makefile b/glslang/MachineIndependent/Makefile index 2ed8365..1b6c404 100644 --- a/glslang/MachineIndependent/Makefile +++ b/glslang/MachineIndependent/Makefile @@ -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 diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index b0de06a..6fb2c8d 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -154,8 +154,17 @@ bool TParseContext::parseShaderStrings(TPpContext& ppContext, char* strings[], s return true; } + anyIndexLimits = ! limits.generalAttributeMatrixVectorIndexing || + ! limits.generalConstantMatrixVectorIndexing || + ! limits.generalSamplerIndexing || + ! limits.generalUniformIndexing || + ! limits.generalVariableIndexing || + ! limits.generalVaryingIndexing; + yyparse((void*)this); + finalize(); + return numErrors == 0; } @@ -510,6 +519,23 @@ TIntermTyped* TParseContext::handleBracketDereference(TSourceLoc loc, TIntermTyp newType.getQualifier().storage = EvqConst; newType.dereference(); result->setType(newType); + + if (anyIndexLimits) { + // for ES 2.0 (version 100) limitations for almost all index operations except vertex-shader uniforms + if ((! limits.generalSamplerIndexing && base->getBasicType() == EbtSampler) || + (! limits.generalUniformIndexing && base->getQualifier().isUniform() && language != EShLangVertex) || + (! limits.generalAttributeMatrixVectorIndexing && base->getQualifier().isPipeInput() && language == EShLangVertex && (base->getType().isMatrix() || base->getType().isVector())) || + (! limits.generalConstantMatrixVectorIndexing && base->getAsConstantUnion()) || + (! limits.generalVariableIndexing && ! base->getType().getQualifier().isUniform() && + ! base->getType().getQualifier().isPipeInput() && + ! base->getType().getQualifier().isPipeOutput() && + base->getType().getQualifier().storage != EvqConst) || + (! limits.generalVaryingIndexing && (base->getType().getQualifier().isPipeInput() || + base->getType().getQualifier().isPipeOutput()))) { + // it's too early to know what the inductive variables are, save it for post processing + needsIndexLimitationChecking.push_back(index); + } + } } return result; @@ -1915,6 +1941,133 @@ void TParseContext::arrayObjectCheck(TSourceLoc loc, const TType& type, const ch } // +// See if this loop satisfies the limitations for ES 2.0 (version 100) for loops in Appendex A: +// +// "The loop index has type int or float. +// +// "The for statement has the form: +// for ( init-declaration ; condition ; expression ) +// init-declaration has the form: type-specifier identifier = constant-expression +// condition has the form: loop-index relational_operator constant-expression +// where relational_operator is one of: > >= < <= == or != +// expression [sic] has one of the following forms: +// loop-index++ +// loop-index-- +// loop-index += constant-expression +// loop-index -= constant-expression +// +// The body is handled in an AST traversal. +// +void TParseContext::inductiveLoopCheck(TSourceLoc loc, TIntermNode* init, TIntermLoop* loop) +{ + // loop index init must exist and be a declaration, which shows up in the AST as an aggregate of size 1 of the declaration + bool badInit = false; + if (! init || ! init->getAsAggregate() || ! init->getAsAggregate()->getSequence().size() == 1) + badInit = true; + TIntermBinary* binaryInit; + if (! badInit) { + // get the declaration assignment + binaryInit = init->getAsAggregate()->getSequence()[0]->getAsBinaryNode(); + if (! binaryInit) + badInit = true; + } + if (badInit) { + error(loc, "inductive-loop init-declaration requires the form \"type-specifier loop-index = constant-expression\"", "limitations", ""); + return; + } + + // loop index must be type int or float + if (! binaryInit->getType().isScalar() || (binaryInit->getBasicType() != EbtInt && binaryInit->getBasicType() != EbtFloat)) { + error(loc, "inductive loop requires a scalar 'int' or 'float' loop index", "limitations", ""); + return; + } + + // init is the form "loop-index = constant" + if (binaryInit->getOp() != EOpAssign || ! binaryInit->getLeft()->getAsSymbolNode() || ! binaryInit->getRight()->getAsConstantUnion()) { + error(loc, "inductive-loop init-declaration requires the form \"type-specifier loop-index = constant-expression\"", "limitations", ""); + return; + } + + // get the unique id of the loop index + int loopIndex = binaryInit->getLeft()->getAsSymbolNode()->getId(); + inductiveLoopIds.insert(loopIndex); + + // condition's form must be "loop-index relational-operator constant-expression" + bool badCond = ! loop->getTest(); + if (! badCond) { + TIntermBinary* binaryCond = loop->getTest()->getAsBinaryNode(); + badCond = ! binaryCond; + if (! badCond) { + switch (binaryCond->getOp()) { + case EOpGreaterThan: + case EOpGreaterThanEqual: + case EOpLessThan: + case EOpLessThanEqual: + case EOpEqual: + case EOpNotEqual: + break; + default: + badCond = true; + } + } + if (binaryCond && (! binaryCond->getLeft()->getAsSymbolNode() || + binaryCond->getLeft()->getAsSymbolNode()->getId() != loopIndex || + ! binaryCond->getRight()->getAsConstantUnion())) + badCond = true; + } + if (badCond) { + error(loc, "inductive-loop condition requires the form \"loop-index 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. // diff --git a/glslang/MachineIndependent/ParseHelper.h b/glslang/MachineIndependent/ParseHelper.h index 57b99b8..4e8d7d8 100644 --- a/glslang/MachineIndependent/ParseHelper.h +++ b/glslang/MachineIndependent/ParseHelper.h @@ -53,6 +53,8 @@ struct TPragma { class TScanContext; class TPpContext; +typedef std::set 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 needsIndexLimitationChecking; // TODO: desktop functionality: track use of gl_FragDepth before redeclaration }; diff --git a/glslang/MachineIndependent/glslang.y b/glslang/MachineIndependent/glslang.y index 460742d..e9a4b37 100644 --- a/glslang/MachineIndependent/glslang.y +++ b/glslang/MachineIndependent/glslang.y @@ -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($5.node1), reinterpret_cast($5.node2), true, $1.loc), - $1.loc); + TIntermLoop* forLoop = parseContext.intermediate.addLoop($7, reinterpret_cast($5.node1), reinterpret_cast($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; } diff --git a/glslang/MachineIndependent/limits.cpp b/glslang/MachineIndependent/limits.cpp new file mode 100644 index 0000000..0c660a8 --- /dev/null +++ b/glslang/MachineIndependent/limits.cpp @@ -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(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(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(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(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(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 diff --git a/glslang/MachineIndependent/localintermediate.h b/glslang/MachineIndependent/localintermediate.h index b8c3727..f038211 100644 --- a/glslang/MachineIndependent/localintermediate.h +++ b/glslang/MachineIndependent/localintermediate.h @@ -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); diff --git a/glslang/MachineIndependent/parseConst.cpp b/glslang/MachineIndependent/parseConst.cpp index e77b96f..872607b 100644 --- a/glslang/MachineIndependent/parseConst.cpp +++ b/glslang/MachineIndependent/parseConst.cpp @@ -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; -- 2.7.4