blob: 892f2849e04f76d6e362b6dbe93edba4934b998d [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//
Zhenyao Moe40d1e92014-07-16 17:40:36 -070011// Nodes in the tree are defined as a hierarchy of classes derived from
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000012// 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
Zhenyao Moe40d1e92014-07-16 17:40:36 -070016#ifndef COMPILER_TRANSLATOR_INTERMEDIATE_H_
17#define COMPILER_TRANSLATOR_INTERMEDIATE_H_
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000018
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>
Zhenyao Moe40d1e92014-07-16 17:40:36 -070023
Geoff Lang17732822013-08-29 13:46:49 -040024#include "compiler/translator/Common.h"
25#include "compiler/translator/Types.h"
26#include "compiler/translator/ConstantUnion.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000027
28//
29// Operators used by the high-level (parse tree) representation.
30//
Zhenyao Moe40d1e92014-07-16 17:40:36 -070031enum TOperator
32{
alokp@chromium.org2cf17712010-03-30 20:33:18 +000033 EOpNull, // if in a node, should only mean a node is still being built
34 EOpSequence, // denotes a list of statements, or parameters, etc.
Zhenyao Moe40d1e92014-07-16 17:40:36 -070035 EOpFunctionCall,
alokp@chromium.org2cf17712010-03-30 20:33:18 +000036 EOpFunction, // For function definition
37 EOpParameters, // an aggregate listing the parameters to a function
daniel@transgaming.comd1acd1e2010-04-13 03:25:57 +000038
alokp@chromium.org2cf17712010-03-30 20:33:18 +000039 EOpDeclaration,
daniel@transgaming.comd1acd1e2010-04-13 03:25:57 +000040 EOpPrototype,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000041
alokp@chromium.org2cf17712010-03-30 20:33:18 +000042 //
43 // Unary operators
44 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000045
alokp@chromium.org2cf17712010-03-30 20:33:18 +000046 EOpNegative,
47 EOpLogicalNot,
48 EOpVectorLogicalNot,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000049
alokp@chromium.org2cf17712010-03-30 20:33:18 +000050 EOpPostIncrement,
51 EOpPostDecrement,
52 EOpPreIncrement,
53 EOpPreDecrement,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000054
alokp@chromium.org2cf17712010-03-30 20:33:18 +000055 //
56 // binary operations
57 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000058
alokp@chromium.org2cf17712010-03-30 20:33:18 +000059 EOpAdd,
60 EOpSub,
61 EOpMul,
62 EOpDiv,
63 EOpEqual,
64 EOpNotEqual,
65 EOpVectorEqual,
66 EOpVectorNotEqual,
67 EOpLessThan,
68 EOpGreaterThan,
69 EOpLessThanEqual,
70 EOpGreaterThanEqual,
71 EOpComma,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000072
alokp@chromium.org2cf17712010-03-30 20:33:18 +000073 EOpVectorTimesScalar,
74 EOpVectorTimesMatrix,
75 EOpMatrixTimesVector,
76 EOpMatrixTimesScalar,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000077
alokp@chromium.org2cf17712010-03-30 20:33:18 +000078 EOpLogicalOr,
79 EOpLogicalXor,
80 EOpLogicalAnd,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000081
alokp@chromium.org2cf17712010-03-30 20:33:18 +000082 EOpIndexDirect,
83 EOpIndexIndirect,
84 EOpIndexDirectStruct,
shannonwoods@chromium.org5668c5d2013-05-30 00:11:48 +000085 EOpIndexDirectInterfaceBlock,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000086
alokp@chromium.org2cf17712010-03-30 20:33:18 +000087 EOpVectorSwizzle,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000088
alokp@chromium.org2cf17712010-03-30 20:33:18 +000089 //
90 // Built-in functions potentially mapped to operators
91 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000092
alokp@chromium.org2cf17712010-03-30 20:33:18 +000093 EOpRadians,
94 EOpDegrees,
95 EOpSin,
96 EOpCos,
97 EOpTan,
98 EOpAsin,
99 EOpAcos,
100 EOpAtan,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000101
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000102 EOpPow,
103 EOpExp,
104 EOpLog,
105 EOpExp2,
106 EOpLog2,
107 EOpSqrt,
108 EOpInverseSqrt,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000109
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000110 EOpAbs,
111 EOpSign,
112 EOpFloor,
113 EOpCeil,
114 EOpFract,
115 EOpMod,
116 EOpMin,
117 EOpMax,
118 EOpClamp,
119 EOpMix,
120 EOpStep,
121 EOpSmoothStep,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000122
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000123 EOpLength,
124 EOpDistance,
125 EOpDot,
126 EOpCross,
127 EOpNormalize,
128 EOpFaceForward,
129 EOpReflect,
130 EOpRefract,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000131
alokp@chromium.org06098892010-08-26 19:36:42 +0000132 EOpDFdx, // Fragment only, OES_standard_derivatives extension
133 EOpDFdy, // Fragment only, OES_standard_derivatives extension
134 EOpFwidth, // Fragment only, OES_standard_derivatives extension
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000135
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000136 EOpMatrixTimesMatrix,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000137
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000138 EOpAny,
139 EOpAll,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000140
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000141 //
142 // Branch
143 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000144
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000145 EOpKill, // Fragment only
146 EOpReturn,
147 EOpBreak,
148 EOpContinue,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000149
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000150 //
151 // Constructors
152 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000153
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000154 EOpConstructInt,
Nicolas Capensab60b932013-06-05 10:31:21 -0400155 EOpConstructUInt,
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000156 EOpConstructBool,
157 EOpConstructFloat,
158 EOpConstructVec2,
159 EOpConstructVec3,
160 EOpConstructVec4,
161 EOpConstructBVec2,
162 EOpConstructBVec3,
163 EOpConstructBVec4,
164 EOpConstructIVec2,
165 EOpConstructIVec3,
166 EOpConstructIVec4,
shannonwoods@chromium.org8c788e82013-05-30 00:20:21 +0000167 EOpConstructUVec2,
168 EOpConstructUVec3,
169 EOpConstructUVec4,
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000170 EOpConstructMat2,
171 EOpConstructMat3,
172 EOpConstructMat4,
173 EOpConstructStruct,
174
175 //
176 // moves
177 //
178
179 EOpAssign,
180 EOpInitialize,
181 EOpAddAssign,
182 EOpSubAssign,
183 EOpMulAssign,
184 EOpVectorTimesMatrixAssign,
185 EOpVectorTimesScalarAssign,
186 EOpMatrixTimesScalarAssign,
187 EOpMatrixTimesMatrixAssign,
daniel@transgaming.comb3077d02013-01-11 04:12:09 +0000188 EOpDivAssign
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000189};
190
191class 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;
Jamie Madill4cfb1e82014-07-07 12:49:23 -0400201class TIntermRaw;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000202
203//
204// Base class for the tree nodes
205//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700206class TIntermNode
207{
208 public:
Alok Priyadarshi8156b6b2013-09-23 14:56:58 -0400209 POOL_ALLOCATOR_NEW_DELETE();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700210 TIntermNode()
211 {
Jamie Madill075edd82013-07-08 13:30:19 -0400212 // TODO: Move this to TSourceLoc constructor
213 // after getting rid of TPublicType.
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700214 mLine.first_file = mLine.last_file = 0;
215 mLine.first_line = mLine.last_line = 0;
Jamie Madill075edd82013-07-08 13:30:19 -0400216 }
217 virtual ~TIntermNode() { }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000218
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700219 const TSourceLoc &getLine() const { return mLine; }
220 void setLine(const TSourceLoc &l) { mLine = l; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000221
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700222 virtual void traverse(TIntermTraverser *) = 0;
223 virtual TIntermTyped *getAsTyped() { return 0; }
224 virtual TIntermConstantUnion *getAsConstantUnion() { return 0; }
225 virtual TIntermAggregate *getAsAggregate() { return 0; }
226 virtual TIntermBinary *getAsBinaryNode() { return 0; }
227 virtual TIntermUnary *getAsUnaryNode() { return 0; }
228 virtual TIntermSelection *getAsSelectionNode() { return 0; }
229 virtual TIntermSymbol *getAsSymbolNode() { return 0; }
230 virtual TIntermLoop *getAsLoopNode() { return 0; }
231 virtual TIntermRaw *getAsRawNode() { return 0; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000232
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700233 // Replace a child node. Return true if |original| is a child
234 // node and it is replaced; otherwise, return false.
235 virtual bool replaceChildNode(
236 TIntermNode *original, TIntermNode *replacement) = 0;
237
Jamie Madilldd0d3422014-03-26 14:01:56 -0400238 // For traversing a tree in no particular order, but using
239 // heap memory.
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700240 virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const = 0;
Jamie Madilldd0d3422014-03-26 14:01:56 -0400241
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700242 protected:
243 TSourceLoc mLine;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000244};
245
246//
247// This is just to help yacc.
248//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700249struct TIntermNodePair
250{
251 TIntermNode *node1;
252 TIntermNode *node2;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000253};
254
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000255//
256// Intermediate class for nodes that have a type.
257//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700258class TIntermTyped : public TIntermNode
259{
260 public:
261 TIntermTyped(const TType &t) : mType(t) { }
262 virtual TIntermTyped *getAsTyped() { return this; }
alokp@chromium.orgdd037b22010-03-30 18:47:20 +0000263
Jamie Madill3c9eeb92013-11-04 11:09:26 -0500264 virtual bool hasSideEffects() const = 0;
265
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700266 void setType(const TType &t) { mType = t; }
267 const TType &getType() const { return mType; }
268 TType *getTypePointer() { return &mType; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000269
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700270 TBasicType getBasicType() const { return mType.getBasicType(); }
271 TQualifier getQualifier() const { return mType.getQualifier(); }
272 TPrecision getPrecision() const { return mType.getPrecision(); }
273 int getCols() const { return mType.getCols(); }
274 int getRows() const { return mType.getRows(); }
275 int getNominalSize() const { return mType.getNominalSize(); }
276 int getSecondarySize() const { return mType.getSecondarySize(); }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000277
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700278 bool isInterfaceBlock() const { return mType.isInterfaceBlock(); }
279 bool isMatrix() const { return mType.isMatrix(); }
280 bool isArray() const { return mType.isArray(); }
281 bool isVector() const { return mType.isVector(); }
282 bool isScalar() const { return mType.isScalar(); }
283 bool isScalarInt() const { return mType.isScalarInt(); }
284 const char *getBasicString() const { return mType.getBasicString(); }
285 const char *getQualifierString() const { return mType.getQualifierString(); }
286 TString getCompleteString() const { return mType.getCompleteString(); }
daniel@transgaming.com3ca980a2012-12-20 21:11:52 +0000287
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700288 int getArraySize() const { return mType.getArraySize(); }
289
290 protected:
291 TType mType;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000292};
293
294//
295// Handle for, do-while, and while loops.
296//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700297enum TLoopType
298{
alokp@chromium.org52813552010-11-16 18:36:09 +0000299 ELoopFor,
300 ELoopWhile,
daniel@transgaming.comb3077d02013-01-11 04:12:09 +0000301 ELoopDoWhile
alokp@chromium.org52813552010-11-16 18:36:09 +0000302};
303
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700304class TIntermLoop : public TIntermNode
305{
306 public:
307 TIntermLoop(TLoopType type,
308 TIntermNode *init, TIntermTyped *cond, TIntermTyped *expr,
309 TIntermNode *body)
310 : mType(type),
311 mInit(init),
312 mCond(cond),
313 mExpr(expr),
314 mBody(body),
315 mUnrollFlag(false) { }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000316
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700317 virtual TIntermLoop *getAsLoopNode() { return this; }
318 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
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700322 TLoopType getType() const { return mType; }
323 TIntermNode *getInit() { return mInit; }
324 TIntermTyped *getCondition() { return mCond; }
325 TIntermTyped *getExpression() { return mExpr; }
326 TIntermNode *getBody() { return mBody; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000327
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700328 void setUnrollFlag(bool flag) { mUnrollFlag = flag; }
329 bool getUnrollFlag() const { return mUnrollFlag; }
zmo@google.com0b8d4eb2011-04-04 19:17:11 +0000330
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700331 virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const;
Jamie Madilldd0d3422014-03-26 14:01:56 -0400332
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700333 protected:
334 TLoopType mType;
335 TIntermNode *mInit; // for-loop initialization
336 TIntermTyped *mCond; // loop exit condition
337 TIntermTyped *mExpr; // for-loop expression
338 TIntermNode *mBody; // loop body
zmo@google.com0b8d4eb2011-04-04 19:17:11 +0000339
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700340 bool mUnrollFlag; // Whether the loop should be unrolled or not.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000341};
342
343//
344// Handle break, continue, return, and kill.
345//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700346class TIntermBranch : public TIntermNode
347{
348 public:
349 TIntermBranch(TOperator op, TIntermTyped *e)
350 : mFlowOp(op),
351 mExpression(e) { }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000352
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700353 virtual void traverse(TIntermTraverser *);
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700354 virtual bool replaceChildNode(
355 TIntermNode *original, TIntermNode *replacement);
alokp@chromium.org58e54292010-08-24 21:40:03 +0000356
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700357 TOperator getFlowOp() { return mFlowOp; }
358 TIntermTyped* getExpression() { return mExpression; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000359
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700360 virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const;
Jamie Madilldd0d3422014-03-26 14:01:56 -0400361
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000362protected:
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700363 TOperator mFlowOp;
364 TIntermTyped *mExpression; // non-zero except for "return exp;" statements
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000365};
366
367//
368// Nodes that correspond to symbols or constants in the source code.
369//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700370class TIntermSymbol : public TIntermTyped
371{
372 public:
373 // if symbol is initialized as symbol(sym), the memory comes from the poolallocator of sym.
374 // If sym comes from per process globalpoolallocator, then it causes increased memory usage
375 // per compile it is essential to use "symbol = sym" to assign to symbol
376 TIntermSymbol(int id, const TString &symbol, const TType &type)
377 : TIntermTyped(type),
378 mId(id)
379 {
380 mSymbol = symbol;
381 }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000382
Jamie Madill3c9eeb92013-11-04 11:09:26 -0500383 virtual bool hasSideEffects() const { return false; }
384
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700385 int getId() const { return mId; }
386 const TString &getSymbol() const { return mSymbol; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000387
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700388 void setId(int newId) { mId = newId; }
zmo@google.comfd747b82011-04-23 01:30:07 +0000389
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700390 virtual void traverse(TIntermTraverser *);
391 virtual TIntermSymbol *getAsSymbolNode() { return this; }
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700392 virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000393
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700394 virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const {}
Jamie Madilldd0d3422014-03-26 14:01:56 -0400395
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700396 protected:
397 int mId;
398 TString mSymbol;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000399};
400
Jamie Madill4cfb1e82014-07-07 12:49:23 -0400401// A Raw node stores raw code, that the translator will insert verbatim
402// into the output stream. Useful for transformation operations that make
403// complex code that might not fit naturally into the GLSL model.
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700404class TIntermRaw : public TIntermTyped
405{
406 public:
407 TIntermRaw(const TType &type, const TString &rawText)
408 : TIntermTyped(type),
409 mRawText(rawText) { }
Jamie Madill4cfb1e82014-07-07 12:49:23 -0400410
411 virtual bool hasSideEffects() const { return false; }
412
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700413 TString getRawText() const { return mRawText; }
Jamie Madill4cfb1e82014-07-07 12:49:23 -0400414
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700415 virtual void traverse(TIntermTraverser *);
Jamie Madill4cfb1e82014-07-07 12:49:23 -0400416
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700417 virtual TIntermRaw *getAsRawNode() { return this; }
Jamie Madill4cfb1e82014-07-07 12:49:23 -0400418 virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; }
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700419 virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const {}
Jamie Madill4cfb1e82014-07-07 12:49:23 -0400420
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700421 protected:
422 TString mRawText;
Jamie Madill4cfb1e82014-07-07 12:49:23 -0400423};
424
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700425class TIntermConstantUnion : public TIntermTyped
426{
427 public:
428 TIntermConstantUnion(ConstantUnion *unionPointer, const TType &type)
429 : TIntermTyped(type),
430 mUnionArrayPointer(unionPointer) { }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000431
Jamie Madill3c9eeb92013-11-04 11:09:26 -0500432 virtual bool hasSideEffects() const { return false; }
433
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700434 ConstantUnion *getUnionArrayPointer() const { return mUnionArrayPointer; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000435
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700436 int getIConst(size_t index) const
437 {
438 return mUnionArrayPointer ? mUnionArrayPointer[index].getIConst() : 0;
439 }
440 unsigned int getUConst(size_t index) const
441 {
442 return mUnionArrayPointer ? mUnionArrayPointer[index].getUConst() : 0;
443 }
444 float getFConst(size_t index) const
445 {
446 return mUnionArrayPointer ? mUnionArrayPointer[index].getFConst() : 0.0f;
447 }
448 bool getBConst(size_t index) const
449 {
450 return mUnionArrayPointer ? mUnionArrayPointer[index].getBConst() : false;
451 }
452
453 virtual TIntermConstantUnion *getAsConstantUnion() { return this; }
454 virtual void traverse(TIntermTraverser *);
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700455 virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000456
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700457 TIntermTyped *fold(TOperator, TIntermTyped *, TInfoSink &);
alokp@chromium.org58e54292010-08-24 21:40:03 +0000458
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700459 virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const {}
Jamie Madilldd0d3422014-03-26 14:01:56 -0400460
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700461 protected:
462 ConstantUnion *mUnionArrayPointer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000463};
464
465//
466// Intermediate class for node types that hold operators.
467//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700468class TIntermOperator : public TIntermTyped
469{
470 public:
471 TOperator getOp() const { return mOp; }
472 void setOp(TOperator op) { mOp = op; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000473
Jamie Madillf4b79ba2013-11-26 10:38:18 -0500474 bool isAssignment() const;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000475 bool isConstructor() const;
alokp@chromium.org58e54292010-08-24 21:40:03 +0000476
Jamie Madillf4b79ba2013-11-26 10:38:18 -0500477 virtual bool hasSideEffects() const { return isAssignment(); }
478
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700479 protected:
480 TIntermOperator(TOperator op)
481 : TIntermTyped(TType(EbtFloat, EbpUndefined)),
482 mOp(op) {}
483 TIntermOperator(TOperator op, const TType &type)
484 : TIntermTyped(type),
485 mOp(op) {}
486
487 TOperator mOp;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000488};
489
490//
491// Nodes for all the basic binary math operators.
492//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700493class TIntermBinary : public TIntermOperator
494{
495 public:
496 TIntermBinary(TOperator op)
497 : TIntermOperator(op),
498 mAddIndexClamp(false) {}
alokp@chromium.org58e54292010-08-24 21:40:03 +0000499
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700500 virtual TIntermBinary *getAsBinaryNode() { return this; }
501 virtual void traverse(TIntermTraverser *);
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700502 virtual bool replaceChildNode(
503 TIntermNode *original, TIntermNode *replacement);
alokp@chromium.org58e54292010-08-24 21:40:03 +0000504
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700505 virtual bool hasSideEffects() const
506 {
507 return isAssignment() || mLeft->hasSideEffects() || mRight->hasSideEffects();
508 }
Jamie Madill3c9eeb92013-11-04 11:09:26 -0500509
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700510 void setLeft(TIntermTyped *node) { mLeft = node; }
511 void setRight(TIntermTyped *node) { mRight = node; }
512 TIntermTyped *getLeft() const { return mLeft; }
513 TIntermTyped *getRight() const { return mRight; }
514 bool promote(TInfoSink &);
alokp@chromium.org58e54292010-08-24 21:40:03 +0000515
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700516 void setAddIndexClamp() { mAddIndexClamp = true; }
517 bool getAddIndexClamp() { return mAddIndexClamp; }
daniel@transgaming.com4167cc92013-01-11 04:11:53 +0000518
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700519 virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const;
Jamie Madilldd0d3422014-03-26 14:01:56 -0400520
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700521 protected:
522 TIntermTyped* mLeft;
523 TIntermTyped* mRight;
daniel@transgaming.com4167cc92013-01-11 04:11:53 +0000524
525 // If set to true, wrap any EOpIndexIndirect with a clamp to bounds.
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700526 bool mAddIndexClamp;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000527};
528
529//
530// Nodes for unary math operators.
531//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700532class TIntermUnary : public TIntermOperator
533{
534 public:
535 TIntermUnary(TOperator op, const TType &type)
536 : TIntermOperator(op, type),
537 mOperand(NULL),
538 mUseEmulatedFunction(false) {}
539 TIntermUnary(TOperator op)
540 : TIntermOperator(op),
541 mOperand(NULL),
542 mUseEmulatedFunction(false) {}
alokp@chromium.org58e54292010-08-24 21:40:03 +0000543
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700544 virtual void traverse(TIntermTraverser *);
545 virtual TIntermUnary *getAsUnaryNode() { return this; }
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700546 virtual bool replaceChildNode(
547 TIntermNode *original, TIntermNode *replacement);
alokp@chromium.org58e54292010-08-24 21:40:03 +0000548
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700549 virtual bool hasSideEffects() const
550 {
551 return isAssignment() || mOperand->hasSideEffects();
552 }
Jamie Madill3c9eeb92013-11-04 11:09:26 -0500553
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700554 void setOperand(TIntermTyped *operand) { mOperand = operand; }
555 TIntermTyped *getOperand() { return mOperand; }
556 bool promote(TInfoSink &);
alokp@chromium.org58e54292010-08-24 21:40:03 +0000557
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700558 void setUseEmulatedFunction() { mUseEmulatedFunction = true; }
559 bool getUseEmulatedFunction() { return mUseEmulatedFunction; }
zmo@google.com32e97312011-08-24 01:03:11 +0000560
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700561 virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const;
Jamie Madilldd0d3422014-03-26 14:01:56 -0400562
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700563 protected:
564 TIntermTyped *mOperand;
zmo@google.comf420c422011-09-12 18:27:59 +0000565
566 // If set to true, replace the built-in function call with an emulated one
567 // to work around driver bugs.
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700568 bool mUseEmulatedFunction;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000569};
570
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700571typedef TVector<TIntermNode *> TIntermSequence;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000572typedef TVector<int> TQualifierList;
alokp@chromium.org8b851c62012-06-15 16:25:11 +0000573
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000574//
575// Nodes that operate on an arbitrary sized set of children.
576//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700577class TIntermAggregate : public TIntermOperator
578{
579 public:
580 TIntermAggregate()
581 : TIntermOperator(EOpNull),
582 mUserDefined(false),
583 mUseEmulatedFunction(false) { }
584 TIntermAggregate(TOperator op)
585 : TIntermOperator(op),
586 mUseEmulatedFunction(false) { }
alokp@chromium.org8b851c62012-06-15 16:25:11 +0000587 ~TIntermAggregate() { }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000588
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700589 virtual TIntermAggregate *getAsAggregate() { return this; }
590 virtual void traverse(TIntermTraverser *);
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700591 virtual bool replaceChildNode(
592 TIntermNode *original, TIntermNode *replacement);
alokp@chromium.org58e54292010-08-24 21:40:03 +0000593
Jamie Madill3c9eeb92013-11-04 11:09:26 -0500594 // Conservatively assume function calls and other aggregate operators have side-effects
595 virtual bool hasSideEffects() const { return true; }
596
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700597 TIntermSequence *getSequence() { return &mSequence; }
alokp@chromium.orgb19403a2010-09-08 17:56:26 +0000598
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700599 void setName(const TString &name) { mName = name; }
600 const TString &getName() const { return mName; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000601
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700602 void setUserDefined() { mUserDefined = true; }
603 bool isUserDefined() const { return mUserDefined; }
alokp@chromium.orgb19403a2010-09-08 17:56:26 +0000604
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700605 void setOptimize(bool optimize) { mOptimize = optimize; }
606 bool getOptimize() const { return mOptimize; }
607 void setDebug(bool debug) { mDebug = debug; }
608 bool getDebug() const { return mDebug; }
alokp@chromium.org8b851c62012-06-15 16:25:11 +0000609
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700610 void setUseEmulatedFunction() { mUseEmulatedFunction = true; }
611 bool getUseEmulatedFunction() { return mUseEmulatedFunction; }
zmo@google.comf420c422011-09-12 18:27:59 +0000612
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700613 virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const;
Jamie Madilldd0d3422014-03-26 14:01:56 -0400614
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700615 protected:
616 TIntermAggregate(const TIntermAggregate &); // disallow copy constructor
617 TIntermAggregate &operator=(const TIntermAggregate &); // disallow assignment operator
618 TIntermSequence mSequence;
619 TString mName;
620 bool mUserDefined; // used for user defined function names
alokp@chromium.orgb19403a2010-09-08 17:56:26 +0000621
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700622 bool mOptimize;
623 bool mDebug;
zmo@google.comf420c422011-09-12 18:27:59 +0000624
625 // If set to true, replace the built-in function call with an emulated one
626 // to work around driver bugs.
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700627 bool mUseEmulatedFunction;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000628};
629
630//
631// For if tests. Simplified since there is no switch statement.
632//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700633class TIntermSelection : public TIntermTyped
634{
635 public:
636 TIntermSelection(TIntermTyped *cond, TIntermNode *trueB, TIntermNode *falseB)
637 : TIntermTyped(TType(EbtVoid, EbpUndefined)),
638 mCondition(cond),
639 mTrueBlock(trueB),
640 mFalseBlock(falseB) {}
641 TIntermSelection(TIntermTyped *cond, TIntermNode *trueB, TIntermNode *falseB,
642 const TType &type)
643 : TIntermTyped(type),
644 mCondition(cond),
645 mTrueBlock(trueB),
646 mFalseBlock(falseB) {}
alokp@chromium.org58e54292010-08-24 21:40:03 +0000647
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700648 virtual void traverse(TIntermTraverser *);
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700649 virtual bool replaceChildNode(
650 TIntermNode *original, TIntermNode *replacement);
alokp@chromium.org58e54292010-08-24 21:40:03 +0000651
Jamie Madill3c9eeb92013-11-04 11:09:26 -0500652 // Conservatively assume selections have side-effects
653 virtual bool hasSideEffects() const { return true; }
654
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000655 bool usesTernaryOperator() const { return getBasicType() != EbtVoid; }
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700656 TIntermNode *getCondition() const { return mCondition; }
657 TIntermNode *getTrueBlock() const { return mTrueBlock; }
658 TIntermNode *getFalseBlock() const { return mFalseBlock; }
659 TIntermSelection *getAsSelectionNode() { return this; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000660
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700661 virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const;
Jamie Madilldd0d3422014-03-26 14:01:56 -0400662
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000663protected:
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700664 TIntermTyped *mCondition;
665 TIntermNode *mTrueBlock;
666 TIntermNode *mFalseBlock;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000667};
668
669enum Visit
670{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000671 PreVisit,
672 InVisit,
673 PostVisit
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000674};
675
676//
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700677// For traversing the tree. User should derive from this,
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000678// put their traversal specific data in it, and then pass
679// it to a Traverse method.
680//
681// When using this, just fill in the methods for nodes you want visited.
682// Return false from a pre-visit to skip visiting that node's subtree.
683//
684class TIntermTraverser
685{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700686 public:
Alok Priyadarshi8156b6b2013-09-23 14:56:58 -0400687 POOL_ALLOCATOR_NEW_DELETE();
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700688 // TODO(zmo): remove default values.
689 TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false,
690 bool rightToLeft = false)
691 : preVisit(preVisit),
692 inVisit(inVisit),
693 postVisit(postVisit),
694 rightToLeft(rightToLeft),
695 mDepth(0),
696 mMaxDepth(0) {}
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700697 virtual ~TIntermTraverser() {}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000698
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700699 virtual void visitSymbol(TIntermSymbol *) {}
700 virtual void visitRaw(TIntermRaw *) {}
701 virtual void visitConstantUnion(TIntermConstantUnion *) {}
702 virtual bool visitBinary(Visit, TIntermBinary *) { return true; }
703 virtual bool visitUnary(Visit, TIntermUnary *) { return true; }
704 virtual bool visitSelection(Visit, TIntermSelection *) { return true; }
705 virtual bool visitAggregate(Visit, TIntermAggregate *) { return true; }
706 virtual bool visitLoop(Visit, TIntermLoop *) { return true; }
707 virtual bool visitBranch(Visit, TIntermBranch *) { return true; }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000708
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700709 int getMaxDepth() const { return mMaxDepth; }
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700710
711 void incrementDepth(TIntermNode *current)
712 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700713 mDepth++;
714 mMaxDepth = std::max(mMaxDepth, mDepth);
715 mPath.push_back(current);
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700716 }
717
718 void decrementDepth()
719 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700720 mDepth--;
721 mPath.pop_back();
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700722 }
723
724 TIntermNode *getParentNode()
725 {
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700726 return mPath.size() == 0 ? NULL : mPath.back();
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700727 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000728
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +0000729 // Return the original name if hash function pointer is NULL;
730 // otherwise return the hashed name.
731 static TString hash(const TString& name, ShHashFunction64 hashFunction);
732
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000733 const bool preVisit;
734 const bool inVisit;
735 const bool postVisit;
736 const bool rightToLeft;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000737
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700738 protected:
739 int mDepth;
740 int mMaxDepth;
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700741
742 // All the nodes from root to the current node's parent during traversing.
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700743 TVector<TIntermNode *> mPath;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000744};
745
Jamie Madill6654bc92014-03-26 14:01:57 -0400746//
747// For traversing the tree, and computing max depth.
748// Takes a maximum depth limit to prevent stack overflow.
749//
750class TMaxDepthTraverser : public TIntermTraverser
751{
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700752 public:
Jamie Madill6654bc92014-03-26 14:01:57 -0400753 POOL_ALLOCATOR_NEW_DELETE();
754 TMaxDepthTraverser(int depthLimit)
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700755 : TIntermTraverser(true, true, false, false),
756 mDepthLimit(depthLimit) { }
Jamie Madill6654bc92014-03-26 14:01:57 -0400757
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700758 virtual bool visitBinary(Visit, TIntermBinary *) { return depthCheck(); }
759 virtual bool visitUnary(Visit, TIntermUnary *) { return depthCheck(); }
760 virtual bool visitSelection(Visit, TIntermSelection *) { return depthCheck(); }
761 virtual bool visitAggregate(Visit, TIntermAggregate *) { return depthCheck(); }
762 virtual bool visitLoop(Visit, TIntermLoop *) { return depthCheck(); }
763 virtual bool visitBranch(Visit, TIntermBranch *) { return depthCheck(); }
Jamie Madill6654bc92014-03-26 14:01:57 -0400764
765protected:
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700766 bool depthCheck() const { return mMaxDepth < mDepthLimit; }
Jamie Madill6654bc92014-03-26 14:01:57 -0400767
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700768 int mDepthLimit;
Jamie Madill6654bc92014-03-26 14:01:57 -0400769};
770
Zhenyao Moe40d1e92014-07-16 17:40:36 -0700771#endif // COMPILER_TRANSLATOR_INTERMEDIATE_H_