From: John Kessenich Date: Tue, 24 Sep 2013 21:18:46 +0000 (+0000) Subject: Add basic intra-stage linking validation for matching types and qualification of... X-Git-Tag: upstream/0.1~917 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=337dbc7d8c2f9290704c4ba77be2b215329b2fac;p=platform%2Fupstream%2Fglslang.git Add basic intra-stage linking validation for matching types and qualification of uniforms/ins/outs/globals, function body duplication, and mixing ES/non-ES shaders. Still need to handle arrays and built-in redeclarations, and many more rules, but this puts the basics in place. git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@23225 e7fa87d3-cd2b-0410-9028-fcbf551c1848 --- diff --git a/Test/baseResults/120.frag.out b/Test/baseResults/120.frag.out index 49efdfc..bbcda69 100644 --- a/Test/baseResults/120.frag.out +++ b/Test/baseResults/120.frag.out @@ -281,9 +281,15 @@ ERROR: node is still EOpNull! 0:121 'gl_TexCoord' (smooth in unsized array of 4-component vector of float) 0:121 3 (const int) 0:? Linker Objects +0:? 'lowp' (float) +0:? 'mediump' (float) +0:? 'highp' (float) +0:? 'precision' (float) 0:? 'i' (smooth in 4-component vector of float) 0:? 'o' (out 4-component vector of float) 0:? 's2D' (uniform sampler2D) 0:? 'centTexCoord' (centroid smooth in 2-component vector of float) 0:? 'm' (uniform 4X2 matrix of float) +0:? 'imageBuffer' (float) +0:? 'uimage2DRect' (float) diff --git a/Test/baseResults/300.vert.out b/Test/baseResults/300.vert.out index 550b748..567be86 100644 --- a/Test/baseResults/300.vert.out +++ b/Test/baseResults/300.vert.out @@ -134,6 +134,7 @@ ERROR: node is still EOpNull! 0:? 'rep2' (centroid smooth sample out highp 4-component vector of float) 0:? 'rep3' (in highp 4-component vector of float) 0:? 's' (smooth out structure) +0:? 'badsize2' (unsized array of highp float) 0:? 'ubInst' (layout(shared ) uniform unsized array of block) 0:? 'gl_VertexID' (gl_VertexId highp int) 0:? 'gl_InstanceID' (gl_InstanceId highp int) diff --git a/Test/baseResults/300BuiltIns.frag.out b/Test/baseResults/300BuiltIns.frag.out index 0fb1a81..91b0218 100644 --- a/Test/baseResults/300BuiltIns.frag.out +++ b/Test/baseResults/300BuiltIns.frag.out @@ -181,4 +181,25 @@ ERROR: node is still EOpNull! 0:67 unpackHalf2x16 (mediump 2-component vector of float) 0:67 'uy' (mediump uint) 0:70 0.000000 +0:? Linker Objects +0:? 'imax' (mediump int) +0:? 'imin' (mediump int) +0:? 'umax' (mediump uint) +0:? 'umin' (mediump uint) +0:? 'x' (mediump 3-component vector of float) +0:? 'y' (mediump 3-component vector of float) +0:? 'bv' (3-component vector of bool) +0:? 'uy' (mediump uint) +0:? 'uv2c' (mediump 2-component vector of uint) +0:? 'uv2y' (mediump 2-component vector of uint) +0:? 'uv2x' (mediump 2-component vector of uint) +0:? 'uv4y' (mediump 4-component vector of uint) +0:? 'iv3a' (mediump 3-component vector of int) +0:? 'iv3b' (mediump 3-component vector of int) +0:? 'iv4a' (mediump 4-component vector of int) +0:? 'iv4b' (mediump 4-component vector of int) +0:? 'f' (mediump float) +0:? 'v2a' (mediump 2-component vector of float) +0:? 'v2b' (mediump 2-component vector of float) +0:? 'v4' (mediump 4-component vector of float) diff --git a/Test/baseResults/300operations.frag.out b/Test/baseResults/300operations.frag.out index effb530..a679ca0 100644 --- a/Test/baseResults/300operations.frag.out +++ b/Test/baseResults/300operations.frag.out @@ -199,4 +199,5 @@ ERROR: node is still EOpNull! 0:127 'iv3' (mediump 3-component vector of int) 0:? Linker Objects 0:? 'instanceName' (layout(shared ) uniform block) +0:? 's' (structure) diff --git a/Test/baseResults/300scope.vert.out b/Test/baseResults/300scope.vert.out index 2eef9be..ba95ec3 100644 --- a/Test/baseResults/300scope.vert.out +++ b/Test/baseResults/300scope.vert.out @@ -90,6 +90,7 @@ ERROR: node is still EOpNull! 0:62 'S' (structure) 0:62 0 (const int) 0:? Linker Objects +0:? 'b' (bool) 0:? 'gl_VertexID' (gl_VertexId highp int) 0:? 'gl_InstanceID' (gl_InstanceId highp int) diff --git a/Test/baseResults/400.geom.out b/Test/baseResults/400.geom.out index edebc11..b32b57f 100644 --- a/Test/baseResults/400.geom.out +++ b/Test/baseResults/400.geom.out @@ -1,10 +1,12 @@ -0:3Function Definition: main( (void) -0:3 Function Parameters: -0:5 Sequence -0:5 EmitStreamVertex (void) -0:5 1 (const int) -0:6 EndStreamPrimitive (void) -0:6 0 (const int) -0:7 EmitVertex (void) -0:8 EndPrimitive (void) +0:? Sequence +0:3 Function Definition: main( (void) +0:3 Function Parameters: +0:5 Sequence +0:5 EmitStreamVertex (void) +0:5 1 (const int) +0:6 EndStreamPrimitive (void) +0:6 0 (const int) +0:7 EmitVertex (void) +0:8 EndPrimitive (void) +0:? Linker Objects diff --git a/Test/baseResults/400.tesc.out b/Test/baseResults/400.tesc.out index 04ce0e4..05a8a20 100644 --- a/Test/baseResults/400.tesc.out +++ b/Test/baseResults/400.tesc.out @@ -1,5 +1,7 @@ -0:3Function Definition: main( (void) -0:3 Function Parameters: -0:5 Sequence -0:5 Barrier (void) +0:? Sequence +0:3 Function Definition: main( (void) +0:3 Function Parameters: +0:5 Sequence +0:5 Barrier (void) +0:? Linker Objects diff --git a/Test/baseResults/400.tese.out b/Test/baseResults/400.tese.out index 7356a2d..67821cf 100644 --- a/Test/baseResults/400.tese.out +++ b/Test/baseResults/400.tese.out @@ -1,8 +1,10 @@ ERROR: 0:5: 'barrier' : no matching overloaded function found ERROR: 1 compilation errors. No code generated. -0:3Function Definition: main( (void) -0:3 Function Parameters: -0:5 Sequence -0:5 0.000000 +ERROR: node is still EOpNull! +0:3 Function Definition: main( (void) +0:3 Function Parameters: +0:5 Sequence +0:5 0.000000 +0:? Linker Objects diff --git a/Test/baseResults/420.tese.out b/Test/baseResults/420.tese.out index b7880b7..f44d24c 100644 --- a/Test/baseResults/420.tese.out +++ b/Test/baseResults/420.tese.out @@ -1,5 +1,7 @@ -0:3Function Definition: main( (void) -0:3 Function Parameters: -0:5 Sequence -0:5 MemoryBarrier (void) +0:? Sequence +0:3 Function Definition: main( (void) +0:3 Function Parameters: +0:5 Sequence +0:5 MemoryBarrier (void) +0:? Linker Objects diff --git a/Test/baseResults/430.comp.out b/Test/baseResults/430.comp.out index f160633..feac3c3 100644 --- a/Test/baseResults/430.comp.out +++ b/Test/baseResults/430.comp.out @@ -1,9 +1,11 @@ -0:3Function Definition: main( (void) -0:3 Function Parameters: -0:5 Sequence -0:5 MemoryBarrierAtomicCounter (void) -0:6 MemoryBarrierBuffer (void) -0:7 MemoryBarrierShared (void) -0:8 MemoryBarrierImage (void) -0:9 GroupMemoryBarrier (void) +0:? Sequence +0:3 Function Definition: main( (void) +0:3 Function Parameters: +0:5 Sequence +0:5 MemoryBarrierAtomicCounter (void) +0:6 MemoryBarrierBuffer (void) +0:7 MemoryBarrierShared (void) +0:8 MemoryBarrierImage (void) +0:9 GroupMemoryBarrier (void) +0:? Linker Objects diff --git a/Test/baseResults/430scope.vert.out b/Test/baseResults/430scope.vert.out index 540d52b..39d2556 100644 --- a/Test/baseResults/430scope.vert.out +++ b/Test/baseResults/430scope.vert.out @@ -86,6 +86,8 @@ ERROR: node is still EOpNull! 0:62 'S' (structure) 0:62 0 (const int) 0:? Linker Objects +0:? 'b' (bool) +0:? 'tan' (float) 0:? 'gl_VertexID' (gl_VertexId int) 0:? 'gl_InstanceID' (gl_InstanceId int) diff --git a/Test/baseResults/cppComplexExpr.vert.out b/Test/baseResults/cppComplexExpr.vert.out index 36fb057..f6410bf 100644 --- a/Test/baseResults/cppComplexExpr.vert.out +++ b/Test/baseResults/cppComplexExpr.vert.out @@ -20,4 +20,5 @@ WARNING: #version: statement missing; use #version on first line of shader 0:39 'gl_Position' (gl_Position highp 4-component vector of float) 0:39 Construct vec4 (highp 4-component vector of float) 0:39 'sum' (highp float) +0:? Linker Objects diff --git a/Test/baseResults/cppIndent.vert.out b/Test/baseResults/cppIndent.vert.out index 7ae92d6..0f9f66a 100644 --- a/Test/baseResults/cppIndent.vert.out +++ b/Test/baseResults/cppIndent.vert.out @@ -25,4 +25,5 @@ 0:56 'gl_Position' (gl_Position 4-component vector of float) 0:56 Construct vec4 (4-component vector of float) 0:56 'sum' (float) +0:? Linker Objects diff --git a/Test/baseResults/cppNest.vert.out b/Test/baseResults/cppNest.vert.out index 1d33459..4574806 100644 --- a/Test/baseResults/cppNest.vert.out +++ b/Test/baseResults/cppNest.vert.out @@ -28,4 +28,5 @@ 0:86 'gl_Position' (gl_Position 4-component vector of float) 0:86 Construct vec4 (4-component vector of float) 0:86 'sum' (float) +0:? Linker Objects diff --git a/Test/baseResults/cppSimple.vert.out b/Test/baseResults/cppSimple.vert.out index 6dcdca3..b98f560 100644 --- a/Test/baseResults/cppSimple.vert.out +++ b/Test/baseResults/cppSimple.vert.out @@ -70,4 +70,6 @@ ERROR: node is still EOpNull! 0:130 move second child to first child (float) 0:130 'twoPi' (float) 0:130 6.280000 +0:? Linker Objects +0:? 'tod' (float) diff --git a/Test/baseResults/dce.frag.out b/Test/baseResults/dce.frag.out index d854aca..7975f99 100644 --- a/Test/baseResults/dce.frag.out +++ b/Test/baseResults/dce.frag.out @@ -113,4 +113,5 @@ 0:53 5 (const int) 0:55 Pre-Increment (int) 0:55 'c' (int) +0:? Linker Objects diff --git a/Test/baseResults/errors.frag.out b/Test/baseResults/errors.frag.out index 279ffd7..b555dd3 100644 --- a/Test/baseResults/errors.frag.out +++ b/Test/baseResults/errors.frag.out @@ -3,10 +3,12 @@ ERROR: 0:1: 'main' : function cannot take any parameter(s) ERROR: 0:1: 'int' : main function cannot return a value ERROR: 2 compilation errors. No code generated. -0:1Function Definition: main(i1; (mediump int) -0:1 Function Parameters: -0:1 'foo' (in mediump int) -0:3 Sequence -0:3 Branch: Return with expression -0:3 1 (const int) +ERROR: node is still EOpNull! +0:1 Function Definition: main(i1; (mediump int) +0:1 Function Parameters: +0:1 'foo' (in mediump int) +0:3 Sequence +0:3 Branch: Return with expression +0:3 1 (const int) +0:? Linker Objects diff --git a/Test/baseResults/functionSemantics.frag.out b/Test/baseResults/functionSemantics.frag.out index 35af953..79c9b36 100644 --- a/Test/baseResults/functionSemantics.frag.out +++ b/Test/baseResults/functionSemantics.frag.out @@ -97,4 +97,5 @@ 0:35 Construct vec4 (mediump 4-component vector of float) 0:35 Convert int to float (mediump float) 0:35 'color' (mediump int) +0:? Linker Objects diff --git a/Test/baseResults/length.frag.out b/Test/baseResults/length.frag.out index bb8f8a6..5deccaa 100644 --- a/Test/baseResults/length.frag.out +++ b/Test/baseResults/length.frag.out @@ -18,4 +18,5 @@ 0:17 30.000000 0:17 30.000000 0:17 30.000000 +0:? Linker Objects diff --git a/Test/baseResults/lineContinuation.vert.out b/Test/baseResults/lineContinuation.vert.out index 2e56483..b66a25f 100644 --- a/Test/baseResults/lineContinuation.vert.out +++ b/Test/baseResults/lineContinuation.vert.out @@ -12,6 +12,7 @@ ERROR: node is still EOpNull! 0:20 Construct vec4 (highp 4-component vector of float) 0:20 'foo' (highp float) 0:? Linker Objects +0:? 'foo' (highp float) 0:? 'gl_VertexID' (gl_VertexId highp int) 0:? 'gl_InstanceID' (gl_InstanceId highp int) diff --git a/Test/baseResults/link1.frag.out b/Test/baseResults/link1.frag.out new file mode 100644 index 0000000..5119acf --- /dev/null +++ b/Test/baseResults/link1.frag.out @@ -0,0 +1,150 @@ +link1.frag + +0:? Sequence +0:8 Sequence +0:8 move second child to first child (4-component vector of float) +0:8 'a' (4-component vector of float) +0:8 vector-scale (4-component vector of float) +0:8 8.000000 +0:8 'uv4' (uniform 4-component vector of float) +0:13 Function Definition: main( (void) +0:13 Function Parameters: +0:17 Sequence +0:17 move second child to first child (4-component vector of float) +0:17 'b' (4-component vector of float) +0:17 vector-scale (4-component vector of float) +0:17 8.000000 +0:17 'a' (4-component vector of float) +0:19 Function Definition: foo(mf22; (2-component vector of int) +0:19 Function Parameters: +0:19 'm' (in 2X2 matrix of float) +0:21 Sequence +0:21 Branch: Return with expression +0:21 Convert float to int (2-component vector of int) +0:21 direct index (in 2-component vector of float) +0:21 'm' (in 2X2 matrix of float) +0:21 0 (const int) +0:24 Sequence +0:24 move second child to first child (4-component vector of float) +0:24 'c' (4-component vector of float) +0:24 component-wise multiply (4-component vector of float) +0:24 'b' (4-component vector of float) +0:24 'b' (4-component vector of float) +0:? Linker Objects +0:? 'uv4' (uniform 4-component vector of float) +0:? 'glass' (uniform 3-component vector of float) +0:? 'iv3' (smooth in 3-component vector of float) +0:? 'cup' (smooth in 4-component vector of float) + +link2.frag + +0:? Sequence +0:8 Sequence +0:8 move second child to first child (4-component vector of float) +0:8 'd' (4-component vector of float) +0:8 vector-scale (4-component vector of float) +0:8 8.000000 +0:8 'uv4' (uniform 4-component vector of float) +0:13 Sequence +0:13 move second child to first child (4-component vector of float) +0:13 'e' (4-component vector of float) +0:13 vector-scale (4-component vector of float) +0:13 8.000000 +0:13 'd' (4-component vector of float) +0:15 Function Definition: foo( (2-component vector of int) +0:15 Function Parameters: +0:17 Sequence +0:17 Branch: Return with expression +0:17 2 (const int) +0:17 2 (const int) +0:20 Sequence +0:20 move second child to first child (4-component vector of float) +0:20 'f' (4-component vector of float) +0:20 component-wise multiply (4-component vector of float) +0:20 'e' (4-component vector of float) +0:20 'e' (4-component vector of float) +0:? Linker Objects +0:? 'uv4' (uniform 4-component vector of float) +0:? 'glass' (uniform 2-component vector of float) +0:? 'iv3' (smooth in 3-component vector of float) +0:? 'cup' (flat in 4-component vector of float) + +link3.frag + +0:? Sequence +0:? Linker Objects +0:? 'iv3' (smooth in highp 2-component vector of float) + + +Linked fragment stage: + +ERROR: Linking fragment stage: Types must match: + glass: "uniform 3-component vector of float" versus "uniform 2-component vector of float" +ERROR: Linking fragment stage: Interpolation and auxiliary storage qualifiers must match: + cup: "smooth in 4-component vector of float" versus "flat in 4-component vector of float" +ERROR: Linking fragment stage: Cannot mix ES profile with non-ES profile shaders + +ERROR: Linking fragment stage: Types must match: +ERROR: Linking fragment stage: Precision qualifiers must match: + iv3: "smooth in 3-component vector of float" versus "smooth in highp 2-component vector of float" + +0:? Sequence +0:8 Sequence +0:8 move second child to first child (4-component vector of float) +0:8 'a' (4-component vector of float) +0:8 vector-scale (4-component vector of float) +0:8 8.000000 +0:8 'uv4' (uniform 4-component vector of float) +0:13 Function Definition: main( (void) +0:13 Function Parameters: +0:17 Sequence +0:17 move second child to first child (4-component vector of float) +0:17 'b' (4-component vector of float) +0:17 vector-scale (4-component vector of float) +0:17 8.000000 +0:17 'a' (4-component vector of float) +0:19 Function Definition: foo(mf22; (2-component vector of int) +0:19 Function Parameters: +0:19 'm' (in 2X2 matrix of float) +0:21 Sequence +0:21 Branch: Return with expression +0:21 Convert float to int (2-component vector of int) +0:21 direct index (in 2-component vector of float) +0:21 'm' (in 2X2 matrix of float) +0:21 0 (const int) +0:24 Sequence +0:24 move second child to first child (4-component vector of float) +0:24 'c' (4-component vector of float) +0:24 component-wise multiply (4-component vector of float) +0:24 'b' (4-component vector of float) +0:24 'b' (4-component vector of float) +0:8 Sequence +0:8 move second child to first child (4-component vector of float) +0:8 'd' (4-component vector of float) +0:8 vector-scale (4-component vector of float) +0:8 8.000000 +0:8 'uv4' (uniform 4-component vector of float) +0:13 Sequence +0:13 move second child to first child (4-component vector of float) +0:13 'e' (4-component vector of float) +0:13 vector-scale (4-component vector of float) +0:13 8.000000 +0:13 'd' (4-component vector of float) +0:15 Function Definition: foo( (2-component vector of int) +0:15 Function Parameters: +0:17 Sequence +0:17 Branch: Return with expression +0:17 2 (const int) +0:17 2 (const int) +0:20 Sequence +0:20 move second child to first child (4-component vector of float) +0:20 'f' (4-component vector of float) +0:20 component-wise multiply (4-component vector of float) +0:20 'e' (4-component vector of float) +0:20 'e' (4-component vector of float) +0:? Linker Objects +0:? 'uv4' (uniform 4-component vector of float) +0:? 'glass' (uniform 3-component vector of float) +0:? 'iv3' (smooth in 3-component vector of float) +0:? 'cup' (smooth in 4-component vector of float) + diff --git a/Test/baseResults/mains1.frag.out b/Test/baseResults/mains1.frag.out index 69a2078..9393d86 100644 --- a/Test/baseResults/mains1.frag.out +++ b/Test/baseResults/mains1.frag.out @@ -1,33 +1,54 @@ mains1.frag -0:3Function Definition: main( (void) -0:3 Function Parameters: +0:? Sequence +0:3 Function Definition: main( (void) +0:3 Function Parameters: +0:? Linker Objects mains2.frag -0:3Function Definition: main( (void) -0:3 Function Parameters: +0:? Sequence +0:3 Function Definition: main( (void) +0:3 Function Parameters: +0:? Linker Objects noMain1.geom ERROR: #version: geometry shaders require non-es profile and version 150 or above ERROR: 1 compilation errors. No code generated. -0:3Function Definition: foo( (void) -0:3 Function Parameters: +ERROR: node is still EOpNull! +0:3 Function Definition: foo( (void) +0:3 Function Parameters: +0:? Linker Objects noMain2.geom -0:3Function Definition: bar( (void) -0:3 Function Parameters: +0:? Sequence +0:3 Function Definition: bar( (void) +0:3 Function Parameters: +0:? Linker Objects Linked geometry stage: -ERROR: Missing entry point: Each stage requires one "void main()" entry point +ERROR: Linking geometry stage: Missing entry point: Each stage requires one "void main()" entry point Linked fragment stage: -ERROR: Too many entry points: Each stage can have at most one "void main()" entry point. - +ERROR: Linking fragment stage: Multiple function bodies in multiple compilation units for the same signature in the same stage: + main( + +ERROR: node is still EOpNull! +0:3 Function Definition: foo( (void) +0:3 Function Parameters: +0:3 Function Definition: bar( (void) +0:3 Function Parameters: +0:? Linker Objects +0:? Sequence +0:3 Function Definition: main( (void) +0:3 Function Parameters: +0:3 Function Definition: main( (void) +0:3 Function Parameters: +0:? Linker Objects diff --git a/Test/baseResults/noMain.vert.out b/Test/baseResults/noMain.vert.out index f55806c..fa97a7d 100644 --- a/Test/baseResults/noMain.vert.out +++ b/Test/baseResults/noMain.vert.out @@ -1,7 +1,11 @@ noMain.vert -0:3Function Definition: foo( (void) -0:3 Function Parameters: +0:? Sequence +0:3 Function Definition: foo( (void) +0:3 Function Parameters: +0:? Linker Objects +0:? 'gl_VertexID' (gl_VertexId highp int) +0:? 'gl_InstanceID' (gl_InstanceId highp int) mains.frag ERROR: 0:7: 'main' : function already has a body @@ -13,14 +17,14 @@ ERROR: node is still EOpNull! 0:3 Function Parameters: 0:7 Function Definition: main( (void) 0:7 Function Parameters: +0:? Linker Objects Linked vertex stage: -ERROR: Missing entry point: Each stage requires one "void main()" entry point +ERROR: Linking vertex stage: Missing entry point: Each stage requires one "void main()" entry point Linked fragment stage: -ERROR: Too many entry points: Each stage can have at most one "void main()" entry point. diff --git a/Test/baseResults/precision.frag.out b/Test/baseResults/precision.frag.out index 76ef998..93f1cba 100644 --- a/Test/baseResults/precision.frag.out +++ b/Test/baseResults/precision.frag.out @@ -103,7 +103,10 @@ ERROR: node is still EOpNull! 0:69 0.200000 0:? Linker Objects 0:? 'color' (smooth in mediump 3-component vector of float) +0:? 'global_medium' (mediump int) 0:? 'samplerLow' (uniform lowp sampler2D) 0:? 'samplerMed' (uniform mediump sampler2D) 0:? 'samplerHigh' (uniform highp sampler2D) +0:? 'uint' (mediump 4-component vector of float) +0:? 'global_high' (highp int) diff --git a/Test/baseResults/prepost.frag.out b/Test/baseResults/prepost.frag.out index bddbcae..f322cc7 100644 --- a/Test/baseResults/prepost.frag.out +++ b/Test/baseResults/prepost.frag.out @@ -1,112 +1,114 @@ -0:3Function Definition: main( (void) -0:3 Function Parameters: -0:? Sequence -0:10 Sequence -0:10 move second child to first child (int) -0:10 'index' (int) -0:10 5 (const int) -0:12 move second child to first child (float) -0:12 direct index (float) -0:12 y: direct index for structure (5-element array of float) -0:12 'str' (structure) -0:12 0 (const int) -0:12 4 (const int) -0:12 2.000000 -0:13 move second child to first child (float) -0:13 't' (float) -0:13 Pre-Increment (float) -0:13 indirect index (float) -0:13 y: direct index for structure (5-element array of float) -0:13 'str' (structure) -0:13 0 (const int) -0:13 Pre-Decrement (int) -0:13 'index' (int) -0:14 add second child into first child (float) -0:14 direct index (float) -0:14 y: direct index for structure (5-element array of float) -0:14 'str' (structure) -0:14 0 (const int) -0:14 4 (const int) -0:14 't' (float) -0:15 move second child to first child (float) -0:15 't' (float) -0:15 Post-Decrement (float) -0:15 direct index (float) -0:15 y: direct index for structure (5-element array of float) -0:15 'str' (structure) -0:15 0 (const int) -0:15 4 (const int) -0:16 add second child into first child (float) -0:16 indirect index (float) -0:16 y: direct index for structure (5-element array of float) -0:16 'str' (structure) -0:16 0 (const int) -0:16 Post-Increment (int) -0:16 'index' (int) -0:16 't' (float) -0:17 Pre-Decrement (float) -0:17 indirect index (float) -0:17 y: direct index for structure (5-element array of float) -0:17 'str' (structure) -0:17 0 (const int) -0:17 Pre-Decrement (int) -0:17 'index' (int) -0:19 Sequence -0:19 move second child to first child (float) -0:19 'x' (float) -0:19 direct index (float) -0:19 y: direct index for structure (5-element array of float) -0:19 'str' (structure) -0:19 0 (const int) -0:19 4 (const int) -0:20 Pre-Increment (float) -0:20 'x' (float) -0:21 Pre-Decrement (float) -0:21 'x' (float) -0:22 Post-Increment (float) -0:22 'x' (float) -0:23 Post-Decrement (float) -0:23 'x' (float) -0:27 Sequence -0:27 move second child to first child (float) -0:27 'y' (float) -0:27 component-wise multiply (float) -0:27 'x' (float) -0:27 Pre-Increment (float) +0:? Sequence +0:3 Function Definition: main( (void) +0:3 Function Parameters: +0:? Sequence +0:10 Sequence +0:10 move second child to first child (int) +0:10 'index' (int) +0:10 5 (const int) +0:12 move second child to first child (float) +0:12 direct index (float) +0:12 y: direct index for structure (5-element array of float) +0:12 'str' (structure) +0:12 0 (const int) +0:12 4 (const int) +0:12 2.000000 +0:13 move second child to first child (float) +0:13 't' (float) +0:13 Pre-Increment (float) +0:13 indirect index (float) +0:13 y: direct index for structure (5-element array of float) +0:13 'str' (structure) +0:13 0 (const int) +0:13 Pre-Decrement (int) +0:13 'index' (int) +0:14 add second child into first child (float) +0:14 direct index (float) +0:14 y: direct index for structure (5-element array of float) +0:14 'str' (structure) +0:14 0 (const int) +0:14 4 (const int) +0:14 't' (float) +0:15 move second child to first child (float) +0:15 't' (float) +0:15 Post-Decrement (float) +0:15 direct index (float) +0:15 y: direct index for structure (5-element array of float) +0:15 'str' (structure) +0:15 0 (const int) +0:15 4 (const int) +0:16 add second child into first child (float) +0:16 indirect index (float) +0:16 y: direct index for structure (5-element array of float) +0:16 'str' (structure) +0:16 0 (const int) +0:16 Post-Increment (int) +0:16 'index' (int) +0:16 't' (float) +0:17 Pre-Decrement (float) +0:17 indirect index (float) +0:17 y: direct index for structure (5-element array of float) +0:17 'str' (structure) +0:17 0 (const int) +0:17 Pre-Decrement (int) +0:17 'index' (int) +0:19 Sequence +0:19 move second child to first child (float) +0:19 'x' (float) +0:19 direct index (float) +0:19 y: direct index for structure (5-element array of float) +0:19 'str' (structure) +0:19 0 (const int) +0:19 4 (const int) +0:20 Pre-Increment (float) +0:20 'x' (float) +0:21 Pre-Decrement (float) +0:21 'x' (float) +0:22 Post-Increment (float) +0:22 'x' (float) +0:23 Post-Decrement (float) +0:23 'x' (float) +0:27 Sequence +0:27 move second child to first child (float) +0:27 'y' (float) +0:27 component-wise multiply (float) 0:27 'x' (float) -0:28 Sequence -0:28 move second child to first child (float) -0:28 'z' (float) -0:28 component-wise multiply (float) -0:28 'y' (float) -0:28 Post-Decrement (float) -0:28 'x' (float) -0:33 Sequence -0:33 move second child to first child (4-component vector of float) -0:33 'v' (4-component vector of float) -0:33 1.000000 -0:33 2.000000 -0:33 3.000000 -0:33 4.000000 -0:34 move second child to first child (float) -0:34 direct index (float) -0:34 'v' (4-component vector of float) -0:34 1 (const int) -0:34 Post-Decrement (float) +0:27 Pre-Increment (float) +0:27 'x' (float) +0:28 Sequence +0:28 move second child to first child (float) +0:28 'z' (float) +0:28 component-wise multiply (float) +0:28 'y' (float) +0:28 Post-Decrement (float) +0:28 'x' (float) +0:33 Sequence +0:33 move second child to first child (4-component vector of float) +0:33 'v' (4-component vector of float) +0:33 1.000000 +0:33 2.000000 +0:33 3.000000 +0:33 4.000000 +0:34 move second child to first child (float) 0:34 direct index (float) 0:34 'v' (4-component vector of float) -0:34 2 (const int) -0:35 move second child to first child (float) -0:35 direct index (float) -0:35 'v' (4-component vector of float) -0:35 0 (const int) -0:35 Pre-Decrement (float) +0:34 1 (const int) +0:34 Post-Decrement (float) +0:34 direct index (float) +0:34 'v' (4-component vector of float) +0:34 2 (const int) +0:35 move second child to first child (float) 0:35 direct index (float) 0:35 'v' (4-component vector of float) -0:35 3 (const int) -0:37 move second child to first child (4-component vector of float) -0:37 'gl_FragColor' (fragColor 4-component vector of float) -0:37 vector-scale (4-component vector of float) -0:37 'z' (float) -0:37 'v' (4-component vector of float) +0:35 0 (const int) +0:35 Pre-Decrement (float) +0:35 direct index (float) +0:35 'v' (4-component vector of float) +0:35 3 (const int) +0:37 move second child to first child (4-component vector of float) +0:37 'gl_FragColor' (fragColor 4-component vector of float) +0:37 vector-scale (4-component vector of float) +0:37 'z' (float) +0:37 'v' (4-component vector of float) +0:? Linker Objects diff --git a/Test/baseResults/specExamples.frag.out b/Test/baseResults/specExamples.frag.out index 7c0558d..9bba530 100644 --- a/Test/baseResults/specExamples.frag.out +++ b/Test/baseResults/specExamples.frag.out @@ -196,6 +196,22 @@ ERROR: node is still EOpNull! 0:218 'c' (5-element array of float) 0:218 'a' (5-element array of float) 0:? Linker Objects +0:? 'fa' (float) +0:? 'fc' (double) +0:? 'texcoord1' (2-component vector of float) +0:? 'texcoord2' (2-component vector of float) +0:? 'position' (3-component vector of float) +0:? 'myRGBA' (4-component vector of float) +0:? 'textureLookup' (2-component vector of int) +0:? 'less' (3-component vector of bool) +0:? 'mat2D' (2X2 matrix of float) +0:? 'optMatrix' (3X3 matrix of float) +0:? 'view' (4X4 matrix of float) +0:? 'projection' (4X4 matrix of float) +0:? 'm' (3X2 matrix of float) +0:? 'highPrecisionMVP' (4X4 matrix of double) +0:? 'dm' (2X4 matrix of double) +0:? 'lightVar' (structure) 0:? 'normal' (smooth in 3-component vector of float) 0:? 'TexCoord' (centroid smooth in 2-component vector of float) 0:? 'Color' (invariant centroid smooth in 4-component vector of float) diff --git a/Test/baseResults/syntaxError.frag.out b/Test/baseResults/syntaxError.frag.out index 44892c2..54df813 100644 --- a/Test/baseResults/syntaxError.frag.out +++ b/Test/baseResults/syntaxError.frag.out @@ -2,4 +2,9 @@ ERROR: 0:9: 'vec5' : undeclared identifier ERROR: 0:9: '' : syntax error ERROR: 2 compilation errors. No code generated. +ERROR: node is still EOpNull! +0:? Linker Objects +0:? 'bigColor' (uniform 4-component vector of float) +0:? 'BaseColor' (smooth in 4-component vector of float) +0:? 'd' (uniform float) diff --git a/Test/baseResults/tokenLength.vert.out b/Test/baseResults/tokenLength.vert.out index 7c42c8f..613a81c 100644 --- a/Test/baseResults/tokenLength.vert.out +++ b/Test/baseResults/tokenLength.vert.out @@ -77,6 +77,7 @@ ERROR: node is still EOpNull! 0:? Linker Objects 0:? 'BCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789' (in highp float) 0:? 'ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789' (in highp float) +0:? 'BCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789B' (highp float) 0:? 'gl_VertexID' (gl_VertexId highp int) 0:? 'gl_InstanceID' (gl_InstanceId highp int) diff --git a/Test/link1.frag b/Test/link1.frag new file mode 100644 index 0000000..3bb5cf6 --- /dev/null +++ b/Test/link1.frag @@ -0,0 +1,24 @@ +#version 130 + +uniform vec4 uv4; +uniform vec3 glass; + +const int ci = 8; + +vec4 a = ci * uv4; + +in vec3 iv3; +in vec4 cup; + +void main() +{ +} + +vec4 b = ci * a; + +ivec2 foo(mat2 m) +{ + return ivec2(m[0]); +} + +vec4 c = b * b; diff --git a/Test/link2.frag b/Test/link2.frag new file mode 100644 index 0000000..e7fe630 --- /dev/null +++ b/Test/link2.frag @@ -0,0 +1,20 @@ +#version 130 + +uniform vec4 uv4; +uniform vec2 glass; + +const int ci = 8; + +vec4 d = ci * uv4; + +in vec3 iv3; +flat in vec4 cup; + +vec4 e = ci * d; + +ivec2 foo() +{ + return ivec2(2); +} + +vec4 f = e * e; diff --git a/Test/link3.frag b/Test/link3.frag new file mode 100644 index 0000000..a9604c4 --- /dev/null +++ b/Test/link3.frag @@ -0,0 +1,5 @@ +#version 300 es + +precision highp float; + +in vec2 iv3; diff --git a/Test/runtests b/Test/runtests index 16b5deb..55c039a 100644 --- a/Test/runtests +++ b/Test/runtests @@ -33,7 +33,8 @@ function runLinkTest { } runLinkTest mains1.frag mains2.frag noMain1.geom noMain2.geom -runLinkTest noMain.vert mains.frag +runLinkTest noMain.vert mains.frag +runLinkTest link1.frag link2.frag link3.frag # # multi-threaded test @@ -42,4 +43,3 @@ echo Comparing single thread to multithread for all tests in current directory.. $EXE -i *.vert *.geom *.frag *.tes* *.comp > singleThread.out $EXE -i *.vert *.geom *.frag *.tes* *.comp -t > multiThread.out diff singleThread.out multiThread.out - diff --git a/Todo.txt b/Todo.txt index 4d4360b..84784b2 100644 --- a/Todo.txt +++ b/Todo.txt @@ -11,26 +11,29 @@ Link Validation - mixed es/non-es profiles - statically consumed input not produced by previous stage - matching between gl_PerVertex blocks and gl_PerFragment blocks - - compute shader not with other stages + - compute shader not combined with any other stages + - give error for sharing a packed block - 1.3: deprecated mixing fixed vertex/fragment stage with programmable fragment/vertex stage. - 4.3: remove cross-version linking restrictions. - 4.3: Allow mismatches in interpolation and auxiliary qualification across stages. - 4.4: A stage contains two different blocks, each with no instance name, where the blocks contain a member with the same name. Intra-stage linking - - exactly one main - - type consistency check of uniforms, globals, ins, and outs, both variables and blocks + + exactly one main + + type consistency check of uniforms, globals, ins, and outs + - still need to cover arrays and the combinations of this rule with redeclarations of built-ins - value checking of global const initializers - value checking of uniform initializers - - location/component/binding/index/offset match check + + location match + - component/binding/index/offset match check - location/component aliasing (except desktop vertex shader inputs) - location layout range/overlap semantics - geometry shader input array sizes and input layout qualifier declaration - compute shader layout(local_size_*) matching - - mixed es/non-es profiles - - matching initializers for globals + + mixed es/non-es profiles - recursion for both functions and subroutines - - Even the potential for recursion through subroutine uniforms is an error. - - matching redeclarations of interface blocks + - Even the potential for recursion through subroutine uniforms is an error. + - block matching + - matching redeclarations of interface blocks - read or write to both gl_ClipVertex and gl_ClipDistance - write to only one of gl_FragColor, gl_FragData, or user-declared - 4.3: Be clear that early_fragment_tests is only needed in one fragment-stage compilation unit. diff --git a/glslang/MachineIndependent/Intermediate.cpp b/glslang/MachineIndependent/Intermediate.cpp index 62c93a4..20212c9 100644 --- a/glslang/MachineIndependent/Intermediate.cpp +++ b/glslang/MachineIndependent/Intermediate.cpp @@ -850,7 +850,7 @@ bool TIntermediate::postProcess(TIntermNode* root, EShLanguage language) return true; } -void TIntermediate::addSymbolLinkageNodes(TIntermNode* root, TIntermAggregate*& linkage, EShLanguage language, TSymbolTable& symbolTable) +void TIntermediate::addSymbolLinkageNodes(TIntermAggregate*& linkage, EShLanguage language, TSymbolTable& symbolTable) { // Add top-level nodes for declarations that must be checked cross // compilation unit by a linker, yet might not have been referenced @@ -880,13 +880,9 @@ void TIntermediate::addSymbolLinkageNodes(TIntermNode* root, TIntermAggregate*& addSymbolLinkageNode(linkage, symbolTable, "gl_InstanceID"); } - if (linkage) { - // Finish off linkage sequence - linkage->setOperator(EOpLinkerObjects); - - // Add a child to the root node for the linker objects - growAggregate(root, linkage); - } + // Add a child to the root node for the linker objects + linkage->setOperator(EOpLinkerObjects); + treeRoot = growAggregate(treeRoot, linkage); } void TIntermediate::addSymbolLinkageNode(TIntermAggregate*& linkage, TSymbolTable& symbolTable, const TString& name) @@ -903,30 +899,179 @@ void TIntermediate::addSymbolLinkageNode(TIntermAggregate*& linkage, const TVari } // -// Merge the information in 'unit' into 'this' +// Merge the information from 'unit' into 'this' // -void TIntermediate::merge(TIntermediate& unit) +void TIntermediate::merge(TInfoSink& infoSink, TIntermediate& unit) { numMains += unit.numMains; + + if (profile != EEsProfile && unit.profile == EEsProfile || + profile == EEsProfile && unit.profile != EEsProfile) + error(infoSink, "Cannot mix ES profile with non-ES profile shaders\n"); + + if (unit.treeRoot == 0) + return; + + if (treeRoot == 0) { + version = unit.version; + treeRoot = unit.treeRoot; + return; + } else + version = std::max(version, unit.version); + + // Get the top-level globals of each level + TIntermSequence& globals = treeRoot->getAsAggregate()->getSequence(); + TIntermSequence& unitGlobals = unit.treeRoot->getAsAggregate()->getSequence(); + + // Get the last members of the sequences, expected to be the linker-object lists + assert(globals.back()->getAsAggregate()->getOp() == EOpLinkerObjects); + assert(unitGlobals.back()->getAsAggregate()->getOp() == EOpLinkerObjects); + TIntermSequence& linkerObjects = globals.back()->getAsAggregate()->getSequence(); + TIntermSequence& unitLinkerObjects = unitGlobals.back()->getAsAggregate()->getSequence(); + + mergeBodies(infoSink, globals, unitGlobals); + mergeLinkerObjects(infoSink, linkerObjects, unitLinkerObjects); +} + +// +// Merge the function bodies and global-level initalizers from unitGlobals into globals. +// Will error check duplication of function bodies for the same signature. +// +void TIntermediate::mergeBodies(TInfoSink& infoSink, TIntermSequence& globals, const TIntermSequence& unitGlobals) +{ + // TODO: Performance: Processing in alphabetical order will be faster + + // Error check the global objects, not including the linker objects + for (unsigned int child = 0; child < globals.size() - 1; ++child) { + for (unsigned int unitChild = 0; unitChild < unitGlobals.size() - 1; ++unitChild) { + TIntermAggregate* body = globals[child]->getAsAggregate(); + TIntermAggregate* unitBody = unitGlobals[unitChild]->getAsAggregate(); + if (body && unitBody && body->getOp() == EOpFunction && unitBody->getOp() == EOpFunction && body->getName() == unitBody->getName()) { + error(infoSink, "Multiple function bodies in multiple compilation units for the same signature in the same stage:"); + infoSink.info << " " << globals[child]->getAsAggregate()->getName() << "\n"; + } + } + } + + // Merge the global objects, just in front of the linker objects + globals.insert(globals.end() - 1, unitGlobals.begin(), unitGlobals.end() - 1); +} + +// +// Merge the linker objects from unitLinkerObjects into linkerObjects. +// Duplication is expected and filtered out, but contradictions are an error. +// +void TIntermediate::mergeLinkerObjects(TInfoSink& infoSink, TIntermSequence& linkerObjects, const TIntermSequence& unitLinkerObjects) +{ + // Error check and merge the linker objects (duplicates should not be merged) + unsigned int initialNumLinkerObjects = linkerObjects.size(); + for (unsigned int unitLinkObj = 0; unitLinkObj < unitLinkerObjects.size(); ++unitLinkObj) { + bool merge = true; + for (unsigned int linkObj = 0; linkObj < initialNumLinkerObjects; ++linkObj) { + TIntermSymbol* symbol = linkerObjects[linkObj]->getAsSymbolNode(); + TIntermSymbol* unitSymbol = unitLinkerObjects[unitLinkObj]->getAsSymbolNode(); + assert(symbol && unitSymbol); + if (symbol->getName() == unitSymbol->getName()) { + // filter out copy + merge = false; + + // Check for consistent types/qualification/etc. + linkErrorCheck(infoSink, *symbol, *unitSymbol, false); + } + } + if (merge) + linkerObjects.push_back(unitLinkerObjects[unitLinkObj]); + } } void TIntermediate::errorCheck(TInfoSink& infoSink) { if (numMains < 1) error(infoSink, "Missing entry point: Each stage requires one \"void main()\" entry point"); - if (numMains > 1) - error(infoSink, "Too many entry points: Each stage can have at most one \"void main()\" entry point."); } void TIntermediate::error(TInfoSink& infoSink, const char* message) { infoSink.info.prefix(EPrefixError); - infoSink.info << message << "\n"; + infoSink.info << "Linking " << StageName[language] << " stage: " << message << "\n"; ++numErrors; } // +// Compare two global objects from two compilation units and see if they match +// well enough. Rules can be different for intra- vs. cross-stage matching. +// +// This function only does one of intra- or cross-stage matching per call. +// +// TODO: Linker Functionality: this function is under active development +// +void TIntermediate::linkErrorCheck(TInfoSink& infoSink, const TIntermSymbol& symbol, const TIntermSymbol& unitSymbol, bool crossStage) +{ + bool writeTypeComparison = false; + + // Types have to match + if (symbol.getType() != unitSymbol.getType()) { + error(infoSink, "Types must match:"); + writeTypeComparison = true; + } + + // Qualifiers have to (almost) match + + // Storage... + if (symbol.getQualifier().storage != unitSymbol.getQualifier().storage) { + error(infoSink, "Storage qualifiers must match:"); + writeTypeComparison = true; + } + + // Precision... + if (symbol.getQualifier().precision != unitSymbol.getQualifier().precision) { + error(infoSink, "Precision qualifiers must match:"); + writeTypeComparison = true; + } + + // Invariance... + if (! crossStage && symbol.getQualifier().invariant != unitSymbol.getQualifier().invariant) { + error(infoSink, "Presence of invariant qualifier must match:"); + writeTypeComparison = true; + } + + // Auxiliary and interpolation... + if (symbol.getQualifier().centroid != unitSymbol.getQualifier().centroid || + symbol.getQualifier().smooth != unitSymbol.getQualifier().smooth || + symbol.getQualifier().flat != unitSymbol.getQualifier().flat || + symbol.getQualifier().sample != unitSymbol.getQualifier().sample || + symbol.getQualifier().patch != unitSymbol.getQualifier().patch || + symbol.getQualifier().nopersp != unitSymbol.getQualifier().nopersp) { + error(infoSink, "Interpolation and auxiliary storage qualifiers must match:"); + writeTypeComparison = true; + } + + // Memory... + if (symbol.getQualifier().shared != unitSymbol.getQualifier().shared || + symbol.getQualifier().coherent != unitSymbol.getQualifier().coherent || + symbol.getQualifier().volatil != unitSymbol.getQualifier().volatil || + symbol.getQualifier().restrict != unitSymbol.getQualifier().restrict || + symbol.getQualifier().readonly != unitSymbol.getQualifier().readonly || + symbol.getQualifier().writeonly != unitSymbol.getQualifier().writeonly) { + error(infoSink, "Memory qualifiers must match:"); + writeTypeComparison = true; + } + + // Layouts... + if (symbol.getQualifier().layoutMatrix != unitSymbol.getQualifier().layoutMatrix || + symbol.getQualifier().layoutPacking != unitSymbol.getQualifier().layoutPacking || + symbol.getQualifier().layoutSlotLocation != unitSymbol.getQualifier().layoutSlotLocation) { + error(infoSink, "Layout qualification must match:"); + writeTypeComparison = true; + } + + if (writeTypeComparison) + infoSink.info << " " << symbol.getName() << ": \"" << symbol.getType().getCompleteString() << "\" versus \"" << + unitSymbol.getType().getCompleteString() << "\"\n"; +} + +// // This deletes the tree. // void TIntermediate::removeTree() diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index 25de8f9..d41a31d 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -51,12 +51,15 @@ TParseContext::TParseContext(TSymbolTable& symt, TIntermediate& interm, bool pb, intermediate(interm), symbolTable(symt), infoSink(is), language(L), version(v), profile(p), forwardCompatible(fc), messages(m), contextPragma(true, false), loopNestingLevel(0), structNestingLevel(0), - linkage(0), tokensBeforeEOF(false), + tokensBeforeEOF(false), parsingBuiltins(pb), numErrors(0), afterEOF(false) { currentLoc.line = 1; currentLoc.string = 0; + // ensure we always have a linkage node, even if empty, to simplify tree topology algorithms + linkage = new TIntermAggregate; + // set all precision defaults to EpqNone, which is correct for all desktop types // and for ES types that don't have defaults (thus getting an error on use) for (int type = 0; type < EbtNumTypes; ++type) @@ -1795,7 +1798,7 @@ void TParseContext::nonInitConstCheck(TSourceLoc loc, TString& identifier, TPubl // // Make the qualifier make sense. // - if (type.qualifier.storage == EvqConst) { + if (type.qualifier.storage == EvqConst) { type.qualifier.storage = EvqTemporary; error(loc, "variables with qualifier 'const' must be initialized", identifier.c_str(), ""); } @@ -1808,8 +1811,10 @@ void TParseContext::nonInitConstCheck(TSourceLoc loc, TString& identifier, TPubl void TParseContext::nonInitCheck(TSourceLoc loc, TString& identifier, TPublicType& publicType) { TType type(publicType); - bool newDeclaration; + + bool newDeclaration; // true if a new entry gets added to the symbol table TVariable* variable = redeclare(loc, identifier, type, newDeclaration); + if (! variable) { reservedErrorCheck(loc, identifier); variable = new TVariable(&identifier, type); @@ -1823,19 +1828,19 @@ void TParseContext::nonInitCheck(TSourceLoc loc, TString& identifier, TPublicTyp voidErrorCheck(loc, identifier, publicType); // see if it's a linker-level object to track - if (type.getQualifier().isUniform() || type.getQualifier().isPipeInput() || type.getQualifier().isPipeOutput()) - intermediate.addSymbolLinkageNode(linkage, *variable); + if (type.getQualifier().isUniform() || type.getQualifier().isPipeInput() || type.getQualifier().isPipeOutput() || type.getQualifier().storage == EvqGlobal) + intermediate.addSymbolLinkageNode(linkage, *variable); } } // // See if the identifier is a built-in symbol that can be redeclared, // and if so, copy of the symbol table's read-only built-in to the current -// globol level, so it can be modified. +// global level, so it can be modified. // TVariable* TParseContext::redeclare(TSourceLoc loc, const TString& identifier, const TType& type, bool& newDeclaration) { - newDeclaration = false; + newDeclaration = false; // true if a new entry gets added to the symbol table if (profile == EEsProfile || identifier.substr(0, 3) != TString("gl_") || symbolTable.atBuiltInLevel()) return 0; diff --git a/glslang/MachineIndependent/ShaderLang.cpp b/glslang/MachineIndependent/ShaderLang.cpp index 7d7b75e..6b577c0 100644 --- a/glslang/MachineIndependent/ShaderLang.cpp +++ b/glslang/MachineIndependent/ShaderLang.cpp @@ -106,7 +106,7 @@ TPoolAllocator* PerProcessGPA = 0; bool InitializeSymbolTable(const TString& builtIns, int version, EProfile profile, EShLanguage language, TInfoSink& infoSink, TSymbolTable& symbolTable) { - TIntermediate intermediate(version, profile); + TIntermediate intermediate(language, version, profile); TParseContext parseContext(symbolTable, intermediate, true, version, profile, language, infoSink); TPpContext ppContext(parseContext); @@ -452,7 +452,7 @@ bool CompileDeferred( bool ret = parseContext.parseShaderStrings(ppContext, const_cast(shaderStrings), lengths, numStrings); if (! ret) success = false; - intermediate.addSymbolLinkageNodes(intermediate.getTreeRoot(), parseContext.linkage, parseContext.language, symbolTable); + intermediate.addSymbolLinkageNodes(parseContext.linkage, parseContext.language, symbolTable); // Clean up the symbol table. The AST is self-sufficient now. delete symbolTableMemory; @@ -595,7 +595,7 @@ int ShCompile( compiler->infoSink.info.erase(); compiler->infoSink.debug.erase(); - TIntermediate intermediate; + TIntermediate intermediate(compiler->getLanguage()); bool success = CompileDeferred(compiler, shaderStrings, numStrings, inputLengths, optLevel, resources, defaultVersion, forwardCompatible, messages, intermediate); // @@ -866,7 +866,7 @@ TShader::TShader(EShLanguage s) { infoSink = new TInfoSink; compiler = new TDeferredCompiler(stage, *infoSink); - intermediate = new TIntermediate; + intermediate = new TIntermediate(s); } TShader::~TShader() @@ -941,7 +941,7 @@ bool TProgram::linkStage(EShLanguage stage, EShMessages messages) if (stages[stage].size() == 1) merged = stages[stage].front()->intermediate; else { - intermediate[stage] = new TIntermediate(); + intermediate[stage] = new TIntermediate(stage); merged = intermediate[stage]; } @@ -950,7 +950,7 @@ bool TProgram::linkStage(EShLanguage stage, EShMessages messages) if (stages[stage].size() > 1) { std::list::const_iterator it; for (it = stages[stage].begin(); it != stages[stage].end(); ++it) - merged->merge(*(*it)->intermediate); + merged->merge(*infoSink, *(*it)->intermediate); if (messages & EShMsgAST) merged->outputTree(*infoSink); diff --git a/glslang/MachineIndependent/localintermediate.h b/glslang/MachineIndependent/localintermediate.h index e32b4fd..9b92244 100644 --- a/glslang/MachineIndependent/localintermediate.h +++ b/glslang/MachineIndependent/localintermediate.h @@ -56,7 +56,7 @@ class TVariable; // class TIntermediate { public: - explicit TIntermediate(int v = 0, EProfile p = ENoProfile) : treeRoot(0), profile(p), version(v), numMains(0), numErrors(0) { } + explicit TIntermediate(EShLanguage l, int v = 0, EProfile p = ENoProfile) : language(l), treeRoot(0), profile(p), version(v), numMains(0), numErrors(0) { } void setVersion(int v) { version = v; } int getVersion() const { return version; } @@ -95,20 +95,24 @@ public: TIntermBranch* addBranch(TOperator, TIntermTyped*, TSourceLoc); TIntermTyped* addSwizzle(TVectorFields&, TSourceLoc); bool postProcess(TIntermNode*, EShLanguage); - void addSymbolLinkageNodes(TIntermNode* root, TIntermAggregate*& linkage, EShLanguage, TSymbolTable&); + void addSymbolLinkageNodes(TIntermAggregate*& linkage, EShLanguage, TSymbolTable&); void addSymbolLinkageNode(TIntermAggregate*& linkage, TSymbolTable&, const TString&); void addSymbolLinkageNode(TIntermAggregate*& linkage, const TVariable&); - void merge(TIntermediate&); - void errorCheck(TInfoSink& infoSink); + void merge(TInfoSink&, TIntermediate&); + void errorCheck(TInfoSink&); - void outputTree(TInfoSink& infoSink); + void outputTree(TInfoSink&); void removeTree(); protected: + void mergeBodies(TInfoSink&, TIntermSequence& globals, const TIntermSequence& unitGlobals); + void mergeLinkerObjects(TInfoSink&, TIntermSequence& linkerObjects, const TIntermSequence& unitLinkerObjects); void error(TInfoSink& infoSink, const char*); + void linkErrorCheck(TInfoSink&, const TIntermSymbol&, const TIntermSymbol&, bool crossStage); protected: + EShLanguage language; TIntermNode* treeRoot; EProfile profile; int version;