Implement implicit conversions of function-call arguments (both in and out) as explicit conversions in the AST, through handleArgumentConversions().
Also - uniformly handle EvqConstReadOnly as an input argument in a function, with isParamInput() and isParamOutput() queries in TQualifier. - provide a makeTemporary() in TQualifier, for erasing original qualification when making a temp - provide a makeInternalVariable() call to make a shader variable not seen in the shader source git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@25912 e7fa87d3-cd2b-0410-9028-fcbf551c1848
This commit is contained in:
parent
e5d92eb194
commit
75694fdacd
@ -58,15 +58,15 @@ float overloadA(float); // ERROR, different return value for same sig
|
|||||||
float overloadA(out float f, int);
|
float overloadA(out float f, int);
|
||||||
float overloadA(int i);
|
float overloadA(int i);
|
||||||
|
|
||||||
vec2 overloadB(float, float);
|
void overloadB(float, const in float) { }
|
||||||
|
|
||||||
vec2 overloadC(int, int);
|
vec2 overloadC(int, int);
|
||||||
vec2 overloadC(int, float);
|
vec2 overloadC(const in int, float);
|
||||||
vec2 overloadC(float, int);
|
vec2 overloadC(float, int);
|
||||||
vec2 overloadC(vec2, vec2);
|
vec2 overloadC(vec2, vec2);
|
||||||
|
|
||||||
vec3 overloadD(int, float);
|
vec3 overloadD(int, float);
|
||||||
vec3 overloadD(float, int);
|
vec3 overloadD(float, in int);
|
||||||
|
|
||||||
vec3 overloadE(float[2]);
|
vec3 overloadE(float[2]);
|
||||||
vec3 overloadE(mat2 m);
|
vec3 overloadE(mat2 m);
|
||||||
@ -119,3 +119,21 @@ void foo()
|
|||||||
}
|
}
|
||||||
|
|
||||||
varying vec4 gl_TexCoord[35]; // ERROR, size too big
|
varying vec4 gl_TexCoord[35]; // ERROR, size too big
|
||||||
|
|
||||||
|
// tests for output conversions
|
||||||
|
void outFun(in float, out ivec2, in int, out float);
|
||||||
|
int outFunRet(in float, out int, const in int, out ivec4);
|
||||||
|
ivec2 outFunRet(in float, out ivec4, in int, out ivec4);
|
||||||
|
|
||||||
|
void foo2()
|
||||||
|
{
|
||||||
|
vec2 v2;
|
||||||
|
vec4 v4;
|
||||||
|
float f;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
outFun(i, v2, i, f);
|
||||||
|
outFunRet(i, f, i, v4);
|
||||||
|
float ret = outFunRet(i, f, i, v4);
|
||||||
|
vec2 ret2 = outFunRet(i, v4, i, v4);
|
||||||
|
}
|
||||||
|
|||||||
@ -94,19 +94,24 @@ ERROR: node is still EOpNull!
|
|||||||
0:43 'gl_PointSize' (invariant gl_PointSize float)
|
0:43 'gl_PointSize' (invariant gl_PointSize float)
|
||||||
0:43 Constant:
|
0:43 Constant:
|
||||||
0:43 3.800000
|
0:43 3.800000
|
||||||
|
0:61 Function Definition: overloadB(f1;f1; (void)
|
||||||
|
0:61 Function Parameters:
|
||||||
|
0:61 '' (in float)
|
||||||
|
0:61 '' (const (read only) float)
|
||||||
0:78 Function Definition: foo( (void)
|
0:78 Function Definition: foo( (void)
|
||||||
0:78 Function Parameters:
|
0:78 Function Parameters:
|
||||||
0:? Sequence
|
0:? Sequence
|
||||||
0:83 Function Call: overloadB(f1;f1; (2-component vector of float)
|
0:83 Function Call: overloadB(f1;f1; (void)
|
||||||
0:83 'f' (float)
|
0:83 'f' (float)
|
||||||
0:83 'f' (float)
|
0:83 'f' (float)
|
||||||
0:84 Function Call: overloadB(f1;f1; (2-component vector of float)
|
0:84 Function Call: overloadB(f1;f1; (void)
|
||||||
0:84 'f' (float)
|
0:84 'f' (float)
|
||||||
0:84 Constant:
|
0:84 Constant:
|
||||||
0:84 2 (const int)
|
0:84 2.000000
|
||||||
0:85 Function Call: overloadB(f1;f1; (2-component vector of float)
|
0:85 Function Call: overloadB(f1;f1; (void)
|
||||||
0:85 Constant:
|
0:85 Constant:
|
||||||
0:85 1 (const int)
|
0:85 1.000000
|
||||||
|
0:85 Convert int to float (float)
|
||||||
0:85 'i' (int)
|
0:85 'i' (int)
|
||||||
0:87 Constant:
|
0:87 Constant:
|
||||||
0:87 0.000000
|
0:87 0.000000
|
||||||
@ -125,8 +130,8 @@ ERROR: node is still EOpNull!
|
|||||||
0:90 0.000000
|
0:90 0.000000
|
||||||
0:91 Function Call: overloadC(vf2;vf2; (2-component vector of float)
|
0:91 Function Call: overloadC(vf2;vf2; (2-component vector of float)
|
||||||
0:91 Constant:
|
0:91 Constant:
|
||||||
0:91 1 (const int)
|
0:91 1.000000
|
||||||
0:91 1 (const int)
|
0:91 1.000000
|
||||||
0:91 Constant:
|
0:91 Constant:
|
||||||
0:91 2.000000
|
0:91 2.000000
|
||||||
0:91 2.000000
|
0:91 2.000000
|
||||||
@ -137,6 +142,7 @@ ERROR: node is still EOpNull!
|
|||||||
0:94 'f' (float)
|
0:94 'f' (float)
|
||||||
0:94 'i' (int)
|
0:94 'i' (int)
|
||||||
0:95 Function Call: overloadD(f1;i1; (3-component vector of float)
|
0:95 Function Call: overloadD(f1;i1; (3-component vector of float)
|
||||||
|
0:95 Convert int to float (float)
|
||||||
0:95 'i' (int)
|
0:95 'i' (int)
|
||||||
0:95 'i' (int)
|
0:95 'i' (int)
|
||||||
0:98 Constant:
|
0:98 Constant:
|
||||||
@ -146,8 +152,8 @@ ERROR: node is still EOpNull!
|
|||||||
0:101 Function Call: texture2D(s21;vf2; (4-component vector of float)
|
0:101 Function Call: texture2D(s21;vf2; (4-component vector of float)
|
||||||
0:101 's2D' (uniform sampler2D)
|
0:101 's2D' (uniform sampler2D)
|
||||||
0:101 Constant:
|
0:101 Constant:
|
||||||
0:101 0 (const int)
|
0:101 0.000000
|
||||||
0:101 0 (const int)
|
0:101 0.000000
|
||||||
0:102 clamp (4-component vector of float)
|
0:102 clamp (4-component vector of float)
|
||||||
0:102 'attv4' (in 4-component vector of float)
|
0:102 'attv4' (in 4-component vector of float)
|
||||||
0:102 Constant:
|
0:102 Constant:
|
||||||
@ -181,8 +187,8 @@ ERROR: node is still EOpNull!
|
|||||||
0:111 0.000000
|
0:111 0.000000
|
||||||
0:112 Function Call: overloadE(vf2; (3-component vector of float)
|
0:112 Function Call: overloadE(vf2; (3-component vector of float)
|
||||||
0:112 Constant:
|
0:112 Constant:
|
||||||
0:112 1 (const int)
|
0:112 1.000000
|
||||||
0:112 1 (const int)
|
0:112 1.000000
|
||||||
0:115 Function Call: overloadE(f1[2]; (3-component vector of float)
|
0:115 Function Call: overloadE(f1[2]; (3-component vector of float)
|
||||||
0:115 'b' (2-element array of float)
|
0:115 'b' (2-element array of float)
|
||||||
0:117 Constant:
|
0:117 Constant:
|
||||||
@ -190,6 +196,82 @@ ERROR: node is still EOpNull!
|
|||||||
0:118 Function Call: overloadF(i1; (3-component vector of float)
|
0:118 Function Call: overloadF(i1; (3-component vector of float)
|
||||||
0:118 Constant:
|
0:118 Constant:
|
||||||
0:118 1 (const int)
|
0:118 1 (const int)
|
||||||
|
0:128 Function Definition: foo2( (void)
|
||||||
|
0:128 Function Parameters:
|
||||||
|
0:? Sequence
|
||||||
|
0:135 Comma (void)
|
||||||
|
0:135 Function Call: outFun(f1;vi2;i1;f1; (void)
|
||||||
|
0:135 Convert int to float (float)
|
||||||
|
0:135 'i' (int)
|
||||||
|
0:135 'tempArg' (out 2-component vector of int)
|
||||||
|
0:135 'i' (int)
|
||||||
|
0:135 'f' (float)
|
||||||
|
0:135 move second child to first child (2-component vector of float)
|
||||||
|
0:135 'v2' (2-component vector of float)
|
||||||
|
0:135 Convert int to float (2-component vector of float)
|
||||||
|
0:135 'tempArg' (out 2-component vector of int)
|
||||||
|
0:136 Comma (int)
|
||||||
|
0:136 move second child to first child (int)
|
||||||
|
0:136 'tempReturn' (int)
|
||||||
|
0:136 Function Call: outFunRet(f1;i1;i1;vi4; (int)
|
||||||
|
0:136 Convert int to float (float)
|
||||||
|
0:136 'i' (int)
|
||||||
|
0:136 'tempArg' (out int)
|
||||||
|
0:136 'i' (int)
|
||||||
|
0:136 'tempArg' (out 4-component vector of int)
|
||||||
|
0:136 move second child to first child (float)
|
||||||
|
0:136 'f' (float)
|
||||||
|
0:136 Convert int to float (float)
|
||||||
|
0:136 'tempArg' (out int)
|
||||||
|
0:136 move second child to first child (4-component vector of float)
|
||||||
|
0:136 'v4' (4-component vector of float)
|
||||||
|
0:136 Convert int to float (4-component vector of float)
|
||||||
|
0:136 'tempArg' (out 4-component vector of int)
|
||||||
|
0:136 'tempReturn' (int)
|
||||||
|
0:137 Sequence
|
||||||
|
0:137 move second child to first child (float)
|
||||||
|
0:137 'ret' (float)
|
||||||
|
0:137 Convert int to float (float)
|
||||||
|
0:137 Comma (int)
|
||||||
|
0:137 move second child to first child (int)
|
||||||
|
0:137 'tempReturn' (int)
|
||||||
|
0:137 Function Call: outFunRet(f1;i1;i1;vi4; (int)
|
||||||
|
0:137 Convert int to float (float)
|
||||||
|
0:137 'i' (int)
|
||||||
|
0:137 'tempArg' (out int)
|
||||||
|
0:137 'i' (int)
|
||||||
|
0:137 'tempArg' (out 4-component vector of int)
|
||||||
|
0:137 move second child to first child (float)
|
||||||
|
0:137 'f' (float)
|
||||||
|
0:137 Convert int to float (float)
|
||||||
|
0:137 'tempArg' (out int)
|
||||||
|
0:137 move second child to first child (4-component vector of float)
|
||||||
|
0:137 'v4' (4-component vector of float)
|
||||||
|
0:137 Convert int to float (4-component vector of float)
|
||||||
|
0:137 'tempArg' (out 4-component vector of int)
|
||||||
|
0:137 'tempReturn' (int)
|
||||||
|
0:138 Sequence
|
||||||
|
0:138 move second child to first child (2-component vector of float)
|
||||||
|
0:138 'ret2' (2-component vector of float)
|
||||||
|
0:138 Convert int to float (2-component vector of float)
|
||||||
|
0:138 Comma (2-component vector of int)
|
||||||
|
0:138 move second child to first child (2-component vector of int)
|
||||||
|
0:138 'tempReturn' (2-component vector of int)
|
||||||
|
0:138 Function Call: outFunRet(f1;vi4;i1;vi4; (2-component vector of int)
|
||||||
|
0:138 Convert int to float (float)
|
||||||
|
0:138 'i' (int)
|
||||||
|
0:138 'tempArg' (out 4-component vector of int)
|
||||||
|
0:138 'i' (int)
|
||||||
|
0:138 'tempArg' (out 4-component vector of int)
|
||||||
|
0:138 move second child to first child (4-component vector of float)
|
||||||
|
0:138 'v4' (4-component vector of float)
|
||||||
|
0:138 Convert int to float (4-component vector of float)
|
||||||
|
0:138 'tempArg' (out 4-component vector of int)
|
||||||
|
0:138 move second child to first child (4-component vector of float)
|
||||||
|
0:138 'v4' (4-component vector of float)
|
||||||
|
0:138 Convert int to float (4-component vector of float)
|
||||||
|
0:138 'tempArg' (out 4-component vector of int)
|
||||||
|
0:138 'tempReturn' (2-component vector of int)
|
||||||
0:? Linker Objects
|
0:? Linker Objects
|
||||||
0:? 'i' (in 4-component vector of float)
|
0:? 'i' (in 4-component vector of float)
|
||||||
0:? 'o' (smooth out 4-component vector of float)
|
0:? 'o' (smooth out 4-component vector of float)
|
||||||
|
|||||||
@ -1,122 +1,170 @@
|
|||||||
../../LunarGLASS/test/functionSemantics.frag
|
../../LunarGLASS/test/functionSemantics.frag
|
||||||
|
Warning, version 400 is not yet complete; some version-specific features are present, but many are missing.
|
||||||
|
|
||||||
0:? Sequence
|
0:? Sequence
|
||||||
0:3 Function Definition: foo(i1;i1;i1;i1;i1;i1; (mediump int)
|
0:3 Function Definition: foo(i1;i1;i1;i1;i1;i1; (int)
|
||||||
0:3 Function Parameters:
|
0:3 Function Parameters:
|
||||||
0:3 'a' (in mediump int)
|
0:3 'a' (in int)
|
||||||
0:3 'b' (const (read only) mediump int)
|
0:3 'b' (const (read only) int)
|
||||||
0:3 'c' (in mediump int)
|
0:3 'c' (in int)
|
||||||
0:3 'd' (const (read only) mediump int)
|
0:3 'd' (const (read only) int)
|
||||||
0:3 'e' (out mediump int)
|
0:3 'e' (out int)
|
||||||
0:3 'f' (inout mediump int)
|
0:3 'f' (inout int)
|
||||||
0:5 Sequence
|
0:5 Sequence
|
||||||
0:5 Sequence
|
0:5 Sequence
|
||||||
0:5 move second child to first child (mediump int)
|
0:5 move second child to first child (int)
|
||||||
0:5 'sum' (mediump int)
|
0:5 'sum' (int)
|
||||||
0:5 add (mediump int)
|
0:5 add (int)
|
||||||
0:5 add (mediump int)
|
0:5 add (int)
|
||||||
0:5 add (mediump int)
|
0:5 add (int)
|
||||||
0:5 add (mediump int)
|
0:5 add (int)
|
||||||
0:5 'a' (in mediump int)
|
0:5 'a' (in int)
|
||||||
0:5 'b' (const (read only) mediump int)
|
0:5 'b' (const (read only) int)
|
||||||
0:5 'c' (in mediump int)
|
0:5 'c' (in int)
|
||||||
0:5 'd' (const (read only) mediump int)
|
0:5 'd' (const (read only) int)
|
||||||
0:5 'f' (inout mediump int)
|
0:5 'f' (inout int)
|
||||||
0:8 multiply second child into first child (mediump int)
|
0:8 multiply second child into first child (int)
|
||||||
0:8 'a' (in mediump int)
|
0:8 'a' (in int)
|
||||||
0:8 Constant:
|
0:8 Constant:
|
||||||
0:8 64 (const int)
|
0:8 64 (const int)
|
||||||
0:10 multiply second child into first child (mediump int)
|
0:10 multiply second child into first child (int)
|
||||||
0:10 'c' (in mediump int)
|
0:10 'c' (in int)
|
||||||
0:10 Constant:
|
0:10 Constant:
|
||||||
0:10 64 (const int)
|
0:10 64 (const int)
|
||||||
0:12 move second child to first child (mediump int)
|
0:12 move second child to first child (int)
|
||||||
0:12 'e' (out mediump int)
|
0:12 'e' (out int)
|
||||||
0:12 Constant:
|
0:12 Constant:
|
||||||
0:12 1024 (const int)
|
0:12 1024 (const int)
|
||||||
0:13 multiply second child into first child (mediump int)
|
0:13 multiply second child into first child (int)
|
||||||
0:13 'f' (inout mediump int)
|
0:13 'f' (inout int)
|
||||||
0:13 Constant:
|
0:13 Constant:
|
||||||
0:13 64 (const int)
|
0:13 64 (const int)
|
||||||
0:15 add second child into first child (mediump int)
|
0:15 add second child into first child (int)
|
||||||
0:15 'sum' (mediump int)
|
0:15 'sum' (int)
|
||||||
0:15 add (mediump int)
|
0:15 add (int)
|
||||||
0:15 add (mediump int)
|
0:15 add (int)
|
||||||
0:15 add (mediump int)
|
0:15 add (int)
|
||||||
0:15 add (mediump int)
|
0:15 add (int)
|
||||||
0:15 add (mediump int)
|
0:15 add (int)
|
||||||
0:15 'a' (in mediump int)
|
0:15 'a' (in int)
|
||||||
0:15 component-wise multiply (mediump int)
|
0:15 component-wise multiply (int)
|
||||||
0:15 Constant:
|
0:15 Constant:
|
||||||
0:15 64 (const int)
|
0:15 64 (const int)
|
||||||
0:15 'b' (const (read only) mediump int)
|
0:15 'b' (const (read only) int)
|
||||||
0:15 'c' (in mediump int)
|
0:15 'c' (in int)
|
||||||
0:15 component-wise multiply (mediump int)
|
0:15 component-wise multiply (int)
|
||||||
0:15 Constant:
|
0:15 Constant:
|
||||||
0:15 64 (const int)
|
0:15 64 (const int)
|
||||||
0:15 'd' (const (read only) mediump int)
|
0:15 'd' (const (read only) int)
|
||||||
0:15 'e' (out mediump int)
|
0:15 'e' (out int)
|
||||||
0:15 'f' (inout mediump int)
|
0:15 'f' (inout int)
|
||||||
0:18 Branch: Return with expression
|
0:18 Branch: Return with expression
|
||||||
0:18 'sum' (mediump int)
|
0:18 'sum' (int)
|
||||||
0:21 Function Definition: main( (void)
|
0:21 Function Definition: foo2(f1;vf3;i1; (int)
|
||||||
0:21 Function Parameters:
|
0:21 Function Parameters:
|
||||||
0:? Sequence
|
0:21 'a' (in float)
|
||||||
0:24 Sequence
|
0:21 'b' (in 3-component vector of float)
|
||||||
0:24 move second child to first child (mediump int)
|
0:21 'r' (out int)
|
||||||
0:24 't' (mediump int)
|
0:23 Sequence
|
||||||
|
0:23 move second child to first child (int)
|
||||||
|
0:23 'r' (out int)
|
||||||
|
0:23 Convert float to int (int)
|
||||||
|
0:23 component-wise multiply (float)
|
||||||
|
0:23 Constant:
|
||||||
|
0:23 3.000000
|
||||||
|
0:23 'a' (in float)
|
||||||
|
0:24 Branch: Return with expression
|
||||||
|
0:24 Convert float to int (int)
|
||||||
|
0:24 component-wise multiply (float)
|
||||||
0:24 Constant:
|
0:24 Constant:
|
||||||
0:24 2 (const int)
|
0:24 5.000000
|
||||||
0:28 move second child to first child (mediump int)
|
0:24 direct index (float)
|
||||||
0:28 direct index (mediump int)
|
0:24 'b' (in 3-component vector of float)
|
||||||
0:28 t: direct index for structure (mediump 4-component vector of int)
|
0:24 Constant:
|
||||||
0:28 'f' (structure{mediump 4-component vector of int t})
|
0:24 1 (const int)
|
||||||
0:28 Constant:
|
0:27 Function Definition: main( (void)
|
||||||
0:28 0 (const int)
|
0:27 Function Parameters:
|
||||||
0:28 Constant:
|
0:? Sequence
|
||||||
0:28 1 (const int)
|
|
||||||
0:28 Constant:
|
|
||||||
0:28 32 (const int)
|
|
||||||
0:30 Sequence
|
0:30 Sequence
|
||||||
0:30 move second child to first child (mediump int)
|
0:30 move second child to first child (int)
|
||||||
0:30 'color' (mediump int)
|
0:30 't' (int)
|
||||||
0:30 Function Call: foo(i1;i1;i1;i1;i1;i1; (mediump int)
|
|
||||||
0:30 Constant:
|
|
||||||
0:30 1 (const int)
|
|
||||||
0:30 Constant:
|
0:30 Constant:
|
||||||
0:30 2 (const int)
|
0:30 2 (const int)
|
||||||
0:30 add (mediump int)
|
0:34 move second child to first child (int)
|
||||||
0:30 't' (mediump int)
|
0:34 direct index (int)
|
||||||
0:30 't' (mediump int)
|
0:34 t: direct index for structure (4-component vector of int)
|
||||||
0:30 Constant:
|
0:34 'f' (structure{4-component vector of int t})
|
||||||
0:30 8 (const int)
|
0:34 Constant:
|
||||||
0:30 'e' (mediump int)
|
0:34 0 (const int)
|
||||||
0:30 direct index (mediump int)
|
0:34 Constant:
|
||||||
0:30 t: direct index for structure (mediump 4-component vector of int)
|
0:34 1 (const int)
|
||||||
0:30 'f' (structure{mediump 4-component vector of int t})
|
0:34 Constant:
|
||||||
0:30 Constant:
|
0:34 32 (const int)
|
||||||
0:30 0 (const int)
|
0:37 Sequence
|
||||||
0:30 Constant:
|
0:37 move second child to first child (int)
|
||||||
0:30 1 (const int)
|
0:37 'color' (int)
|
||||||
0:32 add second child into first child (mediump int)
|
0:37 Function Call: foo(i1;i1;i1;i1;i1;i1; (int)
|
||||||
0:32 'color' (mediump int)
|
0:37 Constant:
|
||||||
0:32 component-wise multiply (mediump int)
|
0:37 1 (const int)
|
||||||
0:32 Constant:
|
0:37 Constant:
|
||||||
0:32 128 (const int)
|
0:37 2 (const int)
|
||||||
0:32 add (mediump int)
|
0:37 add (int)
|
||||||
0:32 'e' (mediump int)
|
0:37 't' (int)
|
||||||
0:32 direct index (mediump int)
|
0:37 't' (int)
|
||||||
0:32 t: direct index for structure (mediump 4-component vector of int)
|
0:37 Constant:
|
||||||
0:32 'f' (structure{mediump 4-component vector of int t})
|
0:37 8 (const int)
|
||||||
0:32 Constant:
|
0:37 'e' (int)
|
||||||
0:32 0 (const int)
|
0:37 direct index (int)
|
||||||
0:32 Constant:
|
0:37 t: direct index for structure (4-component vector of int)
|
||||||
0:32 1 (const int)
|
0:37 'f' (structure{4-component vector of int t})
|
||||||
0:35 move second child to first child (mediump 4-component vector of float)
|
0:37 Constant:
|
||||||
0:35 'gl_FragColor' (fragColor mediump 4-component vector of float)
|
0:37 0 (const int)
|
||||||
0:35 Construct vec4 (mediump 4-component vector of float)
|
0:37 Constant:
|
||||||
0:35 Convert int to float (mediump float)
|
0:37 1 (const int)
|
||||||
0:35 'color' (mediump int)
|
0:39 add second child into first child (int)
|
||||||
|
0:39 'color' (int)
|
||||||
|
0:39 component-wise multiply (int)
|
||||||
|
0:39 Constant:
|
||||||
|
0:39 128 (const int)
|
||||||
|
0:39 add (int)
|
||||||
|
0:39 'e' (int)
|
||||||
|
0:39 direct index (int)
|
||||||
|
0:39 t: direct index for structure (4-component vector of int)
|
||||||
|
0:39 'f' (structure{4-component vector of int t})
|
||||||
|
0:39 Constant:
|
||||||
|
0:39 0 (const int)
|
||||||
|
0:39 Constant:
|
||||||
|
0:39 1 (const int)
|
||||||
|
0:45 move second child to first child (float)
|
||||||
|
0:45 'ret' (float)
|
||||||
|
0:45 Convert int to float (float)
|
||||||
|
0:45 Comma (int)
|
||||||
|
0:45 move second child to first child (int)
|
||||||
|
0:45 'tempReturn' (int)
|
||||||
|
0:45 Function Call: foo2(f1;vf3;i1; (int)
|
||||||
|
0:45 Constant:
|
||||||
|
0:45 4.000000
|
||||||
|
0:45 Constant:
|
||||||
|
0:45 1.000000
|
||||||
|
0:45 2.000000
|
||||||
|
0:45 3.000000
|
||||||
|
0:45 'tempArg' (out int)
|
||||||
|
0:45 move second child to first child (float)
|
||||||
|
0:45 'arg' (float)
|
||||||
|
0:45 Convert int to float (float)
|
||||||
|
0:45 'tempArg' (out int)
|
||||||
|
0:45 'tempReturn' (int)
|
||||||
|
0:46 add second child into first child (int)
|
||||||
|
0:46 'color' (int)
|
||||||
|
0:46 Convert float to int (int)
|
||||||
|
0:46 add (float)
|
||||||
|
0:46 'ret' (float)
|
||||||
|
0:46 'arg' (float)
|
||||||
|
0:48 move second child to first child (4-component vector of float)
|
||||||
|
0:48 'gl_FragColor' (fragColor 4-component vector of float)
|
||||||
|
0:48 Construct vec4 (4-component vector of float)
|
||||||
|
0:48 Convert int to float (float)
|
||||||
|
0:48 'color' (int)
|
||||||
0:? Linker Objects
|
0:? Linker Objects
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -74,8 +74,7 @@ enum TStorageQualifier {
|
|||||||
EvqIn, // also, for 'in' in the grammar before we know if it's a pipeline input or an 'in' parameter
|
EvqIn, // also, for 'in' in the grammar before we know if it's a pipeline input or an 'in' parameter
|
||||||
EvqOut, // also, for 'out' in the grammar before we know if it's a pipeline output or an 'out' parameter
|
EvqOut, // also, for 'out' in the grammar before we know if it's a pipeline output or an 'out' parameter
|
||||||
EvqInOut,
|
EvqInOut,
|
||||||
|
EvqConstReadOnly, // input; also other read-only types having neither a constant value nor constant-value semantics
|
||||||
EvqConstReadOnly, // read-only types, not having a constant value or constant-value semantics
|
|
||||||
|
|
||||||
// built-ins read by vertex shader
|
// built-ins read by vertex shader
|
||||||
EvqVertexId,
|
EvqVertexId,
|
||||||
|
|||||||
@ -238,9 +238,15 @@ class TQualifier {
|
|||||||
public:
|
public:
|
||||||
void clear()
|
void clear()
|
||||||
{
|
{
|
||||||
storage = EvqTemporary;
|
|
||||||
precision = EpqNone;
|
precision = EpqNone;
|
||||||
invariant = false;
|
invariant = false;
|
||||||
|
makeTemporary();
|
||||||
|
}
|
||||||
|
|
||||||
|
// drop qualifiers that don't belong in a temporary variable
|
||||||
|
void makeTemporary()
|
||||||
|
{
|
||||||
|
storage = EvqTemporary;
|
||||||
centroid = false;
|
centroid = false;
|
||||||
smooth = false;
|
smooth = false;
|
||||||
flat = false;
|
flat = false;
|
||||||
@ -255,6 +261,7 @@ public:
|
|||||||
writeonly = false;
|
writeonly = false;
|
||||||
clearLayout();
|
clearLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
TStorageQualifier storage : 6;
|
TStorageQualifier storage : 6;
|
||||||
TPrecisionQualifier precision : 3;
|
TPrecisionQualifier precision : 3;
|
||||||
bool invariant : 1;
|
bool invariant : 1;
|
||||||
@ -314,6 +321,29 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isParamInput() const
|
||||||
|
{
|
||||||
|
switch (storage) {
|
||||||
|
case EvqIn:
|
||||||
|
case EvqInOut:
|
||||||
|
case EvqConstReadOnly:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isParamOutput() const
|
||||||
|
{
|
||||||
|
switch (storage) {
|
||||||
|
case EvqOut:
|
||||||
|
case EvqInOut:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool isUniform() const
|
bool isUniform() const
|
||||||
{
|
{
|
||||||
switch (storage) {
|
switch (storage) {
|
||||||
|
|||||||
@ -247,7 +247,7 @@ enum TOperator {
|
|||||||
//
|
//
|
||||||
|
|
||||||
EOpConstructGuardStart,
|
EOpConstructGuardStart,
|
||||||
EOpConstructInt,
|
EOpConstructInt, // these first scalar forms also identify what implicit conversion is needed
|
||||||
EOpConstructUint,
|
EOpConstructUint,
|
||||||
EOpConstructBool,
|
EOpConstructBool,
|
||||||
EOpConstructFloat,
|
EOpConstructFloat,
|
||||||
|
|||||||
@ -67,6 +67,11 @@ TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TIntermSymbol* TIntermediate::addSymbol(const TVariable& variable, TSourceLoc loc)
|
||||||
|
{
|
||||||
|
return addSymbol(variable.getUniqueId(), variable.getName(), variable.getType(), loc);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Connect two nodes with a new parent that does a binary operation on the nodes.
|
// Connect two nodes with a new parent that does a binary operation on the nodes.
|
||||||
//
|
//
|
||||||
@ -363,14 +368,16 @@ TIntermTyped* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator o
|
|||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Convert one type to another.
|
// Convert the node's type to the given type, as allowed by the operation involved 'op'.
|
||||||
|
// For implicit conversions, 'op' is not the requested conversion, it is the explicit
|
||||||
|
// operation requiring the implicit conversion.
|
||||||
//
|
//
|
||||||
// Returns the node representing the conversion, which could be the same
|
// Returns the node representing the conversion, which could be the same
|
||||||
// node passed in if no conversion was needed.
|
// node passed in if no conversion was needed.
|
||||||
//
|
//
|
||||||
// Return 0 if a conversion can't be done.
|
// Return 0 if a conversion can't be done.
|
||||||
//
|
//
|
||||||
TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TIntermTyped* node)
|
TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TIntermTyped* node) const
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
// Does the base type allow operation?
|
// Does the base type allow operation?
|
||||||
@ -490,10 +497,9 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node->getAsConstantUnion()) {
|
if (node->getAsConstantUnion())
|
||||||
|
|
||||||
return promoteConstantUnion(promoteTo, node->getAsConstantUnion());
|
return promoteConstantUnion(promoteTo, node->getAsConstantUnion());
|
||||||
} else {
|
|
||||||
//
|
//
|
||||||
// Add a new newNode for the conversion.
|
// Add a new newNode for the conversion.
|
||||||
//
|
//
|
||||||
@ -558,20 +564,19 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
TType type(promoteTo, EvqTemporary, node->getVectorSize(), node->getMatrixCols(), node->getMatrixRows());
|
TType newType(promoteTo, EvqTemporary, node->getVectorSize(), node->getMatrixCols(), node->getMatrixRows());
|
||||||
newNode = new TIntermUnary(newOp, type);
|
newNode = new TIntermUnary(newOp, newType);
|
||||||
newNode->setLoc(node->getLoc());
|
newNode->setLoc(node->getLoc());
|
||||||
newNode->setOperand(node);
|
newNode->setOperand(node);
|
||||||
|
|
||||||
return newNode;
|
return newNode;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// See if the 'from' type is allowed to be implicitly converted to the
|
// See if the 'from' type is allowed to be implicitly converted to the
|
||||||
// 'to' type. This is not about vector/array/struct, only about basic type.
|
// 'to' type. This is not about vector/array/struct, only about basic type.
|
||||||
//
|
//
|
||||||
bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to)
|
bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to) const
|
||||||
{
|
{
|
||||||
if (profile == EEsProfile || version == 110)
|
if (profile == EEsProfile || version == 110)
|
||||||
return false;
|
return false;
|
||||||
@ -713,8 +718,7 @@ TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, T
|
|||||||
TIntermTyped *commaAggregate = growAggregate(left, right, loc);
|
TIntermTyped *commaAggregate = growAggregate(left, right, loc);
|
||||||
commaAggregate->getAsAggregate()->setOperator(EOpComma);
|
commaAggregate->getAsAggregate()->setOperator(EOpComma);
|
||||||
commaAggregate->setType(right->getType());
|
commaAggregate->setType(right->getType());
|
||||||
commaAggregate->getWritableType().getQualifier().storage = EvqTemporary;
|
commaAggregate->getWritableType().getQualifier().makeTemporary();
|
||||||
commaAggregate->getWritableType().getQualifier().precision = right->getType().getQualifier().precision;
|
|
||||||
|
|
||||||
return commaAggregate;
|
return commaAggregate;
|
||||||
}
|
}
|
||||||
@ -782,7 +786,7 @@ TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* true
|
|||||||
// Returns the constant union node created.
|
// Returns the constant union node created.
|
||||||
//
|
//
|
||||||
|
|
||||||
TIntermConstantUnion* TIntermediate::addConstantUnion(const TConstUnionArray& unionArray, const TType& t, TSourceLoc loc, bool literal)
|
TIntermConstantUnion* TIntermediate::addConstantUnion(const TConstUnionArray& unionArray, const TType& t, TSourceLoc loc, bool literal) const
|
||||||
{
|
{
|
||||||
TIntermConstantUnion* node = new TIntermConstantUnion(unionArray, t);
|
TIntermConstantUnion* node = new TIntermConstantUnion(unionArray, t);
|
||||||
node->setLoc(loc);
|
node->setLoc(loc);
|
||||||
@ -1028,7 +1032,7 @@ bool TIntermUnary::promote()
|
|||||||
}
|
}
|
||||||
|
|
||||||
setType(operand->getType());
|
setType(operand->getType());
|
||||||
getWritableType().getQualifier().storage = EvqTemporary;
|
getWritableType().getQualifier().makeTemporary();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1412,7 +1416,7 @@ void TIntermTyped::propagatePrecision(TPrecisionQualifier newPrecision)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermConstantUnion* node)
|
TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermConstantUnion* node) const
|
||||||
{
|
{
|
||||||
const TConstUnionArray& rightUnionArray = node->getConstArray();
|
const TConstUnionArray& rightUnionArray = node->getConstArray();
|
||||||
int size = node->getType().computeNumComponents();
|
int size = node->getType().computeNumComponents();
|
||||||
|
|||||||
@ -381,7 +381,7 @@ TIntermTyped* TParseContext::handleVariable(TSourceLoc loc, TSymbol* symbol, TSt
|
|||||||
if (anon) {
|
if (anon) {
|
||||||
// it was a member of an anonymous container, have to insert its dereference
|
// it was a member of an anonymous container, have to insert its dereference
|
||||||
const TVariable* variable = anon->getAnonContainer().getAsVariable();
|
const TVariable* variable = anon->getAnonContainer().getAsVariable();
|
||||||
TIntermTyped* container = intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), loc);
|
TIntermTyped* container = intermediate.addSymbol(*variable, loc);
|
||||||
TConstUnionArray unionArray(1);
|
TConstUnionArray unionArray(1);
|
||||||
unionArray[0].setUConst(anon->getMemberNumber());
|
unionArray[0].setUConst(anon->getMemberNumber());
|
||||||
TIntermTyped* constNode = intermediate.addConstantUnion(unionArray, TType(EbtUint, EvqConst), loc);
|
TIntermTyped* constNode = intermediate.addConstantUnion(unionArray, TType(EbtUint, EvqConst), loc);
|
||||||
@ -892,9 +892,7 @@ TIntermAggregate* TParseContext::handleFunctionDefinition(TSourceLoc loc, TFunct
|
|||||||
|
|
||||||
// Add the parameter to the HIL
|
// Add the parameter to the HIL
|
||||||
paramNodes = intermediate.growAggregate(paramNodes,
|
paramNodes = intermediate.growAggregate(paramNodes,
|
||||||
intermediate.addSymbol(variable->getUniqueId(),
|
intermediate.addSymbol(*variable, loc),
|
||||||
variable->getName(),
|
|
||||||
variable->getType(), loc),
|
|
||||||
loc);
|
loc);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
@ -916,13 +914,13 @@ TIntermAggregate* TParseContext::handleFunctionDefinition(TSourceLoc loc, TFunct
|
|||||||
// - user function
|
// - user function
|
||||||
// - subroutine call (not implemented yet)
|
// - subroutine call (not implemented yet)
|
||||||
//
|
//
|
||||||
TIntermTyped* TParseContext::handleFunctionCall(TSourceLoc loc, TFunction* fnCall, TIntermNode* intermNode)
|
TIntermTyped* TParseContext::handleFunctionCall(TSourceLoc loc, TFunction* function, TIntermNode* intermNode)
|
||||||
{
|
{
|
||||||
TIntermTyped* result = 0;
|
TIntermTyped* result = 0;
|
||||||
|
|
||||||
TOperator op = fnCall->getBuiltInOp();
|
TOperator op = function->getBuiltInOp();
|
||||||
if (op == EOpArrayLength)
|
if (op == EOpArrayLength)
|
||||||
result = handleLengthMethod(loc, fnCall, intermNode);
|
result = handleLengthMethod(loc, function, intermNode);
|
||||||
else if (op != EOpNull) {
|
else if (op != EOpNull) {
|
||||||
//
|
//
|
||||||
// Then this should be a constructor.
|
// Then this should be a constructor.
|
||||||
@ -930,7 +928,7 @@ TIntermTyped* TParseContext::handleFunctionCall(TSourceLoc loc, TFunction* fnCal
|
|||||||
// Their parameters will be verified algorithmically.
|
// Their parameters will be verified algorithmically.
|
||||||
//
|
//
|
||||||
TType type(EbtVoid); // use this to get the type back
|
TType type(EbtVoid); // use this to get the type back
|
||||||
if (! constructorError(loc, intermNode, *fnCall, op, type)) {
|
if (! constructorError(loc, intermNode, *function, op, type)) {
|
||||||
//
|
//
|
||||||
// It's a constructor, of type 'type'.
|
// It's a constructor, of type 'type'.
|
||||||
//
|
//
|
||||||
@ -944,7 +942,7 @@ TIntermTyped* TParseContext::handleFunctionCall(TSourceLoc loc, TFunction* fnCal
|
|||||||
//
|
//
|
||||||
const TFunction* fnCandidate;
|
const TFunction* fnCandidate;
|
||||||
bool builtIn;
|
bool builtIn;
|
||||||
fnCandidate = findFunction(loc, *fnCall, builtIn);
|
fnCandidate = findFunction(loc, *function, builtIn);
|
||||||
if (fnCandidate) {
|
if (fnCandidate) {
|
||||||
// Error check for function requiring specific extensions present.
|
// Error check for function requiring specific extensions present.
|
||||||
if (builtIn && fnCandidate->getNumExtensions())
|
if (builtIn && fnCandidate->getNumExtensions())
|
||||||
@ -966,30 +964,33 @@ TIntermTyped* TParseContext::handleFunctionCall(TSourceLoc loc, TFunction* fnCal
|
|||||||
} else {
|
} else {
|
||||||
// This is a function call not mapped to built-in operation
|
// This is a function call not mapped to built-in operation
|
||||||
result = intermediate.setAggregateOperator(intermNode, EOpFunctionCall, fnCandidate->getType(), loc);
|
result = intermediate.setAggregateOperator(intermNode, EOpFunctionCall, fnCandidate->getType(), loc);
|
||||||
result->getAsAggregate()->setName(fnCandidate->getMangledName());
|
TIntermAggregate* call = result->getAsAggregate();
|
||||||
|
call->setName(fnCandidate->getMangledName());
|
||||||
|
|
||||||
// this is how we know whether the given function is a built-in function or a user-defined function
|
// this is how we know whether the given function is a built-in function or a user-defined function
|
||||||
// if builtIn == false, it's a userDefined -> could be an overloaded built-in function also
|
// if builtIn == false, it's a userDefined -> could be an overloaded built-in function also
|
||||||
// if builtIn == true, it's definitely a built-in function with EOpNull
|
// if builtIn == true, it's definitely a built-in function with EOpNull
|
||||||
if (! builtIn) {
|
if (! builtIn) {
|
||||||
result->getAsAggregate()->setUserDefined();
|
call->setUserDefined();
|
||||||
intermediate.addToCallGraph(infoSink, currentCaller, fnCandidate->getMangledName());
|
intermediate.addToCallGraph(infoSink, currentCaller, fnCandidate->getMangledName());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure storage qualifications work for these arguments.
|
// Make sure storage qualifications work for these arguments.
|
||||||
TStorageQualifier qual;
|
TStorageQualifier qual;
|
||||||
TQualifierList& qualifierList = result->getAsAggregate()->getQualifierList();
|
TQualifierList& qualifierList = call->getQualifierList();
|
||||||
for (int i = 0; i < fnCandidate->getParamCount(); ++i) {
|
for (int i = 0; i < fnCandidate->getParamCount(); ++i) {
|
||||||
qual = (*fnCandidate)[i].type->getQualifier().storage;
|
qual = (*fnCandidate)[i].type->getQualifier().storage;
|
||||||
if (qual == EvqOut || qual == EvqInOut) {
|
if (qual == EvqOut || qual == EvqInOut) {
|
||||||
if (lValueErrorCheck(result->getLoc(), "assign", result->getAsAggregate()->getSequence()[i]->getAsTyped()))
|
if (lValueErrorCheck(call->getLoc(), "assign", call->getSequence()[i]->getAsTyped()))
|
||||||
error(intermNode->getLoc(), "Constant value cannot be passed for 'out' or 'inout' parameters.", "Error", "");
|
error(intermNode->getLoc(), "Constant value cannot be passed for 'out' or 'inout' parameters.", "Error", "");
|
||||||
}
|
}
|
||||||
qualifierList.push_back(qual);
|
qualifierList.push_back(qual);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result = handleArgumentConversions(*fnCandidate, *call);
|
||||||
|
|
||||||
if (builtIn)
|
if (builtIn)
|
||||||
nonOpBuiltInCheck(loc, *fnCandidate, *result->getAsAggregate());
|
nonOpBuiltInCheck(loc, *fnCandidate, *call);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1007,14 +1008,14 @@ TIntermTyped* TParseContext::handleFunctionCall(TSourceLoc loc, TFunction* fnCal
|
|||||||
|
|
||||||
// Do all processing handling object.length().
|
// Do all processing handling object.length().
|
||||||
// Return resulting tree node.
|
// Return resulting tree node.
|
||||||
TIntermTyped* TParseContext::handleLengthMethod(TSourceLoc loc, TFunction* fnCall, TIntermNode* intermNode)
|
TIntermTyped* TParseContext::handleLengthMethod(TSourceLoc loc, TFunction* function, TIntermNode* intermNode)
|
||||||
{
|
{
|
||||||
int length = 0;
|
int length = 0;
|
||||||
|
|
||||||
if (fnCall->getParamCount() > 0)
|
if (function->getParamCount() > 0)
|
||||||
error(loc, "method does not accept any arguments", fnCall->getName().c_str(), "");
|
error(loc, "method does not accept any arguments", function->getName().c_str(), "");
|
||||||
if (intermNode->getAsTyped() == 0 || ! intermNode->getAsTyped()->getType().isArray())
|
if (intermNode->getAsTyped() == 0 || ! intermNode->getAsTyped()->getType().isArray())
|
||||||
error(loc, "", fnCall->getName().c_str(), "can only be applied to an array");
|
error(loc, "", function->getName().c_str(), "can only be applied to an array");
|
||||||
else if (intermNode->getAsTyped()->getType().getArraySize() == 0) {
|
else if (intermNode->getAsTyped()->getType().getArraySize() == 0) {
|
||||||
bool implicitlySized = false;
|
bool implicitlySized = false;
|
||||||
if (intermNode->getAsSymbolNode() && isIoResizeArray(intermNode->getAsTyped()->getType())) {
|
if (intermNode->getAsSymbolNode() && isIoResizeArray(intermNode->getAsTyped()->getType())) {
|
||||||
@ -1028,9 +1029,9 @@ TIntermTyped* TParseContext::handleLengthMethod(TSourceLoc loc, TFunction* fnCal
|
|||||||
}
|
}
|
||||||
if (length == 0) {
|
if (length == 0) {
|
||||||
if (intermNode->getAsSymbolNode() && isIoResizeArray(intermNode->getAsTyped()->getType()))
|
if (intermNode->getAsSymbolNode() && isIoResizeArray(intermNode->getAsTyped()->getType()))
|
||||||
error(loc, "", fnCall->getName().c_str(), "array must first be sized by a redeclaration or layout qualifier");
|
error(loc, "", function->getName().c_str(), "array must first be sized by a redeclaration or layout qualifier");
|
||||||
else
|
else
|
||||||
error(loc, "", fnCall->getName().c_str(), "array must be declared with a size before using this method");
|
error(loc, "", function->getName().c_str(), "array must be declared with a size before using this method");
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
length = intermNode->getAsTyped()->getType().getArraySize();
|
length = intermNode->getAsTyped()->getType().getArraySize();
|
||||||
@ -1042,6 +1043,86 @@ TIntermTyped* TParseContext::handleLengthMethod(TSourceLoc loc, TFunction* fnCal
|
|||||||
|
|
||||||
return intermediate.addConstantUnion(unionArray, TType(EbtInt, EvqConst), loc);
|
return intermediate.addConstantUnion(unionArray, TType(EbtInt, EvqConst), loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Add any needed implicit conversions for function-call arguments. This is
|
||||||
|
// straightforward for input parameters, but output parameters need to
|
||||||
|
// a different tree topology, complicated further by whether the function
|
||||||
|
// has a return value. Create the new subtree, as neeeded.
|
||||||
|
//
|
||||||
|
// Returns a node of a subtree that evaluates to the return value of the function.
|
||||||
|
//
|
||||||
|
TIntermTyped* TParseContext::handleArgumentConversions(const TFunction& function, TIntermAggregate& intermNode) const
|
||||||
|
{
|
||||||
|
TIntermSequence& arguments = intermNode.getSequence();
|
||||||
|
|
||||||
|
// Will there be any output conversions?
|
||||||
|
bool outputConversions = false;
|
||||||
|
for (int i = 0; i < function.getParamCount(); ++i) {
|
||||||
|
if (*function[i].type != arguments[i]->getAsTyped()->getType() && function[i].type->getQualifier().storage == EvqOut) {
|
||||||
|
outputConversions = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup for the new tree, if needed:
|
||||||
|
//
|
||||||
|
// Output conversions need a different tree topology.
|
||||||
|
// Out-qualified arguments need a temporary of the correct type, with the call
|
||||||
|
// followed by an assignment of the temporary to the original argument:
|
||||||
|
// void: function(arg, ...) -> ( function(tempArg, ...), arg = tempArg, ...)
|
||||||
|
// ret = function(arg, ...) -> ret = (tempRet = function(tempArg, ...), arg = tempArg, ..., tempRet)
|
||||||
|
// Where the "tempArg" type needs no conversion as an argument, but will convert on assignment.
|
||||||
|
TIntermTyped* conversionTree = 0;
|
||||||
|
TVariable* tempRet = 0;
|
||||||
|
if (outputConversions) {
|
||||||
|
if (intermNode.getBasicType() != EbtVoid) {
|
||||||
|
// do the "tempRet = function(...), " bit from above
|
||||||
|
tempRet = makeInternalVariable("tempReturn", intermNode.getType());
|
||||||
|
TIntermSymbol* tempRetNode = intermediate.addSymbol(*tempRet, intermNode.getLoc());
|
||||||
|
conversionTree = intermediate.addAssign(EOpAssign, tempRetNode, &intermNode, intermNode.getLoc());
|
||||||
|
} else
|
||||||
|
conversionTree = &intermNode;
|
||||||
|
|
||||||
|
conversionTree = intermediate.makeAggregate(conversionTree);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process each argument's conversion
|
||||||
|
for (int i = 0; i < function.getParamCount(); ++i) {
|
||||||
|
if (*function[i].type != arguments[i]->getAsTyped()->getType()) {
|
||||||
|
if (function[i].type->getQualifier().isParamInput()) {
|
||||||
|
// In-qualified arguments just need an extra node added above the argument to
|
||||||
|
// convert to the correct type.
|
||||||
|
arguments[i] = intermediate.addConversion(EOpAssign, *function[i].type, arguments[i]->getAsTyped());
|
||||||
|
} else if (function[i].type->getQualifier().isParamOutput()) {
|
||||||
|
// Out-qualified arguments need to use the topology set up above.
|
||||||
|
// do the " ...(tempArg, ...), arg = tempArg" bit from above
|
||||||
|
TVariable* tempArg = makeInternalVariable("tempArg", *function[i].type);
|
||||||
|
tempArg->getWritableType().getQualifier().makeTemporary();
|
||||||
|
TIntermSymbol* tempArgNode = intermediate.addSymbol(*tempArg, intermNode.getLoc());
|
||||||
|
TIntermTyped* tempAssign = intermediate.addAssign(EOpAssign, arguments[i]->getAsTyped(), tempArgNode, arguments[i]->getLoc());
|
||||||
|
conversionTree = intermediate.growAggregate(conversionTree, tempAssign, arguments[i]->getLoc());
|
||||||
|
// replace the argument with another node for the same tempArg variable
|
||||||
|
arguments[i] = intermediate.addSymbol(*tempArg, intermNode.getLoc());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Done if no output conversions
|
||||||
|
if (! outputConversions)
|
||||||
|
return &intermNode;
|
||||||
|
|
||||||
|
// Otherwise, finalize the tree topology (see bigger comment above).
|
||||||
|
if (tempRet) {
|
||||||
|
// do the "..., tempRet" bit from above
|
||||||
|
TIntermSymbol* tempRetNode = intermediate.addSymbol(*tempRet, intermNode.getLoc());
|
||||||
|
conversionTree = intermediate.growAggregate(conversionTree, tempRetNode, intermNode.getLoc());
|
||||||
|
}
|
||||||
|
conversionTree = intermediate.setAggregateOperator(conversionTree, EOpComma, intermNode.getType(), intermNode.getLoc());
|
||||||
|
|
||||||
|
return conversionTree;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Do additional checking of built-in function calls that were not mapped
|
// Do additional checking of built-in function calls that were not mapped
|
||||||
// to built-in operations (e.g., texturing functions).
|
// to built-in operations (e.g., texturing functions).
|
||||||
@ -1136,12 +1217,12 @@ void TParseContext::nonOpBuiltInCheck(TSourceLoc loc, const TFunction& fnCandida
|
|||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Handle seeing a built-in-type constructor call in the grammar.
|
// Handle seeing a built-in constructor in a grammar production.
|
||||||
//
|
//
|
||||||
TFunction* TParseContext::handleConstructorCall(TSourceLoc loc, TPublicType& publicType)
|
TFunction* TParseContext::handleConstructorCall(TSourceLoc loc, const TPublicType& publicType)
|
||||||
{
|
{
|
||||||
publicType.qualifier.precision = EpqNone;
|
|
||||||
TType type(publicType);
|
TType type(publicType);
|
||||||
|
type.getQualifier().precision = EpqNone;
|
||||||
|
|
||||||
if (type.isArray()) {
|
if (type.isArray()) {
|
||||||
profileRequires(loc, ENoProfile, 120, GL_3DL_array_objects, "arrayed constructor");
|
profileRequires(loc, ENoProfile, 120, GL_3DL_array_objects, "arrayed constructor");
|
||||||
@ -1151,10 +1232,9 @@ TFunction* TParseContext::handleConstructorCall(TSourceLoc loc, TPublicType& pub
|
|||||||
TOperator op = mapTypeToConstructorOp(type);
|
TOperator op = mapTypeToConstructorOp(type);
|
||||||
|
|
||||||
if (op == EOpNull) {
|
if (op == EOpNull) {
|
||||||
error(loc, "cannot construct this type", TType::getBasicString(publicType.basicType), "");
|
error(loc, "cannot construct this type", type.getBasicString(), "");
|
||||||
op = EOpConstructFloat;
|
op = EOpConstructFloat;
|
||||||
publicType.basicType = EbtFloat;
|
TType errorType(EbtFloat);
|
||||||
TType errorType(publicType);
|
|
||||||
type.shallowCopy(errorType);
|
type.shallowCopy(errorType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1164,9 +1244,9 @@ TFunction* TParseContext::handleConstructorCall(TSourceLoc loc, TPublicType& pub
|
|||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Given a type, find what operation would construct it.
|
// Given a type, find what operation would fully construct it.
|
||||||
//
|
//
|
||||||
TOperator TParseContext::mapTypeToConstructorOp(const TType& type)
|
TOperator TParseContext::mapTypeToConstructorOp(const TType& type) const
|
||||||
{
|
{
|
||||||
if (type.isStruct())
|
if (type.isStruct())
|
||||||
return EOpConstructStruct;
|
return EOpConstructStruct;
|
||||||
@ -1335,9 +1415,7 @@ void TParseContext::variableCheck(TIntermTyped*& nodePtr)
|
|||||||
symbolTable.insert(*fakeVariable);
|
symbolTable.insert(*fakeVariable);
|
||||||
|
|
||||||
// substitute a symbol node for this new variable
|
// substitute a symbol node for this new variable
|
||||||
nodePtr = intermediate.addSymbol(fakeVariable->getUniqueId(),
|
nodePtr = intermediate.addSymbol(*fakeVariable, symbol->getLoc());
|
||||||
fakeVariable->getName(),
|
|
||||||
fakeVariable->getType(), symbol->getLoc());
|
|
||||||
} else {
|
} else {
|
||||||
switch (symbol->getQualifier().storage) {
|
switch (symbol->getQualifier().storage) {
|
||||||
case EvqPointCoord:
|
case EvqPointCoord:
|
||||||
@ -3340,12 +3418,11 @@ const TFunction* TParseContext::findFunction120(TSourceLoc loc, const TFunction&
|
|||||||
possibleMatch = false;
|
possibleMatch = false;
|
||||||
else {
|
else {
|
||||||
// do direction-specific checks for conversion of basic type
|
// do direction-specific checks for conversion of basic type
|
||||||
TStorageQualifier qualifier = function[i].type->getQualifier().storage;
|
if (function[i].type->getQualifier().isParamInput()) {
|
||||||
if (qualifier == EvqIn || qualifier == EvqInOut) {
|
|
||||||
if (! intermediate.canImplicitlyPromote(call[i].type->getBasicType(), function[i].type->getBasicType()))
|
if (! intermediate.canImplicitlyPromote(call[i].type->getBasicType(), function[i].type->getBasicType()))
|
||||||
possibleMatch = false;
|
possibleMatch = false;
|
||||||
}
|
}
|
||||||
if (qualifier == EvqOut || qualifier == EvqInOut) {
|
if (function[i].type->getQualifier().isParamOutput()) {
|
||||||
if (! intermediate.canImplicitlyPromote(function[i].type->getBasicType(), call[i].type->getBasicType()))
|
if (! intermediate.canImplicitlyPromote(function[i].type->getBasicType(), call[i].type->getBasicType()))
|
||||||
possibleMatch = false;
|
possibleMatch = false;
|
||||||
}
|
}
|
||||||
@ -3471,6 +3548,22 @@ void TParseContext::inheritGlobalDefaults(TQualifier& dst) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Make an internal-only variable whose name is for debug purposes only
|
||||||
|
// and won't be searched for. Callers will only use the return value to use
|
||||||
|
// the variable, not the name to look it up. It is okay if the name
|
||||||
|
// is the same as other names; there won't be any conflict.
|
||||||
|
//
|
||||||
|
TVariable* TParseContext::makeInternalVariable(const char* name, const TType& type) const
|
||||||
|
{
|
||||||
|
TString* nameString = new TString(name);
|
||||||
|
TSourceLoc loc = {0, 0};
|
||||||
|
TVariable* variable = new TVariable(nameString, type);
|
||||||
|
symbolTable.makeInternalVariable(*variable);
|
||||||
|
|
||||||
|
return variable;
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Declare a non-array variable, the main point being there is no redeclaration
|
// Declare a non-array variable, the main point being there is no redeclaration
|
||||||
// for resizing allowed.
|
// for resizing allowed.
|
||||||
@ -3569,7 +3662,7 @@ TIntermNode* TParseContext::executeInitializer(TSourceLoc loc, TString& identifi
|
|||||||
variable->setConstArray(initializer->getAsConstantUnion()->getConstArray());
|
variable->setConstArray(initializer->getAsConstantUnion()->getConstArray());
|
||||||
} else {
|
} else {
|
||||||
// normal assigning of a value to a variable...
|
// normal assigning of a value to a variable...
|
||||||
TIntermSymbol* intermSymbol = intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), loc);
|
TIntermSymbol* intermSymbol = intermediate.addSymbol(*variable, loc);
|
||||||
TIntermNode* initNode = intermediate.addAssign(EOpAssign, intermSymbol, initializer, loc);
|
TIntermNode* initNode = intermediate.addAssign(EOpAssign, intermSymbol, initializer, loc);
|
||||||
if (! initNode)
|
if (! initNode)
|
||||||
assignError(loc, "=", intermSymbol->getCompleteString(), initializer->getCompleteString());
|
assignError(loc, "=", intermSymbol->getCompleteString(), initializer->getCompleteString());
|
||||||
|
|||||||
@ -98,8 +98,9 @@ public:
|
|||||||
TIntermAggregate* handleFunctionDefinition(TSourceLoc, TFunction&);
|
TIntermAggregate* handleFunctionDefinition(TSourceLoc, TFunction&);
|
||||||
TIntermTyped* handleFunctionCall(TSourceLoc, TFunction*, TIntermNode*);
|
TIntermTyped* handleFunctionCall(TSourceLoc, TFunction*, TIntermNode*);
|
||||||
TIntermTyped* handleLengthMethod(TSourceLoc, TFunction*, TIntermNode*);
|
TIntermTyped* handleLengthMethod(TSourceLoc, TFunction*, TIntermNode*);
|
||||||
|
TIntermTyped* handleArgumentConversions(const TFunction&, TIntermAggregate&) const;
|
||||||
void nonOpBuiltInCheck(TSourceLoc, const TFunction&, TIntermAggregate&);
|
void nonOpBuiltInCheck(TSourceLoc, const TFunction&, TIntermAggregate&);
|
||||||
TFunction* handleConstructorCall(TSourceLoc, TPublicType&);
|
TFunction* handleConstructorCall(TSourceLoc, const TPublicType&);
|
||||||
|
|
||||||
bool parseVectorFields(TSourceLoc, const TString&, int vecSize, TVectorFields&);
|
bool parseVectorFields(TSourceLoc, const TString&, int vecSize, TVectorFields&);
|
||||||
void assignError(TSourceLoc, const char* op, TString left, TString right);
|
void assignError(TSourceLoc, const char* op, TString left, TString right);
|
||||||
@ -205,11 +206,12 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
void nonInitConstCheck(TSourceLoc, TString& identifier, TType& type);
|
void nonInitConstCheck(TSourceLoc, TString& identifier, TType& type);
|
||||||
void inheritGlobalDefaults(TQualifier& dst) const;
|
void inheritGlobalDefaults(TQualifier& dst) const;
|
||||||
|
TVariable* makeInternalVariable(const char* name, const TType&) const;
|
||||||
TVariable* declareNonArray(TSourceLoc, TString& identifier, TType&, bool& newDeclaration);
|
TVariable* declareNonArray(TSourceLoc, TString& identifier, TType&, bool& newDeclaration);
|
||||||
void declareArray(TSourceLoc, TString& identifier, const TType&, TSymbol*&, bool& newDeclaration);
|
void declareArray(TSourceLoc, TString& identifier, const TType&, TSymbol*&, bool& newDeclaration);
|
||||||
TIntermNode* executeInitializer(TSourceLoc, TString& identifier, TIntermTyped* initializer, TVariable* variable);
|
TIntermNode* executeInitializer(TSourceLoc, TString& identifier, TIntermTyped* initializer, TVariable* variable);
|
||||||
TIntermTyped* convertInitializerList(TSourceLoc, const TType&, TIntermTyped* initializer);
|
TIntermTyped* convertInitializerList(TSourceLoc, const TType&, TIntermTyped* initializer);
|
||||||
TOperator mapTypeToConstructorOp(const TType&);
|
TOperator mapTypeToConstructorOp(const TType&) const;
|
||||||
void finalErrorCheck();
|
void finalErrorCheck();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|||||||
@ -502,6 +502,12 @@ public:
|
|||||||
table.pop_back();
|
table.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Insert a visible symbol into the symbol table so it can
|
||||||
|
// be found later by name.
|
||||||
|
//
|
||||||
|
// Returns false if the was a name collision.
|
||||||
|
//
|
||||||
bool insert(TSymbol& symbol)
|
bool insert(TSymbol& symbol)
|
||||||
{
|
{
|
||||||
symbol.setUniqueId(++uniqueId);
|
symbol.setUniqueId(++uniqueId);
|
||||||
@ -523,6 +529,17 @@ public:
|
|||||||
return table[currentLevel()]->insert(symbol, separateNameSpaces);
|
return table[currentLevel()]->insert(symbol, separateNameSpaces);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// To allocate an internal temporary, which will need to be uniquely
|
||||||
|
// identified by the consumer of the AST, but never need to
|
||||||
|
// found by doing a symbol table search by name, hence allowed an
|
||||||
|
// arbitrary name in the symbol with no worry of collision.
|
||||||
|
//
|
||||||
|
void makeInternalVariable(TSymbol& symbol)
|
||||||
|
{
|
||||||
|
symbol.setUniqueId(++uniqueId);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// Copy a variable or anonymous member's structure from a shared level up
|
// Copy a variable or anonymous member's structure from a shared level up
|
||||||
// to the current level, so it can be modified without impacting other users
|
// to the current level, so it can be modified without impacting other users
|
||||||
|
|||||||
@ -102,6 +102,7 @@ struct TXfbBuffer {
|
|||||||
|
|
||||||
class TSymbolTable;
|
class TSymbolTable;
|
||||||
class TSymbol;
|
class TSymbol;
|
||||||
|
class TVariable;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Set of helper functions to help parse and build the tree.
|
// Set of helper functions to help parse and build the tree.
|
||||||
@ -133,13 +134,14 @@ public:
|
|||||||
bool isRecursive() const { return recursive; }
|
bool isRecursive() const { return recursive; }
|
||||||
|
|
||||||
TIntermSymbol* addSymbol(int Id, const TString&, const TType&, TSourceLoc);
|
TIntermSymbol* addSymbol(int Id, const TString&, const TType&, TSourceLoc);
|
||||||
TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*);
|
TIntermSymbol* addSymbol(const TVariable&, TSourceLoc);
|
||||||
|
TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*) const;
|
||||||
TIntermTyped* addBinaryMath(TOperator, TIntermTyped* left, TIntermTyped* right, TSourceLoc);
|
TIntermTyped* addBinaryMath(TOperator, TIntermTyped* left, TIntermTyped* right, TSourceLoc);
|
||||||
TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc);
|
TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc);
|
||||||
TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc);
|
TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc);
|
||||||
TIntermTyped* addUnaryMath(TOperator, TIntermNode* child, TSourceLoc);
|
TIntermTyped* addUnaryMath(TOperator, TIntermNode* child, TSourceLoc);
|
||||||
TIntermTyped* addBuiltInFunctionCall(TSourceLoc line, TOperator, bool unary, TIntermNode*, const TType& returnType);
|
TIntermTyped* addBuiltInFunctionCall(TSourceLoc line, TOperator, bool unary, TIntermNode*, const TType& returnType);
|
||||||
bool canImplicitlyPromote(TBasicType from, TBasicType to);
|
bool canImplicitlyPromote(TBasicType from, TBasicType to) const;
|
||||||
TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right);
|
TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right);
|
||||||
TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right, TSourceLoc);
|
TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right, TSourceLoc);
|
||||||
TIntermAggregate* makeAggregate(TIntermNode* node);
|
TIntermAggregate* makeAggregate(TIntermNode* node);
|
||||||
@ -150,8 +152,8 @@ public:
|
|||||||
TIntermTyped* addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, TSourceLoc);
|
TIntermTyped* addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, TSourceLoc);
|
||||||
TIntermTyped* addComma(TIntermTyped* left, TIntermTyped* right, TSourceLoc);
|
TIntermTyped* addComma(TIntermTyped* left, TIntermTyped* right, TSourceLoc);
|
||||||
TIntermTyped* addMethod(TIntermTyped*, const TType&, const TString*, TSourceLoc);
|
TIntermTyped* addMethod(TIntermTyped*, const TType&, const TString*, TSourceLoc);
|
||||||
TIntermConstantUnion* addConstantUnion(const TConstUnionArray&, const TType&, TSourceLoc, bool literal = false);
|
TIntermConstantUnion* addConstantUnion(const TConstUnionArray&, const TType&, TSourceLoc, bool literal = false) const;
|
||||||
TIntermTyped* promoteConstantUnion(TBasicType, TIntermConstantUnion*) ;
|
TIntermTyped* promoteConstantUnion(TBasicType, TIntermConstantUnion*) const;
|
||||||
bool parseConstTree(TIntermNode*, TConstUnionArray, TOperator, const TType&, bool singleConstantParam = false);
|
bool parseConstTree(TIntermNode*, TConstUnionArray, TOperator, const TType&, bool singleConstantParam = false);
|
||||||
TIntermLoop* addLoop(TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, TSourceLoc);
|
TIntermLoop* addLoop(TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, TSourceLoc);
|
||||||
TIntermBranch* addBranch(TOperator, TSourceLoc);
|
TIntermBranch* addBranch(TOperator, TSourceLoc);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user