blob: 4ec41094fbbadba1d6861139fbcea6be1b2184a6 [file] [log] [blame]
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001//
shannon.woods%transgaming.com@gtempaccount.comc0d0c222013-04-13 03:29:36 +00002// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7//
8// Definition of the in-memory high-level intermediate representation
9// of shaders. This is a tree that parser creates.
10//
11// Nodes in the tree are defined as a hierarchy of classes derived from
12// TIntermNode. Each is a node in a tree. There is no preset branching factor;
13// each node can have it's own type of list of children.
14//
15
16#ifndef __INTERMEDIATE_H
17#define __INTERMEDIATE_H
18
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +000019#include "GLSLANG/ShaderLang.h"
20
Jamie Madilleb1a0102013-07-08 13:31:38 -040021#include <algorithm>
Geoff Lang17732822013-08-29 13:46:49 -040022#include "compiler/translator/Common.h"
23#include "compiler/translator/Types.h"
24#include "compiler/translator/ConstantUnion.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000025
26//
27// Operators used by the high-level (parse tree) representation.
28//
29enum TOperator {
alokp@chromium.org2cf17712010-03-30 20:33:18 +000030 EOpNull, // if in a node, should only mean a node is still being built
31 EOpSequence, // denotes a list of statements, or parameters, etc.
32 EOpFunctionCall,
33 EOpFunction, // For function definition
34 EOpParameters, // an aggregate listing the parameters to a function
daniel@transgaming.comd1acd1e2010-04-13 03:25:57 +000035
alokp@chromium.org2cf17712010-03-30 20:33:18 +000036 EOpDeclaration,
daniel@transgaming.comd1acd1e2010-04-13 03:25:57 +000037 EOpPrototype,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000038
alokp@chromium.org2cf17712010-03-30 20:33:18 +000039 //
40 // Unary operators
41 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000042
alokp@chromium.org2cf17712010-03-30 20:33:18 +000043 EOpNegative,
44 EOpLogicalNot,
45 EOpVectorLogicalNot,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000046
alokp@chromium.org2cf17712010-03-30 20:33:18 +000047 EOpPostIncrement,
48 EOpPostDecrement,
49 EOpPreIncrement,
50 EOpPreDecrement,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000051
alokp@chromium.org2cf17712010-03-30 20:33:18 +000052 EOpConvIntToBool,
Nicolas Capensab60b932013-06-05 10:31:21 -040053 EOpConvUIntToBool,
alokp@chromium.org2cf17712010-03-30 20:33:18 +000054 EOpConvFloatToBool,
55 EOpConvBoolToFloat,
56 EOpConvIntToFloat,
Nicolas Capensab60b932013-06-05 10:31:21 -040057 EOpConvUIntToFloat,
alokp@chromium.org2cf17712010-03-30 20:33:18 +000058 EOpConvFloatToInt,
59 EOpConvBoolToInt,
Nicolas Capensab60b932013-06-05 10:31:21 -040060 EOpConvUIntToInt,
61 EOpConvIntToUInt,
62 EOpConvFloatToUInt,
63 EOpConvBoolToUInt,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000064
alokp@chromium.org2cf17712010-03-30 20:33:18 +000065 //
66 // binary operations
67 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000068
alokp@chromium.org2cf17712010-03-30 20:33:18 +000069 EOpAdd,
70 EOpSub,
71 EOpMul,
72 EOpDiv,
73 EOpEqual,
74 EOpNotEqual,
75 EOpVectorEqual,
76 EOpVectorNotEqual,
77 EOpLessThan,
78 EOpGreaterThan,
79 EOpLessThanEqual,
80 EOpGreaterThanEqual,
81 EOpComma,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000082
alokp@chromium.org2cf17712010-03-30 20:33:18 +000083 EOpVectorTimesScalar,
84 EOpVectorTimesMatrix,
85 EOpMatrixTimesVector,
86 EOpMatrixTimesScalar,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000087
alokp@chromium.org2cf17712010-03-30 20:33:18 +000088 EOpLogicalOr,
89 EOpLogicalXor,
90 EOpLogicalAnd,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000091
alokp@chromium.org2cf17712010-03-30 20:33:18 +000092 EOpIndexDirect,
93 EOpIndexIndirect,
94 EOpIndexDirectStruct,
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +000095 EOpIndexDirectInterfaceBlock,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000096
alokp@chromium.org2cf17712010-03-30 20:33:18 +000097 EOpVectorSwizzle,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000098
alokp@chromium.org2cf17712010-03-30 20:33:18 +000099 //
100 // Built-in functions potentially mapped to operators
101 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000102
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000103 EOpRadians,
104 EOpDegrees,
105 EOpSin,
106 EOpCos,
107 EOpTan,
108 EOpAsin,
109 EOpAcos,
110 EOpAtan,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000111
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000112 EOpPow,
113 EOpExp,
114 EOpLog,
115 EOpExp2,
116 EOpLog2,
117 EOpSqrt,
118 EOpInverseSqrt,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000119
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000120 EOpAbs,
121 EOpSign,
122 EOpFloor,
123 EOpCeil,
124 EOpFract,
125 EOpMod,
126 EOpMin,
127 EOpMax,
128 EOpClamp,
129 EOpMix,
130 EOpStep,
131 EOpSmoothStep,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000132
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000133 EOpLength,
134 EOpDistance,
135 EOpDot,
136 EOpCross,
137 EOpNormalize,
138 EOpFaceForward,
139 EOpReflect,
140 EOpRefract,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000141
alokp@chromium.org06098892010-08-26 19:36:42 +0000142 EOpDFdx, // Fragment only, OES_standard_derivatives extension
143 EOpDFdy, // Fragment only, OES_standard_derivatives extension
144 EOpFwidth, // Fragment only, OES_standard_derivatives extension
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000145
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000146 EOpMatrixTimesMatrix,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000147
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000148 EOpAny,
149 EOpAll,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000150
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000151 //
152 // Branch
153 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000154
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000155 EOpKill, // Fragment only
156 EOpReturn,
157 EOpBreak,
158 EOpContinue,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000159
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000160 //
161 // Constructors
162 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000163
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000164 EOpConstructInt,
Nicolas Capensab60b932013-06-05 10:31:21 -0400165 EOpConstructUInt,
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000166 EOpConstructBool,
167 EOpConstructFloat,
168 EOpConstructVec2,
169 EOpConstructVec3,
170 EOpConstructVec4,
171 EOpConstructBVec2,
172 EOpConstructBVec3,
173 EOpConstructBVec4,
174 EOpConstructIVec2,
175 EOpConstructIVec3,
176 EOpConstructIVec4,
shannonwoods@chromium.org8c788e82013-05-30 00:20:21 +0000177 EOpConstructUVec2,
178 EOpConstructUVec3,
179 EOpConstructUVec4,
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000180 EOpConstructMat2,
181 EOpConstructMat3,
182 EOpConstructMat4,
183 EOpConstructStruct,
184
185 //
186 // moves
187 //
188
189 EOpAssign,
190 EOpInitialize,
191 EOpAddAssign,
192 EOpSubAssign,
193 EOpMulAssign,
194 EOpVectorTimesMatrixAssign,
195 EOpVectorTimesScalarAssign,
196 EOpMatrixTimesScalarAssign,
197 EOpMatrixTimesMatrixAssign,
daniel@transgaming.comb3077d02013-01-11 04:12:09 +0000198 EOpDivAssign
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000199};
200
alokp@chromium.orgb59a7782010-11-24 18:38:33 +0000201extern const char* getOperatorString(TOperator op);
202
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000203class TIntermTraverser;
204class TIntermAggregate;
205class TIntermBinary;
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +0000206class TIntermUnary;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000207class TIntermConstantUnion;
208class TIntermSelection;
209class TIntermTyped;
210class TIntermSymbol;
alokp@chromium.orgd88b7732010-05-26 15:13:14 +0000211class TIntermLoop;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000212class TInfoSink;
213
214//
215// Base class for the tree nodes
216//
217class TIntermNode {
218public:
Alok Priyadarshi8156b6b2013-09-23 14:56:58 -0400219 POOL_ALLOCATOR_NEW_DELETE();
Jamie Madill075edd82013-07-08 13:30:19 -0400220 TIntermNode() {
221 // TODO: Move this to TSourceLoc constructor
222 // after getting rid of TPublicType.
223 line.first_file = line.last_file = 0;
224 line.first_line = line.last_line = 0;
225 }
226 virtual ~TIntermNode() { }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000227
Jamie Madill075edd82013-07-08 13:30:19 -0400228 const TSourceLoc& getLine() const { return line; }
229 void setLine(const TSourceLoc& l) { line = l; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000230
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000231 virtual void traverse(TIntermTraverser*) = 0;
alokp@chromium.orgd88b7732010-05-26 15:13:14 +0000232 virtual TIntermTyped* getAsTyped() { return 0; }
233 virtual TIntermConstantUnion* getAsConstantUnion() { return 0; }
234 virtual TIntermAggregate* getAsAggregate() { return 0; }
235 virtual TIntermBinary* getAsBinaryNode() { return 0; }
236 virtual TIntermUnary* getAsUnaryNode() { return 0; }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000237 virtual TIntermSelection* getAsSelectionNode() { return 0; }
alokp@chromium.orgd88b7732010-05-26 15:13:14 +0000238 virtual TIntermSymbol* getAsSymbolNode() { return 0; }
239 virtual TIntermLoop* getAsLoopNode() { return 0; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000240
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700241 // Replace a child node. Return true if |original| is a child
242 // node and it is replaced; otherwise, return false.
243 virtual bool replaceChildNode(
244 TIntermNode *original, TIntermNode *replacement) = 0;
245
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000246protected:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000247 TSourceLoc line;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000248};
249
250//
251// This is just to help yacc.
252//
253struct TIntermNodePair {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000254 TIntermNode* node1;
255 TIntermNode* node2;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000256};
257
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000258//
259// Intermediate class for nodes that have a type.
260//
261class TIntermTyped : public TIntermNode {
262public:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000263 TIntermTyped(const TType& t) : type(t) { }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000264 virtual TIntermTyped* getAsTyped() { return this; }
alokp@chromium.orgdd037b22010-03-30 18:47:20 +0000265
Jamie Madill3c9eeb92013-11-04 11:09:26 -0500266 virtual bool hasSideEffects() const = 0;
267
alokp@chromium.org58e54292010-08-24 21:40:03 +0000268 void setType(const TType& t) { type = t; }
269 const TType& getType() const { return type; }
270 TType* getTypePointer() { return &type; }
271
272 TBasicType getBasicType() const { return type.getBasicType(); }
273 TQualifier getQualifier() const { return type.getQualifier(); }
274 TPrecision getPrecision() const { return type.getPrecision(); }
Shannon Woods3841b8e2013-09-10 18:23:12 -0400275 int getCols() const { return type.getCols(); }
276 int getRows() const { return type.getRows(); }
277 int getNominalSize() const { return type.getNominalSize(); }
278 int getSecondarySize() const { return type.getSecondarySize(); }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000279
Jamie Madill98493dd2013-07-08 14:39:03 -0400280 bool isInterfaceBlock() const { return type.isInterfaceBlock(); }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000281 bool isMatrix() const { return type.isMatrix(); }
282 bool isArray() const { return type.isArray(); }
283 bool isVector() const { return type.isVector(); }
284 bool isScalar() const { return type.isScalar(); }
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000285 bool isScalarInt() const { return type.isScalarInt(); }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000286 const char* getBasicString() const { return type.getBasicString(); }
287 const char* getQualifierString() const { return type.getQualifierString(); }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000288 TString getCompleteString() const { return type.getCompleteString(); }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000289
daniel@transgaming.com3ca980a2012-12-20 21:11:52 +0000290 int getArraySize() const { return type.getArraySize(); }
291
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000292protected:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000293 TType type;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000294};
295
296//
297// Handle for, do-while, and while loops.
298//
alokp@chromium.org52813552010-11-16 18:36:09 +0000299enum TLoopType {
300 ELoopFor,
301 ELoopWhile,
daniel@transgaming.comb3077d02013-01-11 04:12:09 +0000302 ELoopDoWhile
alokp@chromium.org52813552010-11-16 18:36:09 +0000303};
304
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000305class TIntermLoop : public TIntermNode {
306public:
alokp@chromium.org52813552010-11-16 18:36:09 +0000307 TIntermLoop(TLoopType aType,
308 TIntermNode *aInit, TIntermTyped* aCond, TIntermTyped* aExpr,
309 TIntermNode* aBody) :
310 type(aType),
311 init(aInit),
312 cond(aCond),
313 expr(aExpr),
zmo@google.com0b8d4eb2011-04-04 19:17:11 +0000314 body(aBody),
315 unrollFlag(false) { }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000316
alokp@chromium.orgd88b7732010-05-26 15:13:14 +0000317 virtual TIntermLoop* getAsLoopNode() { return this; }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000318 virtual void traverse(TIntermTraverser*);
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700319 virtual bool replaceChildNode(
320 TIntermNode *original, TIntermNode *replacement);
alokp@chromium.org58e54292010-08-24 21:40:03 +0000321
alokp@chromium.org52813552010-11-16 18:36:09 +0000322 TLoopType getType() const { return type; }
323 TIntermNode* getInit() { return init; }
324 TIntermTyped* getCondition() { return cond; }
325 TIntermTyped* getExpression() { return expr; }
326 TIntermNode* getBody() { return body; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000327
zmo@google.com0b8d4eb2011-04-04 19:17:11 +0000328 void setUnrollFlag(bool flag) { unrollFlag = flag; }
329 bool getUnrollFlag() { return unrollFlag; }
330
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000331protected:
alokp@chromium.org52813552010-11-16 18:36:09 +0000332 TLoopType type;
333 TIntermNode* init; // for-loop initialization
334 TIntermTyped* cond; // loop exit condition
335 TIntermTyped* expr; // for-loop expression
336 TIntermNode* body; // loop body
zmo@google.com0b8d4eb2011-04-04 19:17:11 +0000337
338 bool unrollFlag; // Whether the loop should be unrolled or not.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000339};
340
341//
342// Handle break, continue, return, and kill.
343//
344class TIntermBranch : public TIntermNode {
345public:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000346 TIntermBranch(TOperator op, TIntermTyped* e) :
347 flowOp(op),
348 expression(e) { }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000349
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000350 virtual void traverse(TIntermTraverser*);
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700351 virtual bool replaceChildNode(
352 TIntermNode *original, TIntermNode *replacement);
alokp@chromium.org58e54292010-08-24 21:40:03 +0000353
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000354 TOperator getFlowOp() { return flowOp; }
355 TIntermTyped* getExpression() { return expression; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000356
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000357protected:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000358 TOperator flowOp;
359 TIntermTyped* expression; // non-zero except for "return exp;" statements
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000360};
361
362//
363// Nodes that correspond to symbols or constants in the source code.
364//
365class TIntermSymbol : public TIntermTyped {
366public:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000367 // if symbol is initialized as symbol(sym), the memory comes from the poolallocator of sym. If sym comes from
368 // per process globalpoolallocator, then it causes increased memory usage per compile
369 // it is essential to use "symbol = sym" to assign to symbol
370 TIntermSymbol(int i, const TString& sym, const TType& t) :
zmo@google.comfd747b82011-04-23 01:30:07 +0000371 TIntermTyped(t), id(i) { symbol = sym; originalSymbol = sym; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000372
Jamie Madill3c9eeb92013-11-04 11:09:26 -0500373 virtual bool hasSideEffects() const { return false; }
374
alokp@chromium.org58e54292010-08-24 21:40:03 +0000375 int getId() const { return id; }
376 const TString& getSymbol() const { return symbol; }
377
zmo@google.comfd747b82011-04-23 01:30:07 +0000378 void setId(int newId) { id = newId; }
379 void setSymbol(const TString& sym) { symbol = sym; }
380
381 const TString& getOriginalSymbol() const { return originalSymbol; }
382
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000383 virtual void traverse(TIntermTraverser*);
384 virtual TIntermSymbol* getAsSymbolNode() { return this; }
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700385 virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000386
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000387protected:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000388 int id;
389 TString symbol;
zmo@google.comfd747b82011-04-23 01:30:07 +0000390 TString originalSymbol;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000391};
392
393class TIntermConstantUnion : public TIntermTyped {
394public:
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000395 TIntermConstantUnion(ConstantUnion *unionPointer, const TType& t) : TIntermTyped(t), unionArrayPointer(unionPointer) { }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000396
Jamie Madill3c9eeb92013-11-04 11:09:26 -0500397 virtual bool hasSideEffects() const { return false; }
398
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000399 ConstantUnion* getUnionArrayPointer() const { return unionArrayPointer; }
shannon.woods%transgaming.com@gtempaccount.comc0d0c222013-04-13 03:29:36 +0000400
Nicolas Capensa621c2e2013-11-20 13:40:23 -0500401 int getIConst(size_t index) const { return unionArrayPointer ? unionArrayPointer[index].getIConst() : 0; }
402 unsigned int getUConst(size_t index) const { return unionArrayPointer ? unionArrayPointer[index].getUConst() : 0; }
403 float getFConst(size_t index) const { return unionArrayPointer ? unionArrayPointer[index].getFConst() : 0.0f; }
404 bool getBConst(size_t index) const { return unionArrayPointer ? unionArrayPointer[index].getBConst() : false; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000405
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000406 virtual TIntermConstantUnion* getAsConstantUnion() { return this; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000407 virtual void traverse(TIntermTraverser*);
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700408 virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000409
410 TIntermTyped* fold(TOperator, TIntermTyped*, TInfoSink&);
411
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000412protected:
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000413 ConstantUnion *unionArrayPointer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000414};
415
416//
417// Intermediate class for node types that hold operators.
418//
419class TIntermOperator : public TIntermTyped {
420public:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000421 TOperator getOp() const { return op; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000422 void setOp(TOperator o) { op = o; }
423
Jamie Madillf4b79ba2013-11-26 10:38:18 -0500424 bool isAssignment() const;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000425 bool isConstructor() const;
alokp@chromium.org58e54292010-08-24 21:40:03 +0000426
Jamie Madillf4b79ba2013-11-26 10:38:18 -0500427 virtual bool hasSideEffects() const { return isAssignment(); }
428
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000429protected:
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000430 TIntermOperator(TOperator o) : TIntermTyped(TType(EbtFloat, EbpUndefined)), op(o) {}
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000431 TIntermOperator(TOperator o, TType& t) : TIntermTyped(t), op(o) {}
432 TOperator op;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000433};
434
435//
436// Nodes for all the basic binary math operators.
437//
438class TIntermBinary : public TIntermOperator {
439public:
daniel@transgaming.com4167cc92013-01-11 04:11:53 +0000440 TIntermBinary(TOperator o) : TIntermOperator(o), addIndexClamp(false) {}
alokp@chromium.org58e54292010-08-24 21:40:03 +0000441
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000442 virtual TIntermBinary* getAsBinaryNode() { return this; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000443 virtual void traverse(TIntermTraverser*);
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700444 virtual bool replaceChildNode(
445 TIntermNode *original, TIntermNode *replacement);
alokp@chromium.org58e54292010-08-24 21:40:03 +0000446
Jamie Madillf4b79ba2013-11-26 10:38:18 -0500447 virtual bool hasSideEffects() const { return (isAssignment() || left->hasSideEffects() || right->hasSideEffects()); }
Jamie Madill3c9eeb92013-11-04 11:09:26 -0500448
alokp@chromium.org58e54292010-08-24 21:40:03 +0000449 void setLeft(TIntermTyped* n) { left = n; }
450 void setRight(TIntermTyped* n) { right = n; }
451 TIntermTyped* getLeft() const { return left; }
452 TIntermTyped* getRight() const { return right; }
453 bool promote(TInfoSink&);
454
daniel@transgaming.com4167cc92013-01-11 04:11:53 +0000455 void setAddIndexClamp() { addIndexClamp = true; }
456 bool getAddIndexClamp() { return addIndexClamp; }
457
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000458protected:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000459 TIntermTyped* left;
460 TIntermTyped* right;
daniel@transgaming.com4167cc92013-01-11 04:11:53 +0000461
462 // If set to true, wrap any EOpIndexIndirect with a clamp to bounds.
463 bool addIndexClamp;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000464};
465
466//
467// Nodes for unary math operators.
468//
469class TIntermUnary : public TIntermOperator {
470public:
zmo@google.com32e97312011-08-24 01:03:11 +0000471 TIntermUnary(TOperator o, TType& t) : TIntermOperator(o, t), operand(0), useEmulatedFunction(false) {}
zmo@google.come4eb9912011-08-29 21:13:12 +0000472 TIntermUnary(TOperator o) : TIntermOperator(o), operand(0), useEmulatedFunction(false) {}
alokp@chromium.org58e54292010-08-24 21:40:03 +0000473
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000474 virtual void traverse(TIntermTraverser*);
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +0000475 virtual TIntermUnary* getAsUnaryNode() { return this; }
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700476 virtual bool replaceChildNode(
477 TIntermNode *original, TIntermNode *replacement);
alokp@chromium.org58e54292010-08-24 21:40:03 +0000478
Jamie Madillf4b79ba2013-11-26 10:38:18 -0500479 virtual bool hasSideEffects() const { return (isAssignment() || operand->hasSideEffects()); }
Jamie Madill3c9eeb92013-11-04 11:09:26 -0500480
alokp@chromium.org58e54292010-08-24 21:40:03 +0000481 void setOperand(TIntermTyped* o) { operand = o; }
482 TIntermTyped* getOperand() { return operand; }
483 bool promote(TInfoSink&);
484
zmo@google.com32e97312011-08-24 01:03:11 +0000485 void setUseEmulatedFunction() { useEmulatedFunction = true; }
486 bool getUseEmulatedFunction() { return useEmulatedFunction; }
487
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000488protected:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000489 TIntermTyped* operand;
zmo@google.comf420c422011-09-12 18:27:59 +0000490
491 // If set to true, replace the built-in function call with an emulated one
492 // to work around driver bugs.
493 bool useEmulatedFunction;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000494};
495
496typedef TVector<TIntermNode*> TIntermSequence;
497typedef TVector<int> TQualifierList;
alokp@chromium.org8b851c62012-06-15 16:25:11 +0000498
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000499//
500// Nodes that operate on an arbitrary sized set of children.
501//
502class TIntermAggregate : public TIntermOperator {
503public:
Jamie Madill075edd82013-07-08 13:30:19 -0400504 TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false), useEmulatedFunction(false) { }
alokp@chromium.org8b851c62012-06-15 16:25:11 +0000505 TIntermAggregate(TOperator o) : TIntermOperator(o), useEmulatedFunction(false) { }
506 ~TIntermAggregate() { }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000507
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000508 virtual TIntermAggregate* getAsAggregate() { return this; }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000509 virtual void traverse(TIntermTraverser*);
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700510 virtual bool replaceChildNode(
511 TIntermNode *original, TIntermNode *replacement);
alokp@chromium.org58e54292010-08-24 21:40:03 +0000512
Jamie Madill3c9eeb92013-11-04 11:09:26 -0500513 // Conservatively assume function calls and other aggregate operators have side-effects
514 virtual bool hasSideEffects() const { return true; }
515
alokp@chromium.org58e54292010-08-24 21:40:03 +0000516 TIntermSequence& getSequence() { return sequence; }
alokp@chromium.orgb19403a2010-09-08 17:56:26 +0000517
alokp@chromium.org58e54292010-08-24 21:40:03 +0000518 void setName(const TString& n) { name = n; }
519 const TString& getName() const { return name; }
520
521 void setUserDefined() { userDefined = true; }
maxvujovic@gmail.com66ebd012012-05-30 22:18:11 +0000522 bool isUserDefined() const { return userDefined; }
alokp@chromium.orgb19403a2010-09-08 17:56:26 +0000523
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000524 void setOptimize(bool o) { optimize = o; }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000525 bool getOptimize() { return optimize; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000526 void setDebug(bool d) { debug = d; }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000527 bool getDebug() { return debug; }
alokp@chromium.org8b851c62012-06-15 16:25:11 +0000528
zmo@google.comf420c422011-09-12 18:27:59 +0000529 void setUseEmulatedFunction() { useEmulatedFunction = true; }
530 bool getUseEmulatedFunction() { return useEmulatedFunction; }
531
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000532protected:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000533 TIntermAggregate(const TIntermAggregate&); // disallow copy constructor
534 TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator
535 TIntermSequence sequence;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000536 TString name;
537 bool userDefined; // used for user defined function names
alokp@chromium.orgb19403a2010-09-08 17:56:26 +0000538
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000539 bool optimize;
540 bool debug;
zmo@google.comf420c422011-09-12 18:27:59 +0000541
542 // If set to true, replace the built-in function call with an emulated one
543 // to work around driver bugs.
544 bool useEmulatedFunction;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000545};
546
547//
548// For if tests. Simplified since there is no switch statement.
549//
550class TIntermSelection : public TIntermTyped {
551public:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000552 TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB) :
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000553 TIntermTyped(TType(EbtVoid, EbpUndefined)), condition(cond), trueBlock(trueB), falseBlock(falseB) {}
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000554 TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB, const TType& type) :
555 TIntermTyped(type), condition(cond), trueBlock(trueB), falseBlock(falseB) {}
alokp@chromium.org58e54292010-08-24 21:40:03 +0000556
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000557 virtual void traverse(TIntermTraverser*);
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700558 virtual bool replaceChildNode(
559 TIntermNode *original, TIntermNode *replacement);
alokp@chromium.org58e54292010-08-24 21:40:03 +0000560
Jamie Madill3c9eeb92013-11-04 11:09:26 -0500561 // Conservatively assume selections have side-effects
562 virtual bool hasSideEffects() const { return true; }
563
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000564 bool usesTernaryOperator() const { return getBasicType() != EbtVoid; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000565 TIntermNode* getCondition() const { return condition; }
566 TIntermNode* getTrueBlock() const { return trueBlock; }
567 TIntermNode* getFalseBlock() const { return falseBlock; }
568 TIntermSelection* getAsSelectionNode() { return this; }
569
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000570protected:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000571 TIntermTyped* condition;
572 TIntermNode* trueBlock;
573 TIntermNode* falseBlock;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000574};
575
576enum Visit
577{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000578 PreVisit,
579 InVisit,
580 PostVisit
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000581};
582
583//
584// For traversing the tree. User should derive from this,
585// put their traversal specific data in it, and then pass
586// it to a Traverse method.
587//
588// When using this, just fill in the methods for nodes you want visited.
589// Return false from a pre-visit to skip visiting that node's subtree.
590//
591class TIntermTraverser
592{
593public:
Alok Priyadarshi8156b6b2013-09-23 14:56:58 -0400594 POOL_ALLOCATOR_NEW_DELETE();
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000595 TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false, bool rightToLeft = false) :
596 preVisit(preVisit),
597 inVisit(inVisit),
598 postVisit(postVisit),
599 rightToLeft(rightToLeft),
Jamie Madilleb1a0102013-07-08 13:31:38 -0400600 depth(0),
601 maxDepth(0) {}
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700602 virtual ~TIntermTraverser() {}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000603
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000604 virtual void visitSymbol(TIntermSymbol*) {}
605 virtual void visitConstantUnion(TIntermConstantUnion*) {}
606 virtual bool visitBinary(Visit visit, TIntermBinary*) {return true;}
607 virtual bool visitUnary(Visit visit, TIntermUnary*) {return true;}
608 virtual bool visitSelection(Visit visit, TIntermSelection*) {return true;}
609 virtual bool visitAggregate(Visit visit, TIntermAggregate*) {return true;}
610 virtual bool visitLoop(Visit visit, TIntermLoop*) {return true;}
611 virtual bool visitBranch(Visit visit, TIntermBranch*) {return true;}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000612
Jamie Madilleb1a0102013-07-08 13:31:38 -0400613 int getMaxDepth() const {return maxDepth;}
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700614
615 void incrementDepth(TIntermNode *current)
616 {
617 depth++;
618 maxDepth = std::max(maxDepth, depth);
619 path.push_back(current);
620 }
621
622 void decrementDepth()
623 {
624 depth--;
625 path.pop_back();
626 }
627
628 TIntermNode *getParentNode()
629 {
630 return path.size() == 0 ? NULL : path.back();
631 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000632
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +0000633 // Return the original name if hash function pointer is NULL;
634 // otherwise return the hashed name.
635 static TString hash(const TString& name, ShHashFunction64 hashFunction);
636
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000637 const bool preVisit;
638 const bool inVisit;
639 const bool postVisit;
640 const bool rightToLeft;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000641
642protected:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000643 int depth;
Jamie Madilleb1a0102013-07-08 13:31:38 -0400644 int maxDepth;
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700645
646 // All the nodes from root to the current node's parent during traversing.
647 TVector<TIntermNode *> path;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000648};
649
650#endif // __INTERMEDIATE_H