blob: 0c3a82bba19dc4a707f2513f417a5d5e9e8b0ed7 [file] [log] [blame]
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001//
Nicolas Capens16004fc2014-06-11 11:29:11 -04002// Copyright (c) 2002-2014 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 //
54 // binary operations
55 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000056
alokp@chromium.org2cf17712010-03-30 20:33:18 +000057 EOpAdd,
58 EOpSub,
59 EOpMul,
60 EOpDiv,
61 EOpEqual,
62 EOpNotEqual,
63 EOpVectorEqual,
64 EOpVectorNotEqual,
65 EOpLessThan,
66 EOpGreaterThan,
67 EOpLessThanEqual,
68 EOpGreaterThanEqual,
69 EOpComma,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000070
alokp@chromium.org2cf17712010-03-30 20:33:18 +000071 EOpVectorTimesScalar,
72 EOpVectorTimesMatrix,
73 EOpMatrixTimesVector,
74 EOpMatrixTimesScalar,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000075
alokp@chromium.org2cf17712010-03-30 20:33:18 +000076 EOpLogicalOr,
77 EOpLogicalXor,
78 EOpLogicalAnd,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000079
alokp@chromium.org2cf17712010-03-30 20:33:18 +000080 EOpIndexDirect,
81 EOpIndexIndirect,
82 EOpIndexDirectStruct,
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +000083 EOpIndexDirectInterfaceBlock,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000084
alokp@chromium.org2cf17712010-03-30 20:33:18 +000085 EOpVectorSwizzle,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000086
alokp@chromium.org2cf17712010-03-30 20:33:18 +000087 //
88 // Built-in functions potentially mapped to operators
89 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000090
alokp@chromium.org2cf17712010-03-30 20:33:18 +000091 EOpRadians,
92 EOpDegrees,
93 EOpSin,
94 EOpCos,
95 EOpTan,
96 EOpAsin,
97 EOpAcos,
98 EOpAtan,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000099
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000100 EOpPow,
101 EOpExp,
102 EOpLog,
103 EOpExp2,
104 EOpLog2,
105 EOpSqrt,
106 EOpInverseSqrt,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000107
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000108 EOpAbs,
109 EOpSign,
110 EOpFloor,
111 EOpCeil,
112 EOpFract,
113 EOpMod,
114 EOpMin,
115 EOpMax,
116 EOpClamp,
117 EOpMix,
118 EOpStep,
119 EOpSmoothStep,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000120
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000121 EOpLength,
122 EOpDistance,
123 EOpDot,
124 EOpCross,
125 EOpNormalize,
126 EOpFaceForward,
127 EOpReflect,
128 EOpRefract,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000129
alokp@chromium.org06098892010-08-26 19:36:42 +0000130 EOpDFdx, // Fragment only, OES_standard_derivatives extension
131 EOpDFdy, // Fragment only, OES_standard_derivatives extension
132 EOpFwidth, // Fragment only, OES_standard_derivatives extension
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000133
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000134 EOpMatrixTimesMatrix,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000135
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000136 EOpAny,
137 EOpAll,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000138
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000139 //
140 // Branch
141 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000142
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000143 EOpKill, // Fragment only
144 EOpReturn,
145 EOpBreak,
146 EOpContinue,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000147
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000148 //
149 // Constructors
150 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000151
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000152 EOpConstructInt,
Nicolas Capensab60b932013-06-05 10:31:21 -0400153 EOpConstructUInt,
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000154 EOpConstructBool,
155 EOpConstructFloat,
156 EOpConstructVec2,
157 EOpConstructVec3,
158 EOpConstructVec4,
159 EOpConstructBVec2,
160 EOpConstructBVec3,
161 EOpConstructBVec4,
162 EOpConstructIVec2,
163 EOpConstructIVec3,
164 EOpConstructIVec4,
shannonwoods@chromium.org8c788e82013-05-30 00:20:21 +0000165 EOpConstructUVec2,
166 EOpConstructUVec3,
167 EOpConstructUVec4,
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000168 EOpConstructMat2,
169 EOpConstructMat3,
170 EOpConstructMat4,
171 EOpConstructStruct,
172
173 //
174 // moves
175 //
176
177 EOpAssign,
178 EOpInitialize,
179 EOpAddAssign,
180 EOpSubAssign,
181 EOpMulAssign,
182 EOpVectorTimesMatrixAssign,
183 EOpVectorTimesScalarAssign,
184 EOpMatrixTimesScalarAssign,
185 EOpMatrixTimesMatrixAssign,
daniel@transgaming.comb3077d02013-01-11 04:12:09 +0000186 EOpDivAssign
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000187};
188
alokp@chromium.orgb59a7782010-11-24 18:38:33 +0000189extern const char* getOperatorString(TOperator op);
190
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000191class TIntermTraverser;
192class TIntermAggregate;
193class TIntermBinary;
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +0000194class TIntermUnary;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000195class TIntermConstantUnion;
196class TIntermSelection;
197class TIntermTyped;
198class TIntermSymbol;
alokp@chromium.orgd88b7732010-05-26 15:13:14 +0000199class TIntermLoop;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000200class TInfoSink;
201
202//
203// Base class for the tree nodes
204//
205class TIntermNode {
206public:
Alok Priyadarshi8156b6b2013-09-23 14:56:58 -0400207 POOL_ALLOCATOR_NEW_DELETE();
Jamie Madill075edd82013-07-08 13:30:19 -0400208 TIntermNode() {
209 // TODO: Move this to TSourceLoc constructor
210 // after getting rid of TPublicType.
211 line.first_file = line.last_file = 0;
212 line.first_line = line.last_line = 0;
213 }
214 virtual ~TIntermNode() { }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000215
Jamie Madill075edd82013-07-08 13:30:19 -0400216 const TSourceLoc& getLine() const { return line; }
217 void setLine(const TSourceLoc& l) { line = l; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000218
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000219 virtual void traverse(TIntermTraverser*) = 0;
alokp@chromium.orgd88b7732010-05-26 15:13:14 +0000220 virtual TIntermTyped* getAsTyped() { return 0; }
221 virtual TIntermConstantUnion* getAsConstantUnion() { return 0; }
222 virtual TIntermAggregate* getAsAggregate() { return 0; }
223 virtual TIntermBinary* getAsBinaryNode() { return 0; }
224 virtual TIntermUnary* getAsUnaryNode() { return 0; }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000225 virtual TIntermSelection* getAsSelectionNode() { return 0; }
alokp@chromium.orgd88b7732010-05-26 15:13:14 +0000226 virtual TIntermSymbol* getAsSymbolNode() { return 0; }
227 virtual TIntermLoop* getAsLoopNode() { return 0; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000228
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700229 // Replace a child node. Return true if |original| is a child
230 // node and it is replaced; otherwise, return false.
231 virtual bool replaceChildNode(
232 TIntermNode *original, TIntermNode *replacement) = 0;
233
Jamie Madilldd0d3422014-03-26 14:01:56 -0400234 // For traversing a tree in no particular order, but using
235 // heap memory.
236 virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const = 0;
237
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000238protected:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000239 TSourceLoc line;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000240};
241
242//
243// This is just to help yacc.
244//
245struct TIntermNodePair {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000246 TIntermNode* node1;
247 TIntermNode* node2;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000248};
249
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000250//
251// Intermediate class for nodes that have a type.
252//
253class TIntermTyped : public TIntermNode {
254public:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000255 TIntermTyped(const TType& t) : type(t) { }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000256 virtual TIntermTyped* getAsTyped() { return this; }
alokp@chromium.orgdd037b22010-03-30 18:47:20 +0000257
Jamie Madill3c9eeb92013-11-04 11:09:26 -0500258 virtual bool hasSideEffects() const = 0;
259
alokp@chromium.org58e54292010-08-24 21:40:03 +0000260 void setType(const TType& t) { type = t; }
261 const TType& getType() const { return type; }
262 TType* getTypePointer() { return &type; }
263
264 TBasicType getBasicType() const { return type.getBasicType(); }
265 TQualifier getQualifier() const { return type.getQualifier(); }
266 TPrecision getPrecision() const { return type.getPrecision(); }
Shannon Woods3841b8e2013-09-10 18:23:12 -0400267 int getCols() const { return type.getCols(); }
268 int getRows() const { return type.getRows(); }
269 int getNominalSize() const { return type.getNominalSize(); }
270 int getSecondarySize() const { return type.getSecondarySize(); }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000271
Jamie Madill98493dd2013-07-08 14:39:03 -0400272 bool isInterfaceBlock() const { return type.isInterfaceBlock(); }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000273 bool isMatrix() const { return type.isMatrix(); }
274 bool isArray() const { return type.isArray(); }
275 bool isVector() const { return type.isVector(); }
276 bool isScalar() const { return type.isScalar(); }
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000277 bool isScalarInt() const { return type.isScalarInt(); }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000278 const char* getBasicString() const { return type.getBasicString(); }
279 const char* getQualifierString() const { return type.getQualifierString(); }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000280 TString getCompleteString() const { return type.getCompleteString(); }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000281
daniel@transgaming.com3ca980a2012-12-20 21:11:52 +0000282 int getArraySize() const { return type.getArraySize(); }
283
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000284protected:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000285 TType type;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000286};
287
288//
289// Handle for, do-while, and while loops.
290//
alokp@chromium.org52813552010-11-16 18:36:09 +0000291enum TLoopType {
292 ELoopFor,
293 ELoopWhile,
daniel@transgaming.comb3077d02013-01-11 04:12:09 +0000294 ELoopDoWhile
alokp@chromium.org52813552010-11-16 18:36:09 +0000295};
296
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000297class TIntermLoop : public TIntermNode {
298public:
alokp@chromium.org52813552010-11-16 18:36:09 +0000299 TIntermLoop(TLoopType aType,
300 TIntermNode *aInit, TIntermTyped* aCond, TIntermTyped* aExpr,
301 TIntermNode* aBody) :
302 type(aType),
303 init(aInit),
304 cond(aCond),
305 expr(aExpr),
zmo@google.com0b8d4eb2011-04-04 19:17:11 +0000306 body(aBody),
307 unrollFlag(false) { }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000308
alokp@chromium.orgd88b7732010-05-26 15:13:14 +0000309 virtual TIntermLoop* getAsLoopNode() { return this; }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000310 virtual void traverse(TIntermTraverser*);
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700311 virtual bool replaceChildNode(
312 TIntermNode *original, TIntermNode *replacement);
alokp@chromium.org58e54292010-08-24 21:40:03 +0000313
alokp@chromium.org52813552010-11-16 18:36:09 +0000314 TLoopType getType() const { return type; }
315 TIntermNode* getInit() { return init; }
316 TIntermTyped* getCondition() { return cond; }
317 TIntermTyped* getExpression() { return expr; }
318 TIntermNode* getBody() { return body; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000319
zmo@google.com0b8d4eb2011-04-04 19:17:11 +0000320 void setUnrollFlag(bool flag) { unrollFlag = flag; }
321 bool getUnrollFlag() { return unrollFlag; }
322
Jamie Madilldd0d3422014-03-26 14:01:56 -0400323 virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const;
324
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000325protected:
alokp@chromium.org52813552010-11-16 18:36:09 +0000326 TLoopType type;
327 TIntermNode* init; // for-loop initialization
328 TIntermTyped* cond; // loop exit condition
329 TIntermTyped* expr; // for-loop expression
330 TIntermNode* body; // loop body
zmo@google.com0b8d4eb2011-04-04 19:17:11 +0000331
332 bool unrollFlag; // Whether the loop should be unrolled or not.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000333};
334
335//
336// Handle break, continue, return, and kill.
337//
338class TIntermBranch : public TIntermNode {
339public:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000340 TIntermBranch(TOperator op, TIntermTyped* e) :
341 flowOp(op),
342 expression(e) { }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000343
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000344 virtual void traverse(TIntermTraverser*);
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700345 virtual bool replaceChildNode(
346 TIntermNode *original, TIntermNode *replacement);
alokp@chromium.org58e54292010-08-24 21:40:03 +0000347
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000348 TOperator getFlowOp() { return flowOp; }
349 TIntermTyped* getExpression() { return expression; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000350
Jamie Madilldd0d3422014-03-26 14:01:56 -0400351 virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const;
352
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000353protected:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000354 TOperator flowOp;
355 TIntermTyped* expression; // non-zero except for "return exp;" statements
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000356};
357
358//
359// Nodes that correspond to symbols or constants in the source code.
360//
361class TIntermSymbol : public TIntermTyped {
362public:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000363 // if symbol is initialized as symbol(sym), the memory comes from the poolallocator of sym. If sym comes from
364 // per process globalpoolallocator, then it causes increased memory usage per compile
365 // it is essential to use "symbol = sym" to assign to symbol
366 TIntermSymbol(int i, const TString& sym, const TType& t) :
Zhenyao Mo3cdfcce2014-03-07 13:00:08 -0800367 TIntermTyped(t), id(i) { symbol = sym; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000368
Jamie Madill3c9eeb92013-11-04 11:09:26 -0500369 virtual bool hasSideEffects() const { return false; }
370
alokp@chromium.org58e54292010-08-24 21:40:03 +0000371 int getId() const { return id; }
372 const TString& getSymbol() const { return symbol; }
373
zmo@google.comfd747b82011-04-23 01:30:07 +0000374 void setId(int newId) { id = newId; }
zmo@google.comfd747b82011-04-23 01:30:07 +0000375
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000376 virtual void traverse(TIntermTraverser*);
377 virtual TIntermSymbol* getAsSymbolNode() { return this; }
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700378 virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000379
Jamie Madilldd0d3422014-03-26 14:01:56 -0400380 virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const {}
381
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000382protected:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000383 int id;
384 TString symbol;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000385};
386
387class TIntermConstantUnion : public TIntermTyped {
388public:
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000389 TIntermConstantUnion(ConstantUnion *unionPointer, const TType& t) : TIntermTyped(t), unionArrayPointer(unionPointer) { }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000390
Jamie Madill3c9eeb92013-11-04 11:09:26 -0500391 virtual bool hasSideEffects() const { return false; }
392
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000393 ConstantUnion* getUnionArrayPointer() const { return unionArrayPointer; }
shannon.woods%transgaming.com@gtempaccount.comc0d0c222013-04-13 03:29:36 +0000394
Nicolas Capensa621c2e2013-11-20 13:40:23 -0500395 int getIConst(size_t index) const { return unionArrayPointer ? unionArrayPointer[index].getIConst() : 0; }
396 unsigned int getUConst(size_t index) const { return unionArrayPointer ? unionArrayPointer[index].getUConst() : 0; }
397 float getFConst(size_t index) const { return unionArrayPointer ? unionArrayPointer[index].getFConst() : 0.0f; }
398 bool getBConst(size_t index) const { return unionArrayPointer ? unionArrayPointer[index].getBConst() : false; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000399
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000400 virtual TIntermConstantUnion* getAsConstantUnion() { return this; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000401 virtual void traverse(TIntermTraverser*);
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700402 virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000403
404 TIntermTyped* fold(TOperator, TIntermTyped*, TInfoSink&);
405
Jamie Madilldd0d3422014-03-26 14:01:56 -0400406 virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const {}
407
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000408protected:
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000409 ConstantUnion *unionArrayPointer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000410};
411
412//
413// Intermediate class for node types that hold operators.
414//
415class TIntermOperator : public TIntermTyped {
416public:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000417 TOperator getOp() const { return op; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000418 void setOp(TOperator o) { op = o; }
419
Jamie Madillf4b79ba2013-11-26 10:38:18 -0500420 bool isAssignment() const;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000421 bool isConstructor() const;
alokp@chromium.org58e54292010-08-24 21:40:03 +0000422
Jamie Madillf4b79ba2013-11-26 10:38:18 -0500423 virtual bool hasSideEffects() const { return isAssignment(); }
424
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000425protected:
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000426 TIntermOperator(TOperator o) : TIntermTyped(TType(EbtFloat, EbpUndefined)), op(o) {}
Jamie Madille53c98b2014-02-03 11:57:13 -0500427 TIntermOperator(TOperator o, const TType& t) : TIntermTyped(t), op(o) {}
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000428 TOperator op;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000429};
430
431//
432// Nodes for all the basic binary math operators.
433//
434class TIntermBinary : public TIntermOperator {
435public:
daniel@transgaming.com4167cc92013-01-11 04:11:53 +0000436 TIntermBinary(TOperator o) : TIntermOperator(o), addIndexClamp(false) {}
alokp@chromium.org58e54292010-08-24 21:40:03 +0000437
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000438 virtual TIntermBinary* getAsBinaryNode() { return this; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000439 virtual void traverse(TIntermTraverser*);
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700440 virtual bool replaceChildNode(
441 TIntermNode *original, TIntermNode *replacement);
alokp@chromium.org58e54292010-08-24 21:40:03 +0000442
Jamie Madillf4b79ba2013-11-26 10:38:18 -0500443 virtual bool hasSideEffects() const { return (isAssignment() || left->hasSideEffects() || right->hasSideEffects()); }
Jamie Madill3c9eeb92013-11-04 11:09:26 -0500444
alokp@chromium.org58e54292010-08-24 21:40:03 +0000445 void setLeft(TIntermTyped* n) { left = n; }
446 void setRight(TIntermTyped* n) { right = n; }
447 TIntermTyped* getLeft() const { return left; }
448 TIntermTyped* getRight() const { return right; }
449 bool promote(TInfoSink&);
450
daniel@transgaming.com4167cc92013-01-11 04:11:53 +0000451 void setAddIndexClamp() { addIndexClamp = true; }
452 bool getAddIndexClamp() { return addIndexClamp; }
453
Jamie Madilldd0d3422014-03-26 14:01:56 -0400454 virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const;
455
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000456protected:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000457 TIntermTyped* left;
458 TIntermTyped* right;
daniel@transgaming.com4167cc92013-01-11 04:11:53 +0000459
460 // If set to true, wrap any EOpIndexIndirect with a clamp to bounds.
461 bool addIndexClamp;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000462};
463
464//
465// Nodes for unary math operators.
466//
467class TIntermUnary : public TIntermOperator {
468public:
Jamie Madille53c98b2014-02-03 11:57:13 -0500469 TIntermUnary(TOperator o, const TType& t) : TIntermOperator(o, t), operand(0), useEmulatedFunction(false) {}
zmo@google.come4eb9912011-08-29 21:13:12 +0000470 TIntermUnary(TOperator o) : TIntermOperator(o), operand(0), useEmulatedFunction(false) {}
alokp@chromium.org58e54292010-08-24 21:40:03 +0000471
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000472 virtual void traverse(TIntermTraverser*);
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +0000473 virtual TIntermUnary* getAsUnaryNode() { return this; }
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700474 virtual bool replaceChildNode(
475 TIntermNode *original, TIntermNode *replacement);
alokp@chromium.org58e54292010-08-24 21:40:03 +0000476
Jamie Madillf4b79ba2013-11-26 10:38:18 -0500477 virtual bool hasSideEffects() const { return (isAssignment() || operand->hasSideEffects()); }
Jamie Madill3c9eeb92013-11-04 11:09:26 -0500478
alokp@chromium.org58e54292010-08-24 21:40:03 +0000479 void setOperand(TIntermTyped* o) { operand = o; }
480 TIntermTyped* getOperand() { return operand; }
481 bool promote(TInfoSink&);
482
zmo@google.com32e97312011-08-24 01:03:11 +0000483 void setUseEmulatedFunction() { useEmulatedFunction = true; }
484 bool getUseEmulatedFunction() { return useEmulatedFunction; }
485
Jamie Madilldd0d3422014-03-26 14:01:56 -0400486 virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const;
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
Jamie Madilldd0d3422014-03-26 14:01:56 -0400532 virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const;
533
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000534protected:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000535 TIntermAggregate(const TIntermAggregate&); // disallow copy constructor
536 TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator
537 TIntermSequence sequence;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000538 TString name;
539 bool userDefined; // used for user defined function names
alokp@chromium.orgb19403a2010-09-08 17:56:26 +0000540
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000541 bool optimize;
542 bool debug;
zmo@google.comf420c422011-09-12 18:27:59 +0000543
544 // If set to true, replace the built-in function call with an emulated one
545 // to work around driver bugs.
546 bool useEmulatedFunction;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000547};
548
549//
550// For if tests. Simplified since there is no switch statement.
551//
552class TIntermSelection : public TIntermTyped {
553public:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000554 TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB) :
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000555 TIntermTyped(TType(EbtVoid, EbpUndefined)), condition(cond), trueBlock(trueB), falseBlock(falseB) {}
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000556 TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB, const TType& type) :
557 TIntermTyped(type), condition(cond), trueBlock(trueB), falseBlock(falseB) {}
alokp@chromium.org58e54292010-08-24 21:40:03 +0000558
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000559 virtual void traverse(TIntermTraverser*);
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700560 virtual bool replaceChildNode(
561 TIntermNode *original, TIntermNode *replacement);
alokp@chromium.org58e54292010-08-24 21:40:03 +0000562
Jamie Madill3c9eeb92013-11-04 11:09:26 -0500563 // Conservatively assume selections have side-effects
564 virtual bool hasSideEffects() const { return true; }
565
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000566 bool usesTernaryOperator() const { return getBasicType() != EbtVoid; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000567 TIntermNode* getCondition() const { return condition; }
568 TIntermNode* getTrueBlock() const { return trueBlock; }
569 TIntermNode* getFalseBlock() const { return falseBlock; }
570 TIntermSelection* getAsSelectionNode() { return this; }
571
Jamie Madilldd0d3422014-03-26 14:01:56 -0400572 virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const;
573
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000574protected:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000575 TIntermTyped* condition;
576 TIntermNode* trueBlock;
577 TIntermNode* falseBlock;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000578};
579
580enum Visit
581{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000582 PreVisit,
583 InVisit,
584 PostVisit
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000585};
586
587//
588// For traversing the tree. User should derive from this,
589// put their traversal specific data in it, and then pass
590// it to a Traverse method.
591//
592// When using this, just fill in the methods for nodes you want visited.
593// Return false from a pre-visit to skip visiting that node's subtree.
594//
595class TIntermTraverser
596{
597public:
Alok Priyadarshi8156b6b2013-09-23 14:56:58 -0400598 POOL_ALLOCATOR_NEW_DELETE();
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000599 TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false, bool rightToLeft = false) :
600 preVisit(preVisit),
601 inVisit(inVisit),
602 postVisit(postVisit),
603 rightToLeft(rightToLeft),
Jamie Madilleb1a0102013-07-08 13:31:38 -0400604 depth(0),
605 maxDepth(0) {}
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700606 virtual ~TIntermTraverser() {}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000607
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000608 virtual void visitSymbol(TIntermSymbol*) {}
609 virtual void visitConstantUnion(TIntermConstantUnion*) {}
610 virtual bool visitBinary(Visit visit, TIntermBinary*) {return true;}
611 virtual bool visitUnary(Visit visit, TIntermUnary*) {return true;}
612 virtual bool visitSelection(Visit visit, TIntermSelection*) {return true;}
613 virtual bool visitAggregate(Visit visit, TIntermAggregate*) {return true;}
614 virtual bool visitLoop(Visit visit, TIntermLoop*) {return true;}
615 virtual bool visitBranch(Visit visit, TIntermBranch*) {return true;}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000616
Jamie Madilleb1a0102013-07-08 13:31:38 -0400617 int getMaxDepth() const {return maxDepth;}
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700618
619 void incrementDepth(TIntermNode *current)
620 {
621 depth++;
622 maxDepth = std::max(maxDepth, depth);
623 path.push_back(current);
624 }
625
626 void decrementDepth()
627 {
628 depth--;
629 path.pop_back();
630 }
631
632 TIntermNode *getParentNode()
633 {
634 return path.size() == 0 ? NULL : path.back();
635 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000636
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +0000637 // Return the original name if hash function pointer is NULL;
638 // otherwise return the hashed name.
639 static TString hash(const TString& name, ShHashFunction64 hashFunction);
640
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000641 const bool preVisit;
642 const bool inVisit;
643 const bool postVisit;
644 const bool rightToLeft;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000645
646protected:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000647 int depth;
Jamie Madilleb1a0102013-07-08 13:31:38 -0400648 int maxDepth;
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700649
650 // All the nodes from root to the current node's parent during traversing.
651 TVector<TIntermNode *> path;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000652};
653
Jamie Madill6654bc92014-03-26 14:01:57 -0400654//
655// For traversing the tree, and computing max depth.
656// Takes a maximum depth limit to prevent stack overflow.
657//
658class TMaxDepthTraverser : public TIntermTraverser
659{
660public:
661 POOL_ALLOCATOR_NEW_DELETE();
662 TMaxDepthTraverser(int depthLimit)
663 : TIntermTraverser(true, true, false, false),
664 depthLimit(depthLimit)
665 {}
666
667 virtual bool visitBinary(Visit visit, TIntermBinary*) { return depthCheck(); }
668 virtual bool visitUnary(Visit visit, TIntermUnary*) { return depthCheck(); }
669 virtual bool visitSelection(Visit visit, TIntermSelection*) { return depthCheck(); }
670 virtual bool visitAggregate(Visit visit, TIntermAggregate*) { return depthCheck(); }
671 virtual bool visitLoop(Visit visit, TIntermLoop*) { return depthCheck(); }
672 virtual bool visitBranch(Visit visit, TIntermBranch*) { return depthCheck(); }
673
674protected:
675 int depthLimit;
676
677 bool depthCheck() const { return maxDepth < depthLimit; }
678};
679
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000680#endif // __INTERMEDIATE_H