From 0d22e31c7576e0f80bea07b9bd265b633ff3c066 Mon Sep 17 00:00:00 2001 From: John Kessenich <cepheus@frii.com> Date: Wed, 30 Oct 2013 23:17:34 +0000 Subject: [PATCH] Implement 1.20 style function signature matching under implicit conversion. This was the last key unimplemented feature of versions 120 through 330. git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@23798 e7fa87d3-cd2b-0410-9028-fcbf551c1848 --- Test/120.vert | 59 ++++++++++ Test/baseResults/120.frag.out | 1 - Test/baseResults/120.vert.out | 102 +++++++++++++++- Test/baseResults/always-discard.frag.out | 1 - Test/baseResults/always-discard2.frag.out | 1 - Test/baseResults/conditionalDiscard.frag.out | 1 - Test/baseResults/cppIndent.vert.out | 1 - Test/baseResults/cppNest.vert.out | 1 - Test/baseResults/cppSimple.vert.out | 1 - Test/baseResults/decls.frag.out | 1 - Test/baseResults/deepRvalue.frag.out | 1 - Test/baseResults/discard-dce.frag.out | 1 - Test/baseResults/doWhileLoop.frag.out | 1 - Test/baseResults/earlyReturnDiscard.frag.out | 1 - Test/baseResults/empty.frag.out | 1 - Test/baseResults/flowControl.frag.out | 1 - Test/baseResults/forLoop.frag.out | 1 - Test/baseResults/forwardRef.frag.out | 1 - Test/baseResults/length.frag.out | 1 - Test/baseResults/mains1.frag.out | 2 - Test/baseResults/matrixError.vert.out | 1 - Test/baseResults/nonSquare.vert.out | 1 - Test/baseResults/sample.frag.out | 1 - Test/baseResults/sample.vert.out | 1 - Test/baseResults/swizzle.frag.out | 1 - Test/baseResults/syntaxError.frag.out | 1 - Test/baseResults/test.frag.out | 1 - Test/baseResults/versionsErrors.frag.out | 1 - Test/baseResults/voidFunction.frag.out | 1 - Test/baseResults/whileLoop.frag.out | 1 - Todo.txt | 2 +- glslang/Include/Types.h | 22 +++- glslang/MachineIndependent/ParseHelper.cpp | 116 ++++++++++++++++--- glslang/MachineIndependent/ParseHelper.h | 5 +- glslang/MachineIndependent/ShaderLang.cpp | 5 +- glslang/MachineIndependent/SymbolTable.h | 36 +++++- 36 files changed, 317 insertions(+), 59 deletions(-) diff --git a/Test/120.vert b/Test/120.vert index 9c31d1ac7..b1f69480e 100644 --- a/Test/120.vert +++ b/Test/120.vert @@ -51,3 +51,62 @@ int[2][3] foo( // ERROR float[2][3] a, // ERROR float[2] b[3], // ERROR float c[2][3]); // ERROR + +int overloadA(in float f); +int overloadA(out float f); // ERROR, different qualifiers +float overloadA(float); // ERROR, different return value for same signature +float overloadA(out float f, int); +float overloadA(int i); + +vec2 overloadB(float, float); + +vec2 overloadC(int, int); +vec2 overloadC(int, float); +vec2 overloadC(float, int); +vec2 overloadC(vec2, vec2); + +vec3 overloadD(int, float); +vec3 overloadD(float, int); + +vec3 overloadE(float[2]); +vec3 overloadE(mat2 m); +vec3 overloadE(vec2 v); + +void foo() +{ + float f; + int i; + + overloadB(f, f); + overloadB(f, 2); + overloadB(1, i); + + overloadC(1, i); + overloadC(vec2(1), vec2(2)); + overloadC(f, 3.0); // ERROR, no way + overloadC(ivec2(1), vec2(2)); + + overloadD(i, f); + overloadD(f, i); + overloadD(i, i); // ERROR, ambiguous + + int overloadB; // hiding + overloadB(1, i); // ERROR + + sin(1); + texture2D(s2D, ivec2(0)); + clamp(attv4, 0, 1); + clamp(ivec4(attv4), 0, 1); + + int a[2]; + overloadC(a, 3); // ERROR + overloadE(a); // ERROR + overloadE(3.3); // ERROR + overloadE(vec2(3.3)); + overloadE(mat2(0.5)); + overloadE(ivec4(1)); // ERROR + overloadE(ivec2(1)); + + float b[2]; + overloadE(b); +} diff --git a/Test/baseResults/120.frag.out b/Test/baseResults/120.frag.out index a550fee2e..3b8bd701d 100644 --- a/Test/baseResults/120.frag.out +++ b/Test/baseResults/120.frag.out @@ -1,4 +1,3 @@ -Warning, version 120 is not yet complete; most features are present, but a few are missing. ERROR: 0:9: 'in for stage inputs' : not supported for this version or the enabled extensions ERROR: 0:10: 'out for stage outputs' : not supported for this version or the enabled extensions ERROR: 0:54: '+' : wrong operand types: no operation '+' exists that takes a left-hand operand of type '2-component vector of float' and a right operand of type '3-component vector of float' (or there is no acceptable conversion) diff --git a/Test/baseResults/120.vert.out b/Test/baseResults/120.vert.out index 9f499f87b..851bbf017 100644 --- a/Test/baseResults/120.vert.out +++ b/Test/baseResults/120.vert.out @@ -1,4 +1,3 @@ -Warning, version 120 is not yet complete; most features are present, but a few are missing. ERROR: 0:3: 'in for stage inputs' : not supported for this version or the enabled extensions ERROR: 0:4: 'out for stage outputs' : not supported for this version or the enabled extensions ERROR: 0:11: 'gl_Position' : cannot add storage, auxiliary, memory, interpolation, or precision qualifier to an existing variable @@ -33,7 +32,15 @@ ERROR: 0:50: 'arrays of arrays' : not supported with this profile: none ERROR: 0:51: 'arrays of arrays' : not supported with this profile: none ERROR: 0:52: 'arrays of arrays' : not supported with this profile: none ERROR: 0:53: 'arrays of arrays' : not supported with this profile: none -ERROR: 34 compilation errors. No code generated. +ERROR: 0:56: 'out' : overloaded functions must have the same parameter qualifiers +ERROR: 0:57: 'float' : overloaded functions must have the same return type +ERROR: 0:86: 'overloadC' : no matching overloaded function found +ERROR: 0:91: 'overloadD' : ambiguous function signature match: multiple signatures match under implicit type conversion +ERROR: 0:102: 'overloadC' : no matching overloaded function found +ERROR: 0:103: 'overloadE' : no matching overloaded function found +ERROR: 0:104: 'overloadE' : no matching overloaded function found +ERROR: 0:107: 'overloadE' : no matching overloaded function found +ERROR: 42 compilation errors. No code generated. ERROR: node is still EOpNull! 0:15 Function Definition: main( (void) @@ -81,6 +88,97 @@ ERROR: node is still EOpNull! 0:43 'gl_PointSize' (invariant gl_PointSize float) 0:43 Constant: 0:43 3.800000 +0:75 Function Definition: foo( (void) +0:75 Function Parameters: +0:? Sequence +0:80 Function Call: overloadB(f1;f1; (2-component vector of float) +0:80 'f' (float) +0:80 'f' (float) +0:81 Function Call: overloadB(f1;f1; (2-component vector of float) +0:81 'f' (float) +0:81 Constant: +0:81 2 (const int) +0:82 Function Call: overloadB(f1;f1; (2-component vector of float) +0:82 Constant: +0:82 1 (const int) +0:82 'i' (int) +0:84 Function Call: overloadC(i1;i1; (2-component vector of float) +0:84 Constant: +0:84 1 (const int) +0:84 'i' (int) +0:85 Function Call: overloadC(vf2;vf2; (2-component vector of float) +0:85 Constant: +0:85 1.000000 +0:85 1.000000 +0:85 Constant: +0:85 2.000000 +0:85 2.000000 +0:86 Constant: +0:86 0.000000 +0:87 Function Call: overloadC(vf2;vf2; (2-component vector of float) +0:87 Constant: +0:87 1 (const int) +0:87 1 (const int) +0:87 Constant: +0:87 2.000000 +0:87 2.000000 +0:89 Function Call: overloadD(i1;f1; (3-component vector of float) +0:89 'i' (int) +0:89 'f' (float) +0:90 Function Call: overloadD(f1;i1; (3-component vector of float) +0:90 'f' (float) +0:90 'i' (int) +0:91 Function Call: overloadD(f1;i1; (3-component vector of float) +0:91 'i' (int) +0:91 'i' (int) +0:94 Function Call: overloadB(f1;f1; (2-component vector of float) +0:94 Constant: +0:94 1 (const int) +0:94 'i' (int) +0:96 Constant: +0:96 0.000000 +0:97 Function Call: texture2D(s21;vf2; (4-component vector of float) +0:97 's2D' (uniform sampler2D) +0:97 Constant: +0:97 0 (const int) +0:97 0 (const int) +0:98 clamp (4-component vector of float) +0:98 'attv4' (in 4-component vector of float) +0:98 Constant: +0:98 0 (const int) +0:98 Constant: +0:98 1 (const int) +0:99 clamp (4-component vector of float) +0:99 Convert float to int (4-component vector of int) +0:99 'attv4' (in 4-component vector of float) +0:99 Constant: +0:99 0 (const int) +0:99 Constant: +0:99 1 (const int) +0:102 Constant: +0:102 0.000000 +0:103 Constant: +0:103 0.000000 +0:104 Constant: +0:104 0.000000 +0:105 Function Call: overloadE(vf2; (3-component vector of float) +0:105 Constant: +0:105 3.300000 +0:105 3.300000 +0:106 Function Call: overloadE(mf22; (3-component vector of float) +0:106 Constant: +0:106 0.500000 +0:106 0.000000 +0:106 0.000000 +0:106 0.500000 +0:107 Constant: +0:107 0.000000 +0:108 Function Call: overloadE(vf2; (3-component vector of float) +0:108 Constant: +0:108 1 (const int) +0:108 1 (const int) +0:111 Function Call: overloadE(f1[2]; (3-component vector of float) +0:111 'b' (2-element array of float) 0:? Linker Objects 0:? 'i' (in 4-component vector of float) 0:? 'o' (smooth out 4-component vector of float) diff --git a/Test/baseResults/always-discard.frag.out b/Test/baseResults/always-discard.frag.out index 76055e5f2..579e3ec50 100644 --- a/Test/baseResults/always-discard.frag.out +++ b/Test/baseResults/always-discard.frag.out @@ -1,4 +1,3 @@ -Warning, version 110 is not yet complete; most features are present, but a few are missing. 0:? Sequence 0:4 Function Definition: main( (void) 0:4 Function Parameters: diff --git a/Test/baseResults/always-discard2.frag.out b/Test/baseResults/always-discard2.frag.out index 724c8aecc..401fab76f 100644 --- a/Test/baseResults/always-discard2.frag.out +++ b/Test/baseResults/always-discard2.frag.out @@ -1,4 +1,3 @@ -Warning, version 110 is not yet complete; most features are present, but a few are missing. 0:? Sequence 0:4 Function Definition: main( (void) 0:4 Function Parameters: diff --git a/Test/baseResults/conditionalDiscard.frag.out b/Test/baseResults/conditionalDiscard.frag.out index 1d3359b9d..a4c3e6c25 100644 --- a/Test/baseResults/conditionalDiscard.frag.out +++ b/Test/baseResults/conditionalDiscard.frag.out @@ -1,4 +1,3 @@ -Warning, version 110 is not yet complete; most features are present, but a few are missing. 0:? Sequence 0:6 Function Definition: main( (void) 0:6 Function Parameters: diff --git a/Test/baseResults/cppIndent.vert.out b/Test/baseResults/cppIndent.vert.out index 93c643a7d..221640e41 100644 --- a/Test/baseResults/cppIndent.vert.out +++ b/Test/baseResults/cppIndent.vert.out @@ -1,4 +1,3 @@ -Warning, version 110 is not yet complete; most features are present, but a few are missing. 0:? Sequence 0:5 Sequence 0:5 move second child to first child (float) diff --git a/Test/baseResults/cppNest.vert.out b/Test/baseResults/cppNest.vert.out index 60255be6e..918f832e0 100644 --- a/Test/baseResults/cppNest.vert.out +++ b/Test/baseResults/cppNest.vert.out @@ -1,4 +1,3 @@ -Warning, version 110 is not yet complete; most features are present, but a few are missing. 0:? Sequence 0:5 Sequence 0:5 move second child to first child (float) diff --git a/Test/baseResults/cppSimple.vert.out b/Test/baseResults/cppSimple.vert.out index 48dfcff90..89201f1a4 100644 --- a/Test/baseResults/cppSimple.vert.out +++ b/Test/baseResults/cppSimple.vert.out @@ -1,4 +1,3 @@ -Warning, version 110 is not yet complete; most features are present, but a few are missing. ERROR: 0:77: '#error' : good1 ERROR: 0:81: '#error' : good2 ERROR: 0:85: '#error' : good3 diff --git a/Test/baseResults/decls.frag.out b/Test/baseResults/decls.frag.out index 6e11cfff0..f965ed910 100644 --- a/Test/baseResults/decls.frag.out +++ b/Test/baseResults/decls.frag.out @@ -1,4 +1,3 @@ -Warning, version 120 is not yet complete; most features are present, but a few are missing. ERROR: 0:19: 'vi4' : illegal use of type 'void' ERROR: 0:20: 'vj' : illegal use of type 'void' ERROR: 0:20: 'vk5' : illegal use of type 'void' diff --git a/Test/baseResults/deepRvalue.frag.out b/Test/baseResults/deepRvalue.frag.out index 97a20f8bd..a1281944d 100644 --- a/Test/baseResults/deepRvalue.frag.out +++ b/Test/baseResults/deepRvalue.frag.out @@ -1,4 +1,3 @@ -Warning, version 120 is not yet complete; most features are present, but a few are missing. 0:? Sequence 0:5 Sequence 0:5 move second child to first child (4-component vector of float) diff --git a/Test/baseResults/discard-dce.frag.out b/Test/baseResults/discard-dce.frag.out index 6cc24a01e..97f012bce 100644 --- a/Test/baseResults/discard-dce.frag.out +++ b/Test/baseResults/discard-dce.frag.out @@ -1,4 +1,3 @@ -Warning, version 110 is not yet complete; most features are present, but a few are missing. 0:? Sequence 0:4 Function Definition: main( (void) 0:4 Function Parameters: diff --git a/Test/baseResults/doWhileLoop.frag.out b/Test/baseResults/doWhileLoop.frag.out index 7071474ed..32956c44f 100644 --- a/Test/baseResults/doWhileLoop.frag.out +++ b/Test/baseResults/doWhileLoop.frag.out @@ -1,4 +1,3 @@ -Warning, version 110 is not yet complete; most features are present, but a few are missing. 0:? Sequence 0:7 Function Definition: main( (void) 0:7 Function Parameters: diff --git a/Test/baseResults/earlyReturnDiscard.frag.out b/Test/baseResults/earlyReturnDiscard.frag.out index 3b6144bed..288f55efb 100644 --- a/Test/baseResults/earlyReturnDiscard.frag.out +++ b/Test/baseResults/earlyReturnDiscard.frag.out @@ -1,4 +1,3 @@ -Warning, version 110 is not yet complete; most features are present, but a few are missing. 0:? Sequence 0:19 Function Definition: main( (void) 0:19 Function Parameters: diff --git a/Test/baseResults/empty.frag.out b/Test/baseResults/empty.frag.out index fa91cf3bb..a17d25409 100644 --- a/Test/baseResults/empty.frag.out +++ b/Test/baseResults/empty.frag.out @@ -11,7 +11,6 @@ WARNING: #version: statement missing; use #version on first line of shader 0:? Linker Objects empty3.frag -Warning, version 110 is not yet complete; most features are present, but a few are missing. 0:? Sequence 0:? Linker Objects diff --git a/Test/baseResults/flowControl.frag.out b/Test/baseResults/flowControl.frag.out index d237e726c..606671d13 100644 --- a/Test/baseResults/flowControl.frag.out +++ b/Test/baseResults/flowControl.frag.out @@ -1,4 +1,3 @@ -Warning, version 120 is not yet complete; most features are present, but a few are missing. 0:? Sequence 0:10 Function Definition: main( (void) 0:10 Function Parameters: diff --git a/Test/baseResults/forLoop.frag.out b/Test/baseResults/forLoop.frag.out index 4fec57932..5db7911f2 100644 --- a/Test/baseResults/forLoop.frag.out +++ b/Test/baseResults/forLoop.frag.out @@ -1,4 +1,3 @@ -Warning, version 120 is not yet complete; most features are present, but a few are missing. 0:? Sequence 0:8 Function Definition: main( (void) 0:8 Function Parameters: diff --git a/Test/baseResults/forwardRef.frag.out b/Test/baseResults/forwardRef.frag.out index 6ea65d762..d63454a90 100644 --- a/Test/baseResults/forwardRef.frag.out +++ b/Test/baseResults/forwardRef.frag.out @@ -1,4 +1,3 @@ -Warning, version 110 is not yet complete; most features are present, but a few are missing. 0:? Sequence 0:11 Function Definition: main( (void) 0:11 Function Parameters: diff --git a/Test/baseResults/length.frag.out b/Test/baseResults/length.frag.out index b51af1706..0543e1571 100644 --- a/Test/baseResults/length.frag.out +++ b/Test/baseResults/length.frag.out @@ -1,4 +1,3 @@ -Warning, version 120 is not yet complete; most features are present, but a few are missing. 0:? Sequence 0:11 Function Definition: main( (void) 0:11 Function Parameters: diff --git a/Test/baseResults/mains1.frag.out b/Test/baseResults/mains1.frag.out index 43dba1490..723d725d1 100644 --- a/Test/baseResults/mains1.frag.out +++ b/Test/baseResults/mains1.frag.out @@ -1,5 +1,4 @@ mains1.frag -Warning, version 110 is not yet complete; most features are present, but a few are missing. 0:? Sequence 0:3 Function Definition: main( (void) @@ -7,7 +6,6 @@ Warning, version 110 is not yet complete; most features are present, but a few a 0:? Linker Objects mains2.frag -Warning, version 110 is not yet complete; most features are present, but a few are missing. 0:? Sequence 0:3 Function Definition: main( (void) diff --git a/Test/baseResults/matrixError.vert.out b/Test/baseResults/matrixError.vert.out index fa5a82bd9..70bdae84a 100644 --- a/Test/baseResults/matrixError.vert.out +++ b/Test/baseResults/matrixError.vert.out @@ -1,4 +1,3 @@ -Warning, version 120 is not yet complete; most features are present, but a few are missing. ERROR: 0:10: 'constructor' : too many arguments ERROR: 0:7: 'const' : non-matching or non-convertible constant type for const initializer ERROR: 0:17: 'assign' : cannot convert from '2-component vector of float' to '3-component vector of float' diff --git a/Test/baseResults/nonSquare.vert.out b/Test/baseResults/nonSquare.vert.out index 5257200f8..6b1961dd1 100644 --- a/Test/baseResults/nonSquare.vert.out +++ b/Test/baseResults/nonSquare.vert.out @@ -1,4 +1,3 @@ -Warning, version 120 is not yet complete; most features are present, but a few are missing. 0:? Sequence 0:15 Function Definition: main( (void) 0:15 Function Parameters: diff --git a/Test/baseResults/sample.frag.out b/Test/baseResults/sample.frag.out index 13c8679c4..0e85f8e96 100644 --- a/Test/baseResults/sample.frag.out +++ b/Test/baseResults/sample.frag.out @@ -1,4 +1,3 @@ -Warning, version 110 is not yet complete; most features are present, but a few are missing. 0:? Sequence 0:38 Function Definition: main( (void) 0:38 Function Parameters: diff --git a/Test/baseResults/sample.vert.out b/Test/baseResults/sample.vert.out index 29e3a05c4..e7942be44 100644 --- a/Test/baseResults/sample.vert.out +++ b/Test/baseResults/sample.vert.out @@ -1,4 +1,3 @@ -Warning, version 110 is not yet complete; most features are present, but a few are missing. 0:? Sequence 0:38 Function Definition: main( (void) 0:38 Function Parameters: diff --git a/Test/baseResults/swizzle.frag.out b/Test/baseResults/swizzle.frag.out index 3f1b94719..e6b3a9342 100644 --- a/Test/baseResults/swizzle.frag.out +++ b/Test/baseResults/swizzle.frag.out @@ -1,4 +1,3 @@ -Warning, version 110 is not yet complete; most features are present, but a few are missing. 0:? Sequence 0:9 Function Definition: main( (void) 0:9 Function Parameters: diff --git a/Test/baseResults/syntaxError.frag.out b/Test/baseResults/syntaxError.frag.out index f8264de07..54df81398 100644 --- a/Test/baseResults/syntaxError.frag.out +++ b/Test/baseResults/syntaxError.frag.out @@ -1,4 +1,3 @@ -Warning, version 120 is not yet complete; most features are present, but a few are missing. ERROR: 0:9: 'vec5' : undeclared identifier ERROR: 0:9: '' : syntax error ERROR: 2 compilation errors. No code generated. diff --git a/Test/baseResults/test.frag.out b/Test/baseResults/test.frag.out index 9e2a28917..74bf27089 100644 --- a/Test/baseResults/test.frag.out +++ b/Test/baseResults/test.frag.out @@ -1,4 +1,3 @@ -Warning, version 110 is not yet complete; most features are present, but a few are missing. 0:? Sequence 0:13 Function Definition: main( (void) 0:13 Function Parameters: diff --git a/Test/baseResults/versionsErrors.frag.out b/Test/baseResults/versionsErrors.frag.out index 6a5f61a35..b339567bb 100644 --- a/Test/baseResults/versionsErrors.frag.out +++ b/Test/baseResults/versionsErrors.frag.out @@ -1,5 +1,4 @@ ERROR: #version: versions before 150 do not allow a profile token -Warning, version 110 is not yet complete; most features are present, but a few are missing. ERROR: 0:38: 'attribute' : not supported in this stage: fragment ERROR: 0:40: 'sampler2DRect' : Reserved word. ERROR: 0:40: 'rectangle texture' : not supported for this version or the enabled extensions diff --git a/Test/baseResults/voidFunction.frag.out b/Test/baseResults/voidFunction.frag.out index 5cc5d1eea..4b62cd21f 100644 --- a/Test/baseResults/voidFunction.frag.out +++ b/Test/baseResults/voidFunction.frag.out @@ -1,4 +1,3 @@ -Warning, version 120 is not yet complete; most features are present, but a few are missing. 0:? Sequence 0:7 Sequence 0:7 move second child to first child (float) diff --git a/Test/baseResults/whileLoop.frag.out b/Test/baseResults/whileLoop.frag.out index 4300f1811..7b25a0c3f 100644 --- a/Test/baseResults/whileLoop.frag.out +++ b/Test/baseResults/whileLoop.frag.out @@ -1,4 +1,3 @@ -Warning, version 110 is not yet complete; most features are present, but a few are missing. 0:? Sequence 0:7 Function Definition: main( (void) 0:7 Function Parameters: diff --git a/Todo.txt b/Todo.txt index 1e6be183a..f3ce5b491 100644 --- a/Todo.txt +++ b/Todo.txt @@ -57,7 +57,7 @@ Shader Functionality to Implement/Finish GLSL 1.2 + Handle multiple compilation units per stage + Allow initializers on uniform declarations - - signature matching takes type conversions into account, ambiguity is an error + + signature matching takes type conversions into account, ambiguity is an error - allow constructors to contain non-dereferenced arrays? GLSL 1.3 . flat is for both user and predeclared built-in in/out variables diff --git a/glslang/Include/Types.h b/glslang/Include/Types.h index e7e4bc37c..9ca44076c 100644 --- a/glslang/Include/Types.h +++ b/glslang/Include/Types.h @@ -846,20 +846,30 @@ public: // See if two types match, in all aspects except arrayness bool sameElementType(const TType& right) const { - return basicType == right.basicType && - sampler == right.sampler && + return basicType == right.basicType && sameElementShape(right); + } + + // See if two type's arrayness match + bool sameArrayness(const TType& right) const + { + return ((arraySizes == 0 && right.arraySizes == 0) || + (arraySizes && right.arraySizes && arraySizes->sizes == right.arraySizes->sizes)); + } + + // See if two type's elements match in all ways except basic type + bool sameElementShape(const TType& right) const + { + return sampler == right.sampler && vectorSize == right.vectorSize && matrixCols == right.matrixCols && matrixRows == right.matrixRows && sameStructType(right); } - // See if two types match in all ways (just the actual type, not qualification + // See if two types match in all ways (just the actual type, not qualification) bool operator==(const TType& right) const { - return sameElementType(right) && - ((arraySizes == 0 && right.arraySizes == 0) || - (arraySizes && right.arraySizes && arraySizes->sizes == right.arraySizes->sizes)); + return sameElementType(right) && sameArrayness(right); } bool operator!=(const TType& right) const diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index 14c92a5f8..c46b7e4de 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -829,7 +829,13 @@ TIntermAggregate* TParseContext::handleFunctionPrototype(TSourceLoc loc, TFuncti } // -// Handle seeing a function call in the grammar. +// Handle seeing function call syntax in the grammar, which could be any of +// - .length() method +// - constructor +// - a call to a built-in function mapped to an operator +// - a call to a built-in function that will remain a function call (e.g., texturing) +// - user function +// - subroutine call (not implemented yet) // TIntermTyped* TParseContext::handleFunctionCall(TSourceLoc loc, TFunction* fnCall, TIntermNode* intermNode, TIntermAggregate* intermAggregate) { @@ -866,11 +872,11 @@ TIntermTyped* TParseContext::handleFunctionCall(TSourceLoc loc, TFunction* fnCal } } else { // - // Not a constructor. Find it in the symbol table. + // Find it in the symbol table. // const TFunction* fnCandidate; bool builtIn; - fnCandidate = findFunction(loc, fnCall, &builtIn); + fnCandidate = findFunction(loc, *fnCall, builtIn); if (fnCandidate) { // // A declared function. But, it might still map to a built-in @@ -898,6 +904,7 @@ TIntermTyped* TParseContext::handleFunctionCall(TSourceLoc loc, TFunction* fnCal intermediate.addToCallGraph(infoSink, currentCaller, fnCandidate->getMangledName()); } + // Make sure storage qualifications work for these arguments. TStorageQualifier qual; TQualifierList& qualifierList = result->getAsAggregate()->getQualifierList(); for (int i = 0; i < fnCandidate->getParamCount(); ++i) { @@ -912,12 +919,6 @@ TIntermTyped* TParseContext::handleFunctionCall(TSourceLoc loc, TFunction* fnCal if (builtIn) nonOpBuiltInCheck(loc, *fnCandidate, result->getAsAggregate()); } - } else { - // error message was put out by PaFindFunction() - // Put on a dummy node for error recovery - TConstUnionArray unionArray(1); - unionArray[0].setDConst(0.0); - result = intermediate.addConstantUnion(unionArray, TType(EbtFloat, EvqConst), loc); } } @@ -2543,24 +2544,105 @@ void TParseContext::checkNoShaderLayouts(TSourceLoc loc, const TPublicType& publ // // Return the function symbol if found, otherwise 0. // -const TFunction* TParseContext::findFunction(TSourceLoc loc, TFunction* call, bool *builtIn) +const TFunction* TParseContext::findFunction(TSourceLoc loc, const TFunction& call, bool& builtIn) { - TSymbol* symbol = symbolTable.find(call->getMangledName(), builtIn); + const TFunction* function = 0; + + if (profile == EEsProfile || version < 120) + function = findFunctionExact(loc, call, builtIn); + else if (version < 400) + function = findFunction120(loc, call, builtIn); + else + function = findFunction400(loc, call, builtIn); + return function; +} + +// Function finding algorithm for ES and desktop 110. +const TFunction* TParseContext::findFunctionExact(TSourceLoc loc, const TFunction& call, bool& builtIn) +{ + const TFunction* function = 0; + + TSymbol* symbol = symbolTable.find(call.getMangledName(), &builtIn); if (symbol == 0) { - error(loc, "no matching overloaded function found", call->getName().c_str(), ""); + error(loc, "no matching overloaded function found", call.getName().c_str(), ""); return 0; } - const TFunction* function = symbol->getAsFunction(); - if (! function) { - error(loc, "function name expected", call->getName().c_str(), ""); + return symbol->getAsFunction(); +} - return 0; +// Function finding algorithm for desktop versions 120 through 330. +const TFunction* TParseContext::findFunction120(TSourceLoc loc, const TFunction& call, bool& builtIn) +{ + // first, look for an exact match + TSymbol* symbol = symbolTable.find(call.getMangledName(), &builtIn); + if (symbol) + return symbol->getAsFunction(); + + // exact match not found, look through a list of overloaded functions of the same name + + // "If no exact match is found, then [implicit conversions] will be applied to find a match. Mismatched types + // on input parameters (in or inout or default) must have a conversion from the calling argument type to the + // formal parameter type. Mismatched types on output parameters (out or inout) must have a conversion + // from the formal parameter type to the calling argument type. When argument conversions are used to find + // a match, it is a semantic error if there are multiple ways to apply these conversions to make the call match + // more than one function." + + const TFunction* candidate = 0; + TVector<TFunction*> candidateList; + symbolTable.findFunctionNameList(call.getMangledName(), candidateList, builtIn); + + int numPossibleMatches = 0; + for (TVector<TFunction*>::const_iterator it = candidateList.begin(); it != candidateList.end(); ++it) { + bool possibleMatch = true; + const TFunction& function = *(*it); + for (int i = 0; i < function.getParamCount(); ++i) { + // same types is easy + if (*function[i].type == *call[i].type) + continue; + + // We have a mismatch in type, see if it is implicitly convertible + + if (function[i].type->isArray() || call[i].type->isArray() || + ! function[i].type->sameElementShape(*call[i].type)) + possibleMatch = false; + else { + // do direction-specific checks for conversion of basic type + TStorageQualifier qualifier = function[i].type->getQualifier().storage; + if (qualifier == EvqIn || qualifier == EvqInOut) { + if (! intermediate.canImplicitlyPromote(call[i].type->getBasicType(), function[i].type->getBasicType())) + possibleMatch = false; + } + if (qualifier == EvqOut || qualifier == EvqInOut) { + if (! intermediate.canImplicitlyPromote(function[i].type->getBasicType(), call[i].type->getBasicType())) + possibleMatch = false; + } + } + if (! possibleMatch) + break; + } + if (possibleMatch) { + if (candidate) { + // our second match, meaning ambiguity + error(loc, "ambiguous function signature match: multiple signatures match under implicit type conversion", call.getName().c_str(), ""); + } else + candidate = &function; + } } - return function; + if (candidate == 0) + error(loc, "no matching overloaded function found", call.getName().c_str(), ""); + + return candidate; +} + +// Function finding algorithm for desktop version 400 and above. +const TFunction* TParseContext::findFunction400(TSourceLoc loc, const TFunction& call, bool& builtIn) +{ + // TODO: 4.00 functionality: findFunction400() + return findFunction120(loc, call, builtIn); } // diff --git a/glslang/MachineIndependent/ParseHelper.h b/glslang/MachineIndependent/ParseHelper.h index 4f9e0537d..7e499e7da 100644 --- a/glslang/MachineIndependent/ParseHelper.h +++ b/glslang/MachineIndependent/ParseHelper.h @@ -140,7 +140,10 @@ public: void layoutQualifierCheck(TSourceLoc, const TQualifier&); void checkNoShaderLayouts(TSourceLoc, const TPublicType&); - const TFunction* findFunction(TSourceLoc, TFunction* pfnCall, bool *builtIn = 0); + const TFunction* findFunction(TSourceLoc loc, const TFunction& call, bool& builtIn); + const TFunction* findFunctionExact(TSourceLoc loc, const TFunction& call, bool& builtIn); + const TFunction* findFunction120(TSourceLoc loc, const TFunction& call, bool& builtIn); + const TFunction* findFunction400(TSourceLoc loc, const TFunction& call, bool& builtIn); TIntermNode* declareVariable(TSourceLoc, TString& identifier, TPublicType&, TArraySizes* typeArray = 0, TIntermTyped* initializer = 0); TIntermTyped* addConstructor(TSourceLoc, TIntermNode*, const TType&, TOperator); TIntermTyped* constructStruct(TIntermNode*, const TType&, int, TSourceLoc); diff --git a/glslang/MachineIndependent/ShaderLang.cpp b/glslang/MachineIndependent/ShaderLang.cpp index 9f8bc17a5..407277674 100644 --- a/glslang/MachineIndependent/ShaderLang.cpp +++ b/glslang/MachineIndependent/ShaderLang.cpp @@ -378,10 +378,11 @@ bool DeduceVersionProfile(TInfoSink& infoSink, EShLanguage stage, bool versionNo switch(version) { case 100: case 300: - // versions are complete - break; + case 110: case 120: + // versions are complete + break; case 130: case 140: infoSink.info << "Warning, version " << version << " is not yet complete; most features are present, but a few are missing.\n"; diff --git a/glslang/MachineIndependent/SymbolTable.h b/glslang/MachineIndependent/SymbolTable.h index b71d62cdd..e51f9cee3 100644 --- a/glslang/MachineIndependent/SymbolTable.h +++ b/glslang/MachineIndependent/SymbolTable.h @@ -322,6 +322,19 @@ public: return (*it).second; } + void findFunctionNameList(const TString& name, TVector<TFunction*>& list) + { + size_t parenAt = name.find_first_of('('); + TString base(name, 0, parenAt + 1); + + tLevel::const_iterator begin = level.lower_bound(base); + base[parenAt] = ')'; // assume ')' is lexically after '(' + tLevel::const_iterator end = level.upper_bound(base); + for (tLevel::const_iterator it = begin; it != end; ++it) + list.push_back(it->second->getAsFunction()); + } + + // See if there is already a function in the table having the given non-function-style name. bool hasFunctionName(const TString& name) const { tLevel::const_iterator candidate = level.lower_bound(name); @@ -397,7 +410,7 @@ public: while (table.size() > adoptedLevels) pop(0); } - + void adoptLevels(TSymbolTable& symTable) { for (unsigned int level = 0; level < symTable.table.size(); ++level) { @@ -511,6 +524,27 @@ public: return symbol; } + void findFunctionNameList(const TString& name, TVector<TFunction*>& list, bool& builtIn) + { + // For user levels, return the set found in the first scope with a match + builtIn = false; + int level = currentLevel(); + do { + table[level]->findFunctionNameList(name, list); + --level; + } while (list.empty() && level >= globalLevel); + + if (! list.empty()) + return; + + // Gather across all built-in levels; they don't hide each other + builtIn = true; + do { + table[level]->findFunctionNameList(name, list); + --level; + } while (level >= 0); + } + void relateToOperator(const char* name, TOperator op) { for (unsigned int level = 0; level < table.size(); ++level) -- GitLab