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:
John Kessenich 2014-03-16 23:03:07 +00:00
parent e5d92eb194
commit 75694fdacd
11 changed files with 530 additions and 235 deletions

View File

@ -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);
}

View File

@ -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)

View File

@ -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

View File

@ -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,

View File

@ -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) {

View File

@ -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,

View File

@ -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();

View File

@ -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());

View File

@ -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:

View File

@ -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

View File

@ -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);