blob: b09fc9e415544b31542cf17d6ca872eb5fa39670 [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>
Jamie Madilldd0d3422014-03-26 14:01:56 -040022#include <queue>
Geoff Lang17732822013-08-29 13:46:49 -040023#include "compiler/translator/Common.h"
24#include "compiler/translator/Types.h"
25#include "compiler/translator/ConstantUnion.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000026
27//
28// Operators used by the high-level (parse tree) representation.
29//
30enum TOperator {
alokp@chromium.org2cf17712010-03-30 20:33:18 +000031 EOpNull, // if in a node, should only mean a node is still being built
32 EOpSequence, // denotes a list of statements, or parameters, etc.
33 EOpFunctionCall,
34 EOpFunction, // For function definition
35 EOpParameters, // an aggregate listing the parameters to a function
daniel@transgaming.comd1acd1e2010-04-13 03:25:57 +000036
alokp@chromium.org2cf17712010-03-30 20:33:18 +000037 EOpDeclaration,
daniel@transgaming.comd1acd1e2010-04-13 03:25:57 +000038 EOpPrototype,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000039
alokp@chromium.org2cf17712010-03-30 20:33:18 +000040 //
41 // Unary operators
42 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000043
alokp@chromium.org2cf17712010-03-30 20:33:18 +000044 EOpNegative,
45 EOpLogicalNot,
46 EOpVectorLogicalNot,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000047
alokp@chromium.org2cf17712010-03-30 20:33:18 +000048 EOpPostIncrement,
49 EOpPostDecrement,
50 EOpPreIncrement,
51 EOpPreDecrement,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000052
alokp@chromium.org2cf17712010-03-30 20:33:18 +000053 EOpConvIntToBool,
Nicolas Capensab60b932013-06-05 10:31:21 -040054 EOpConvUIntToBool,
alokp@chromium.org2cf17712010-03-30 20:33:18 +000055 EOpConvFloatToBool,
56 EOpConvBoolToFloat,
57 EOpConvIntToFloat,
Nicolas Capensab60b932013-06-05 10:31:21 -040058 EOpConvUIntToFloat,
alokp@chromium.org2cf17712010-03-30 20:33:18 +000059 EOpConvFloatToInt,
60 EOpConvBoolToInt,
Nicolas Capensab60b932013-06-05 10:31:21 -040061 EOpConvUIntToInt,
62 EOpConvIntToUInt,
63 EOpConvFloatToUInt,
64 EOpConvBoolToUInt,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000065
alokp@chromium.org2cf17712010-03-30 20:33:18 +000066 //
67 // binary operations
68 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000069
alokp@chromium.org2cf17712010-03-30 20:33:18 +000070 EOpAdd,
71 EOpSub,
72 EOpMul,
73 EOpDiv,
74 EOpEqual,
75 EOpNotEqual,
76 EOpVectorEqual,
77 EOpVectorNotEqual,
78 EOpLessThan,
79 EOpGreaterThan,
80 EOpLessThanEqual,
81 EOpGreaterThanEqual,
82 EOpComma,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000083
alokp@chromium.org2cf17712010-03-30 20:33:18 +000084 EOpVectorTimesScalar,
85 EOpVectorTimesMatrix,
86 EOpMatrixTimesVector,
87 EOpMatrixTimesScalar,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000088
alokp@chromium.org2cf17712010-03-30 20:33:18 +000089 EOpLogicalOr,
90 EOpLogicalXor,
91 EOpLogicalAnd,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000092
alokp@chromium.org2cf17712010-03-30 20:33:18 +000093 EOpIndexDirect,
94 EOpIndexIndirect,
95 EOpIndexDirectStruct,
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +000096 EOpIndexDirectInterfaceBlock,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000097
alokp@chromium.org2cf17712010-03-30 20:33:18 +000098 EOpVectorSwizzle,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000099
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000100 //
101 // Built-in functions potentially mapped to operators
102 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000103
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000104 EOpRadians,
105 EOpDegrees,
106 EOpSin,
107 EOpCos,
108 EOpTan,
109 EOpAsin,
110 EOpAcos,
111 EOpAtan,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000112
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000113 EOpPow,
114 EOpExp,
115 EOpLog,
116 EOpExp2,
117 EOpLog2,
118 EOpSqrt,
119 EOpInverseSqrt,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000120
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000121 EOpAbs,
122 EOpSign,
123 EOpFloor,
124 EOpCeil,
125 EOpFract,
126 EOpMod,
127 EOpMin,
128 EOpMax,
129 EOpClamp,
130 EOpMix,
131 EOpStep,
132 EOpSmoothStep,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000133
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000134 EOpLength,
135 EOpDistance,
136 EOpDot,
137 EOpCross,
138 EOpNormalize,
139 EOpFaceForward,
140 EOpReflect,
141 EOpRefract,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000142
alokp@chromium.org06098892010-08-26 19:36:42 +0000143 EOpDFdx, // Fragment only, OES_standard_derivatives extension
144 EOpDFdy, // Fragment only, OES_standard_derivatives extension
145 EOpFwidth, // Fragment only, OES_standard_derivatives extension
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000146
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000147 EOpMatrixTimesMatrix,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000148
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000149 EOpAny,
150 EOpAll,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000151
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000152 //
153 // Branch
154 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000155
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000156 EOpKill, // Fragment only
157 EOpReturn,
158 EOpBreak,
159 EOpContinue,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000160
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000161 //
162 // Constructors
163 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000164
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000165 EOpConstructInt,
Nicolas Capensab60b932013-06-05 10:31:21 -0400166 EOpConstructUInt,
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000167 EOpConstructBool,
168 EOpConstructFloat,
169 EOpConstructVec2,
170 EOpConstructVec3,
171 EOpConstructVec4,
172 EOpConstructBVec2,
173 EOpConstructBVec3,
174 EOpConstructBVec4,
175 EOpConstructIVec2,
176 EOpConstructIVec3,
177 EOpConstructIVec4,
shannonwoods@chromium.org8c788e82013-05-30 00:20:21 +0000178 EOpConstructUVec2,
179 EOpConstructUVec3,
180 EOpConstructUVec4,
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000181 EOpConstructMat2,
182 EOpConstructMat3,
183 EOpConstructMat4,
184 EOpConstructStruct,
185
186 //
187 // moves
188 //
189
190 EOpAssign,
191 EOpInitialize,
192 EOpAddAssign,
193 EOpSubAssign,
194 EOpMulAssign,
195 EOpVectorTimesMatrixAssign,
196 EOpVectorTimesScalarAssign,
197 EOpMatrixTimesScalarAssign,
198 EOpMatrixTimesMatrixAssign,
daniel@transgaming.comb3077d02013-01-11 04:12:09 +0000199 EOpDivAssign
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000200};
201
alokp@chromium.orgb59a7782010-11-24 18:38:33 +0000202extern const char* getOperatorString(TOperator op);
203
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000204class TIntermTraverser;
205class TIntermAggregate;
206class TIntermBinary;
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +0000207class TIntermUnary;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000208class TIntermConstantUnion;
209class TIntermSelection;
210class TIntermTyped;
211class TIntermSymbol;
alokp@chromium.orgd88b7732010-05-26 15:13:14 +0000212class TIntermLoop;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000213class TInfoSink;
214
215//
216// Base class for the tree nodes
217//
218class TIntermNode {
219public:
Alok Priyadarshi8156b6b2013-09-23 14:56:58 -0400220 POOL_ALLOCATOR_NEW_DELETE();
Jamie Madill075edd82013-07-08 13:30:19 -0400221 TIntermNode() {
222 // TODO: Move this to TSourceLoc constructor
223 // after getting rid of TPublicType.
224 line.first_file = line.last_file = 0;
225 line.first_line = line.last_line = 0;
226 }
227 virtual ~TIntermNode() { }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000228
Jamie Madill075edd82013-07-08 13:30:19 -0400229 const TSourceLoc& getLine() const { return line; }
230 void setLine(const TSourceLoc& l) { line = l; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000231
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000232 virtual void traverse(TIntermTraverser*) = 0;
alokp@chromium.orgd88b7732010-05-26 15:13:14 +0000233 virtual TIntermTyped* getAsTyped() { return 0; }
234 virtual TIntermConstantUnion* getAsConstantUnion() { return 0; }
235 virtual TIntermAggregate* getAsAggregate() { return 0; }
236 virtual TIntermBinary* getAsBinaryNode() { return 0; }
237 virtual TIntermUnary* getAsUnaryNode() { return 0; }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000238 virtual TIntermSelection* getAsSelectionNode() { return 0; }
alokp@chromium.orgd88b7732010-05-26 15:13:14 +0000239 virtual TIntermSymbol* getAsSymbolNode() { return 0; }
240 virtual TIntermLoop* getAsLoopNode() { return 0; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000241
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700242 // Replace a child node. Return true if |original| is a child
243 // node and it is replaced; otherwise, return false.
244 virtual bool replaceChildNode(
245 TIntermNode *original, TIntermNode *replacement) = 0;
246
Jamie Madilldd0d3422014-03-26 14:01:56 -0400247 // For traversing a tree in no particular order, but using
248 // heap memory.
249 virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const = 0;
250
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000251protected:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000252 TSourceLoc line;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000253};
254
255//
256// This is just to help yacc.
257//
258struct TIntermNodePair {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000259 TIntermNode* node1;
260 TIntermNode* node2;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000261};
262
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000263//
264// Intermediate class for nodes that have a type.
265//
266class TIntermTyped : public TIntermNode {
267public:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000268 TIntermTyped(const TType& t) : type(t) { }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000269 virtual TIntermTyped* getAsTyped() { return this; }
alokp@chromium.orgdd037b22010-03-30 18:47:20 +0000270
Jamie Madill3c9eeb92013-11-04 11:09:26 -0500271 virtual bool hasSideEffects() const = 0;
272
alokp@chromium.org58e54292010-08-24 21:40:03 +0000273 void setType(const TType& t) { type = t; }
274 const TType& getType() const { return type; }
275 TType* getTypePointer() { return &type; }
276
277 TBasicType getBasicType() const { return type.getBasicType(); }
278 TQualifier getQualifier() const { return type.getQualifier(); }
279 TPrecision getPrecision() const { return type.getPrecision(); }
Shannon Woods3841b8e2013-09-10 18:23:12 -0400280 int getCols() const { return type.getCols(); }
281 int getRows() const { return type.getRows(); }
282 int getNominalSize() const { return type.getNominalSize(); }
283 int getSecondarySize() const { return type.getSecondarySize(); }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000284
Jamie Madill98493dd2013-07-08 14:39:03 -0400285 bool isInterfaceBlock() const { return type.isInterfaceBlock(); }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000286 bool isMatrix() const { return type.isMatrix(); }
287 bool isArray() const { return type.isArray(); }
288 bool isVector() const { return type.isVector(); }
289 bool isScalar() const { return type.isScalar(); }
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000290 bool isScalarInt() const { return type.isScalarInt(); }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000291 const char* getBasicString() const { return type.getBasicString(); }
292 const char* getQualifierString() const { return type.getQualifierString(); }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000293 TString getCompleteString() const { return type.getCompleteString(); }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000294
daniel@transgaming.com3ca980a2012-12-20 21:11:52 +0000295 int getArraySize() const { return type.getArraySize(); }
296
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000297protected:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000298 TType type;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000299};
300
301//
302// Handle for, do-while, and while loops.
303//
alokp@chromium.org52813552010-11-16 18:36:09 +0000304enum TLoopType {
305 ELoopFor,
306 ELoopWhile,
daniel@transgaming.comb3077d02013-01-11 04:12:09 +0000307 ELoopDoWhile
alokp@chromium.org52813552010-11-16 18:36:09 +0000308};
309
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000310class TIntermLoop : public TIntermNode {
311public:
alokp@chromium.org52813552010-11-16 18:36:09 +0000312 TIntermLoop(TLoopType aType,
313 TIntermNode *aInit, TIntermTyped* aCond, TIntermTyped* aExpr,
314 TIntermNode* aBody) :
315 type(aType),
316 init(aInit),
317 cond(aCond),
318 expr(aExpr),
zmo@google.com0b8d4eb2011-04-04 19:17:11 +0000319 body(aBody),
320 unrollFlag(false) { }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000321
alokp@chromium.orgd88b7732010-05-26 15:13:14 +0000322 virtual TIntermLoop* getAsLoopNode() { return this; }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000323 virtual void traverse(TIntermTraverser*);
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700324 virtual bool replaceChildNode(
325 TIntermNode *original, TIntermNode *replacement);
alokp@chromium.org58e54292010-08-24 21:40:03 +0000326
alokp@chromium.org52813552010-11-16 18:36:09 +0000327 TLoopType getType() const { return type; }
328 TIntermNode* getInit() { return init; }
329 TIntermTyped* getCondition() { return cond; }
330 TIntermTyped* getExpression() { return expr; }
331 TIntermNode* getBody() { return body; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000332
zmo@google.com0b8d4eb2011-04-04 19:17:11 +0000333 void setUnrollFlag(bool flag) { unrollFlag = flag; }
334 bool getUnrollFlag() { return unrollFlag; }
335
Jamie Madilldd0d3422014-03-26 14:01:56 -0400336 virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const;
337
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000338protected:
alokp@chromium.org52813552010-11-16 18:36:09 +0000339 TLoopType type;
340 TIntermNode* init; // for-loop initialization
341 TIntermTyped* cond; // loop exit condition
342 TIntermTyped* expr; // for-loop expression
343 TIntermNode* body; // loop body
zmo@google.com0b8d4eb2011-04-04 19:17:11 +0000344
345 bool unrollFlag; // Whether the loop should be unrolled or not.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000346};
347
348//
349// Handle break, continue, return, and kill.
350//
351class TIntermBranch : public TIntermNode {
352public:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000353 TIntermBranch(TOperator op, TIntermTyped* e) :
354 flowOp(op),
355 expression(e) { }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000356
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000357 virtual void traverse(TIntermTraverser*);
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700358 virtual bool replaceChildNode(
359 TIntermNode *original, TIntermNode *replacement);
alokp@chromium.org58e54292010-08-24 21:40:03 +0000360
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000361 TOperator getFlowOp() { return flowOp; }
362 TIntermTyped* getExpression() { return expression; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000363
Jamie Madilldd0d3422014-03-26 14:01:56 -0400364 virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const;
365
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000366protected:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000367 TOperator flowOp;
368 TIntermTyped* expression; // non-zero except for "return exp;" statements
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000369};
370
371//
372// Nodes that correspond to symbols or constants in the source code.
373//
374class TIntermSymbol : public TIntermTyped {
375public:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000376 // if symbol is initialized as symbol(sym), the memory comes from the poolallocator of sym. If sym comes from
377 // per process globalpoolallocator, then it causes increased memory usage per compile
378 // it is essential to use "symbol = sym" to assign to symbol
379 TIntermSymbol(int i, const TString& sym, const TType& t) :
Zhenyao Mo3cdfcce2014-03-07 13:00:08 -0800380 TIntermTyped(t), id(i) { symbol = sym; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000381
Jamie Madill3c9eeb92013-11-04 11:09:26 -0500382 virtual bool hasSideEffects() const { return false; }
383
alokp@chromium.org58e54292010-08-24 21:40:03 +0000384 int getId() const { return id; }
385 const TString& getSymbol() const { return symbol; }
386
zmo@google.comfd747b82011-04-23 01:30:07 +0000387 void setId(int newId) { id = newId; }
zmo@google.comfd747b82011-04-23 01:30:07 +0000388
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000389 virtual void traverse(TIntermTraverser*);
390 virtual TIntermSymbol* getAsSymbolNode() { return this; }
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700391 virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000392
Jamie Madilldd0d3422014-03-26 14:01:56 -0400393 virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const {}
394
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000395protected:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000396 int id;
397 TString symbol;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000398};
399
400class TIntermConstantUnion : public TIntermTyped {
401public:
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000402 TIntermConstantUnion(ConstantUnion *unionPointer, const TType& t) : TIntermTyped(t), unionArrayPointer(unionPointer) { }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000403
Jamie Madill3c9eeb92013-11-04 11:09:26 -0500404 virtual bool hasSideEffects() const { return false; }
405
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000406 ConstantUnion* getUnionArrayPointer() const { return unionArrayPointer; }
shannon.woods%transgaming.com@gtempaccount.comc0d0c222013-04-13 03:29:36 +0000407
Nicolas Capensa621c2e2013-11-20 13:40:23 -0500408 int getIConst(size_t index) const { return unionArrayPointer ? unionArrayPointer[index].getIConst() : 0; }
409 unsigned int getUConst(size_t index) const { return unionArrayPointer ? unionArrayPointer[index].getUConst() : 0; }
410 float getFConst(size_t index) const { return unionArrayPointer ? unionArrayPointer[index].getFConst() : 0.0f; }
411 bool getBConst(size_t index) const { return unionArrayPointer ? unionArrayPointer[index].getBConst() : false; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000412
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000413 virtual TIntermConstantUnion* getAsConstantUnion() { return this; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000414 virtual void traverse(TIntermTraverser*);
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700415 virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000416
417 TIntermTyped* fold(TOperator, TIntermTyped*, TInfoSink&);
418
Jamie Madilldd0d3422014-03-26 14:01:56 -0400419 virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const {}
420
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000421protected:
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000422 ConstantUnion *unionArrayPointer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000423};
424
425//
426// Intermediate class for node types that hold operators.
427//
428class TIntermOperator : public TIntermTyped {
429public:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000430 TOperator getOp() const { return op; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000431 void setOp(TOperator o) { op = o; }
432
Jamie Madillf4b79ba2013-11-26 10:38:18 -0500433 bool isAssignment() const;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000434 bool isConstructor() const;
alokp@chromium.org58e54292010-08-24 21:40:03 +0000435
Jamie Madillf4b79ba2013-11-26 10:38:18 -0500436 virtual bool hasSideEffects() const { return isAssignment(); }
437
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000438protected:
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000439 TIntermOperator(TOperator o) : TIntermTyped(TType(EbtFloat, EbpUndefined)), op(o) {}
Jamie Madille53c98b2014-02-03 11:57:13 -0500440 TIntermOperator(TOperator o, const TType& t) : TIntermTyped(t), op(o) {}
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000441 TOperator op;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000442};
443
444//
445// Nodes for all the basic binary math operators.
446//
447class TIntermBinary : public TIntermOperator {
448public:
daniel@transgaming.com4167cc92013-01-11 04:11:53 +0000449 TIntermBinary(TOperator o) : TIntermOperator(o), addIndexClamp(false) {}
alokp@chromium.org58e54292010-08-24 21:40:03 +0000450
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000451 virtual TIntermBinary* getAsBinaryNode() { return this; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000452 virtual void traverse(TIntermTraverser*);
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700453 virtual bool replaceChildNode(
454 TIntermNode *original, TIntermNode *replacement);
alokp@chromium.org58e54292010-08-24 21:40:03 +0000455
Jamie Madillf4b79ba2013-11-26 10:38:18 -0500456 virtual bool hasSideEffects() const { return (isAssignment() || left->hasSideEffects() || right->hasSideEffects()); }
Jamie Madill3c9eeb92013-11-04 11:09:26 -0500457
alokp@chromium.org58e54292010-08-24 21:40:03 +0000458 void setLeft(TIntermTyped* n) { left = n; }
459 void setRight(TIntermTyped* n) { right = n; }
460 TIntermTyped* getLeft() const { return left; }
461 TIntermTyped* getRight() const { return right; }
462 bool promote(TInfoSink&);
463
daniel@transgaming.com4167cc92013-01-11 04:11:53 +0000464 void setAddIndexClamp() { addIndexClamp = true; }
465 bool getAddIndexClamp() { return addIndexClamp; }
466
Jamie Madilldd0d3422014-03-26 14:01:56 -0400467 virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const;
468
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000469protected:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000470 TIntermTyped* left;
471 TIntermTyped* right;
daniel@transgaming.com4167cc92013-01-11 04:11:53 +0000472
473 // If set to true, wrap any EOpIndexIndirect with a clamp to bounds.
474 bool addIndexClamp;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000475};
476
477//
478// Nodes for unary math operators.
479//
480class TIntermUnary : public TIntermOperator {
481public:
Jamie Madille53c98b2014-02-03 11:57:13 -0500482 TIntermUnary(TOperator o, const TType& t) : TIntermOperator(o, t), operand(0), useEmulatedFunction(false) {}
zmo@google.come4eb9912011-08-29 21:13:12 +0000483 TIntermUnary(TOperator o) : TIntermOperator(o), operand(0), useEmulatedFunction(false) {}
alokp@chromium.org58e54292010-08-24 21:40:03 +0000484
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000485 virtual void traverse(TIntermTraverser*);
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +0000486 virtual TIntermUnary* getAsUnaryNode() { return this; }
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700487 virtual bool replaceChildNode(
488 TIntermNode *original, TIntermNode *replacement);
alokp@chromium.org58e54292010-08-24 21:40:03 +0000489
Jamie Madillf4b79ba2013-11-26 10:38:18 -0500490 virtual bool hasSideEffects() const { return (isAssignment() || operand->hasSideEffects()); }
Jamie Madill3c9eeb92013-11-04 11:09:26 -0500491
alokp@chromium.org58e54292010-08-24 21:40:03 +0000492 void setOperand(TIntermTyped* o) { operand = o; }
493 TIntermTyped* getOperand() { return operand; }
494 bool promote(TInfoSink&);
495
zmo@google.com32e97312011-08-24 01:03:11 +0000496 void setUseEmulatedFunction() { useEmulatedFunction = true; }
497 bool getUseEmulatedFunction() { return useEmulatedFunction; }
498
Jamie Madilldd0d3422014-03-26 14:01:56 -0400499 virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const;
500
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000501protected:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000502 TIntermTyped* operand;
zmo@google.comf420c422011-09-12 18:27:59 +0000503
504 // If set to true, replace the built-in function call with an emulated one
505 // to work around driver bugs.
506 bool useEmulatedFunction;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000507};
508
509typedef TVector<TIntermNode*> TIntermSequence;
510typedef TVector<int> TQualifierList;
alokp@chromium.org8b851c62012-06-15 16:25:11 +0000511
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000512//
513// Nodes that operate on an arbitrary sized set of children.
514//
515class TIntermAggregate : public TIntermOperator {
516public:
Jamie Madill075edd82013-07-08 13:30:19 -0400517 TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false), useEmulatedFunction(false) { }
alokp@chromium.org8b851c62012-06-15 16:25:11 +0000518 TIntermAggregate(TOperator o) : TIntermOperator(o), useEmulatedFunction(false) { }
519 ~TIntermAggregate() { }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000520
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000521 virtual TIntermAggregate* getAsAggregate() { return this; }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000522 virtual void traverse(TIntermTraverser*);
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700523 virtual bool replaceChildNode(
524 TIntermNode *original, TIntermNode *replacement);
alokp@chromium.org58e54292010-08-24 21:40:03 +0000525
Jamie Madill3c9eeb92013-11-04 11:09:26 -0500526 // Conservatively assume function calls and other aggregate operators have side-effects
527 virtual bool hasSideEffects() const { return true; }
528
alokp@chromium.org58e54292010-08-24 21:40:03 +0000529 TIntermSequence& getSequence() { return sequence; }
alokp@chromium.orgb19403a2010-09-08 17:56:26 +0000530
alokp@chromium.org58e54292010-08-24 21:40:03 +0000531 void setName(const TString& n) { name = n; }
532 const TString& getName() const { return name; }
533
534 void setUserDefined() { userDefined = true; }
maxvujovic@gmail.com66ebd012012-05-30 22:18:11 +0000535 bool isUserDefined() const { return userDefined; }
alokp@chromium.orgb19403a2010-09-08 17:56:26 +0000536
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000537 void setOptimize(bool o) { optimize = o; }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000538 bool getOptimize() { return optimize; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000539 void setDebug(bool d) { debug = d; }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000540 bool getDebug() { return debug; }
alokp@chromium.org8b851c62012-06-15 16:25:11 +0000541
zmo@google.comf420c422011-09-12 18:27:59 +0000542 void setUseEmulatedFunction() { useEmulatedFunction = true; }
543 bool getUseEmulatedFunction() { return useEmulatedFunction; }
544
Jamie Madilldd0d3422014-03-26 14:01:56 -0400545 virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const;
546
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000547protected:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000548 TIntermAggregate(const TIntermAggregate&); // disallow copy constructor
549 TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator
550 TIntermSequence sequence;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000551 TString name;
552 bool userDefined; // used for user defined function names
alokp@chromium.orgb19403a2010-09-08 17:56:26 +0000553
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000554 bool optimize;
555 bool debug;
zmo@google.comf420c422011-09-12 18:27:59 +0000556
557 // If set to true, replace the built-in function call with an emulated one
558 // to work around driver bugs.
559 bool useEmulatedFunction;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000560};
561
562//
563// For if tests. Simplified since there is no switch statement.
564//
565class TIntermSelection : public TIntermTyped {
566public:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000567 TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB) :
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000568 TIntermTyped(TType(EbtVoid, EbpUndefined)), condition(cond), trueBlock(trueB), falseBlock(falseB) {}
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000569 TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB, const TType& type) :
570 TIntermTyped(type), condition(cond), trueBlock(trueB), falseBlock(falseB) {}
alokp@chromium.org58e54292010-08-24 21:40:03 +0000571
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000572 virtual void traverse(TIntermTraverser*);
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700573 virtual bool replaceChildNode(
574 TIntermNode *original, TIntermNode *replacement);
alokp@chromium.org58e54292010-08-24 21:40:03 +0000575
Jamie Madill3c9eeb92013-11-04 11:09:26 -0500576 // Conservatively assume selections have side-effects
577 virtual bool hasSideEffects() const { return true; }
578
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000579 bool usesTernaryOperator() const { return getBasicType() != EbtVoid; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000580 TIntermNode* getCondition() const { return condition; }
581 TIntermNode* getTrueBlock() const { return trueBlock; }
582 TIntermNode* getFalseBlock() const { return falseBlock; }
583 TIntermSelection* getAsSelectionNode() { return this; }
584
Jamie Madilldd0d3422014-03-26 14:01:56 -0400585 virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const;
586
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000587protected:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000588 TIntermTyped* condition;
589 TIntermNode* trueBlock;
590 TIntermNode* falseBlock;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000591};
592
593enum Visit
594{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000595 PreVisit,
596 InVisit,
597 PostVisit
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000598};
599
600//
601// For traversing the tree. User should derive from this,
602// put their traversal specific data in it, and then pass
603// it to a Traverse method.
604//
605// When using this, just fill in the methods for nodes you want visited.
606// Return false from a pre-visit to skip visiting that node's subtree.
607//
608class TIntermTraverser
609{
610public:
Alok Priyadarshi8156b6b2013-09-23 14:56:58 -0400611 POOL_ALLOCATOR_NEW_DELETE();
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000612 TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false, bool rightToLeft = false) :
613 preVisit(preVisit),
614 inVisit(inVisit),
615 postVisit(postVisit),
616 rightToLeft(rightToLeft),
Jamie Madilleb1a0102013-07-08 13:31:38 -0400617 depth(0),
618 maxDepth(0) {}
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700619 virtual ~TIntermTraverser() {}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000620
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000621 virtual void visitSymbol(TIntermSymbol*) {}
622 virtual void visitConstantUnion(TIntermConstantUnion*) {}
623 virtual bool visitBinary(Visit visit, TIntermBinary*) {return true;}
624 virtual bool visitUnary(Visit visit, TIntermUnary*) {return true;}
625 virtual bool visitSelection(Visit visit, TIntermSelection*) {return true;}
626 virtual bool visitAggregate(Visit visit, TIntermAggregate*) {return true;}
627 virtual bool visitLoop(Visit visit, TIntermLoop*) {return true;}
628 virtual bool visitBranch(Visit visit, TIntermBranch*) {return true;}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000629
Jamie Madilleb1a0102013-07-08 13:31:38 -0400630 int getMaxDepth() const {return maxDepth;}
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700631
632 void incrementDepth(TIntermNode *current)
633 {
634 depth++;
635 maxDepth = std::max(maxDepth, depth);
636 path.push_back(current);
637 }
638
639 void decrementDepth()
640 {
641 depth--;
642 path.pop_back();
643 }
644
645 TIntermNode *getParentNode()
646 {
647 return path.size() == 0 ? NULL : path.back();
648 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000649
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +0000650 // Return the original name if hash function pointer is NULL;
651 // otherwise return the hashed name.
652 static TString hash(const TString& name, ShHashFunction64 hashFunction);
653
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000654 const bool preVisit;
655 const bool inVisit;
656 const bool postVisit;
657 const bool rightToLeft;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000658
659protected:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000660 int depth;
Jamie Madilleb1a0102013-07-08 13:31:38 -0400661 int maxDepth;
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700662
663 // All the nodes from root to the current node's parent during traversing.
664 TVector<TIntermNode *> path;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000665};
666
667#endif // __INTERMEDIATE_H