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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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: '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 @@
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 @@
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 @@
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 @@
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: '' : 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 @@
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 @@
}
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 @@
$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 @@
- 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 @@
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 @@
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 @@
}
//
-// 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 @@
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 @@
//
// 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::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 @@
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 @@
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 ret = parseContext.parseShaderStrings(ppContext, const_cast<char**>(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 @@
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 @@
{
infoSink = new TInfoSink;
compiler = new TDeferredCompiler(stage, *infoSink);
- intermediate = new TIntermediate;
+ intermediate = new TIntermediate(s);
}
TShader::~TShader()
@@ -941,7 +941,7 @@
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 @@
if (stages[stage].size() > 1) {
std::list<TShader*>::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 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 @@
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;