blob: 9cd26e852782e3c3dac74a686500c3505fcdf6c5 [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;
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//
206class TIntermNode {
207public:
Alok Priyadarshi8156b6b2013-09-23 14:56:58 -0400208 POOL_ALLOCATOR_NEW_DELETE();
Jamie Madill075edd82013-07-08 13:30:19 -0400209 TIntermNode() {
210 // TODO: Move this to TSourceLoc constructor
211 // after getting rid of TPublicType.
212 line.first_file = line.last_file = 0;
213 line.first_line = line.last_line = 0;
214 }
215 virtual ~TIntermNode() { }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000216
Jamie Madill075edd82013-07-08 13:30:19 -0400217 const TSourceLoc& getLine() const { return line; }
218 void setLine(const TSourceLoc& l) { line = l; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000219
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000220 virtual void traverse(TIntermTraverser*) = 0;
alokp@chromium.orgd88b7732010-05-26 15:13:14 +0000221 virtual TIntermTyped* getAsTyped() { return 0; }
222 virtual TIntermConstantUnion* getAsConstantUnion() { return 0; }
223 virtual TIntermAggregate* getAsAggregate() { return 0; }
224 virtual TIntermBinary* getAsBinaryNode() { return 0; }
225 virtual TIntermUnary* getAsUnaryNode() { return 0; }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000226 virtual TIntermSelection* getAsSelectionNode() { return 0; }
alokp@chromium.orgd88b7732010-05-26 15:13:14 +0000227 virtual TIntermSymbol* getAsSymbolNode() { return 0; }
228 virtual TIntermLoop* getAsLoopNode() { return 0; }
Jamie Madill4cfb1e82014-07-07 12:49:23 -0400229 virtual TIntermRaw* getAsRawNode() { return 0; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000230
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700231 // Replace a child node. Return true if |original| is a child
232 // node and it is replaced; otherwise, return false.
233 virtual bool replaceChildNode(
234 TIntermNode *original, TIntermNode *replacement) = 0;
235
Jamie Madilldd0d3422014-03-26 14:01:56 -0400236 // For traversing a tree in no particular order, but using
237 // heap memory.
238 virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const = 0;
239
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000240protected:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000241 TSourceLoc line;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000242};
243
244//
245// This is just to help yacc.
246//
247struct TIntermNodePair {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000248 TIntermNode* node1;
249 TIntermNode* node2;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000250};
251
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000252//
253// Intermediate class for nodes that have a type.
254//
255class TIntermTyped : public TIntermNode {
256public:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000257 TIntermTyped(const TType& t) : type(t) { }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000258 virtual TIntermTyped* getAsTyped() { return this; }
alokp@chromium.orgdd037b22010-03-30 18:47:20 +0000259
Jamie Madill3c9eeb92013-11-04 11:09:26 -0500260 virtual bool hasSideEffects() const = 0;
261
alokp@chromium.org58e54292010-08-24 21:40:03 +0000262 void setType(const TType& t) { type = t; }
263 const TType& getType() const { return type; }
264 TType* getTypePointer() { return &type; }
265
266 TBasicType getBasicType() const { return type.getBasicType(); }
267 TQualifier getQualifier() const { return type.getQualifier(); }
268 TPrecision getPrecision() const { return type.getPrecision(); }
Shannon Woods3841b8e2013-09-10 18:23:12 -0400269 int getCols() const { return type.getCols(); }
270 int getRows() const { return type.getRows(); }
271 int getNominalSize() const { return type.getNominalSize(); }
272 int getSecondarySize() const { return type.getSecondarySize(); }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000273
Jamie Madill98493dd2013-07-08 14:39:03 -0400274 bool isInterfaceBlock() const { return type.isInterfaceBlock(); }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000275 bool isMatrix() const { return type.isMatrix(); }
276 bool isArray() const { return type.isArray(); }
277 bool isVector() const { return type.isVector(); }
278 bool isScalar() const { return type.isScalar(); }
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000279 bool isScalarInt() const { return type.isScalarInt(); }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000280 const char* getBasicString() const { return type.getBasicString(); }
281 const char* getQualifierString() const { return type.getQualifierString(); }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000282 TString getCompleteString() const { return type.getCompleteString(); }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000283
daniel@transgaming.com3ca980a2012-12-20 21:11:52 +0000284 int getArraySize() const { return type.getArraySize(); }
285
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000286protected:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000287 TType type;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000288};
289
290//
291// Handle for, do-while, and while loops.
292//
alokp@chromium.org52813552010-11-16 18:36:09 +0000293enum TLoopType {
294 ELoopFor,
295 ELoopWhile,
daniel@transgaming.comb3077d02013-01-11 04:12:09 +0000296 ELoopDoWhile
alokp@chromium.org52813552010-11-16 18:36:09 +0000297};
298
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000299class TIntermLoop : public TIntermNode {
300public:
alokp@chromium.org52813552010-11-16 18:36:09 +0000301 TIntermLoop(TLoopType aType,
302 TIntermNode *aInit, TIntermTyped* aCond, TIntermTyped* aExpr,
303 TIntermNode* aBody) :
304 type(aType),
305 init(aInit),
306 cond(aCond),
307 expr(aExpr),
zmo@google.com0b8d4eb2011-04-04 19:17:11 +0000308 body(aBody),
309 unrollFlag(false) { }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000310
alokp@chromium.orgd88b7732010-05-26 15:13:14 +0000311 virtual TIntermLoop* getAsLoopNode() { return this; }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000312 virtual void traverse(TIntermTraverser*);
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700313 virtual bool replaceChildNode(
314 TIntermNode *original, TIntermNode *replacement);
alokp@chromium.org58e54292010-08-24 21:40:03 +0000315
alokp@chromium.org52813552010-11-16 18:36:09 +0000316 TLoopType getType() const { return type; }
317 TIntermNode* getInit() { return init; }
318 TIntermTyped* getCondition() { return cond; }
319 TIntermTyped* getExpression() { return expr; }
320 TIntermNode* getBody() { return body; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000321
zmo@google.com0b8d4eb2011-04-04 19:17:11 +0000322 void setUnrollFlag(bool flag) { unrollFlag = flag; }
323 bool getUnrollFlag() { return unrollFlag; }
324
Jamie Madilldd0d3422014-03-26 14:01:56 -0400325 virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const;
326
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000327protected:
alokp@chromium.org52813552010-11-16 18:36:09 +0000328 TLoopType type;
329 TIntermNode* init; // for-loop initialization
330 TIntermTyped* cond; // loop exit condition
331 TIntermTyped* expr; // for-loop expression
332 TIntermNode* body; // loop body
zmo@google.com0b8d4eb2011-04-04 19:17:11 +0000333
334 bool unrollFlag; // Whether the loop should be unrolled or not.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000335};
336
337//
338// Handle break, continue, return, and kill.
339//
340class TIntermBranch : public TIntermNode {
341public:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000342 TIntermBranch(TOperator op, TIntermTyped* e) :
343 flowOp(op),
344 expression(e) { }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000345
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000346 virtual void traverse(TIntermTraverser*);
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700347 virtual bool replaceChildNode(
348 TIntermNode *original, TIntermNode *replacement);
alokp@chromium.org58e54292010-08-24 21:40:03 +0000349
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000350 TOperator getFlowOp() { return flowOp; }
351 TIntermTyped* getExpression() { return expression; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000352
Jamie Madilldd0d3422014-03-26 14:01:56 -0400353 virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const;
354
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000355protected:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000356 TOperator flowOp;
357 TIntermTyped* expression; // non-zero except for "return exp;" statements
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000358};
359
360//
361// Nodes that correspond to symbols or constants in the source code.
362//
363class TIntermSymbol : public TIntermTyped {
364public:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000365 // if symbol is initialized as symbol(sym), the memory comes from the poolallocator of sym. If sym comes from
366 // per process globalpoolallocator, then it causes increased memory usage per compile
367 // it is essential to use "symbol = sym" to assign to symbol
368 TIntermSymbol(int i, const TString& sym, const TType& t) :
Zhenyao Mo3cdfcce2014-03-07 13:00:08 -0800369 TIntermTyped(t), id(i) { symbol = sym; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000370
Jamie Madill3c9eeb92013-11-04 11:09:26 -0500371 virtual bool hasSideEffects() const { return false; }
372
alokp@chromium.org58e54292010-08-24 21:40:03 +0000373 int getId() const { return id; }
374 const TString& getSymbol() const { return symbol; }
375
zmo@google.comfd747b82011-04-23 01:30:07 +0000376 void setId(int newId) { id = newId; }
zmo@google.comfd747b82011-04-23 01:30:07 +0000377
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000378 virtual void traverse(TIntermTraverser*);
379 virtual TIntermSymbol* getAsSymbolNode() { return this; }
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700380 virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000381
Jamie Madilldd0d3422014-03-26 14:01:56 -0400382 virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const {}
383
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000384protected:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000385 int id;
386 TString symbol;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000387};
388
Jamie Madill4cfb1e82014-07-07 12:49:23 -0400389// A Raw node stores raw code, that the translator will insert verbatim
390// into the output stream. Useful for transformation operations that make
391// complex code that might not fit naturally into the GLSL model.
392class TIntermRaw : public TIntermTyped {
393public:
394 TIntermRaw(const TType &t, const TString &rawTextIn)
395 : TIntermTyped(t), rawText(rawTextIn)
396 {}
397
398 virtual bool hasSideEffects() const { return false; }
399
400 TString getRawText() const { return rawText; }
401
402 virtual void traverse(TIntermTraverser*);
403
404 virtual TIntermRaw* getAsRawNode() { return this; }
405 virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; }
406 virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const {}
407
408protected:
409 TString rawText;
410};
411
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000412class TIntermConstantUnion : public TIntermTyped {
413public:
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000414 TIntermConstantUnion(ConstantUnion *unionPointer, const TType& t) : TIntermTyped(t), unionArrayPointer(unionPointer) { }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000415
Jamie Madill3c9eeb92013-11-04 11:09:26 -0500416 virtual bool hasSideEffects() const { return false; }
417
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000418 ConstantUnion* getUnionArrayPointer() const { return unionArrayPointer; }
shannon.woods%transgaming.com@gtempaccount.comc0d0c222013-04-13 03:29:36 +0000419
Nicolas Capensa621c2e2013-11-20 13:40:23 -0500420 int getIConst(size_t index) const { return unionArrayPointer ? unionArrayPointer[index].getIConst() : 0; }
421 unsigned int getUConst(size_t index) const { return unionArrayPointer ? unionArrayPointer[index].getUConst() : 0; }
422 float getFConst(size_t index) const { return unionArrayPointer ? unionArrayPointer[index].getFConst() : 0.0f; }
423 bool getBConst(size_t index) const { return unionArrayPointer ? unionArrayPointer[index].getBConst() : false; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000424
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000425 virtual TIntermConstantUnion* getAsConstantUnion() { return this; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000426 virtual void traverse(TIntermTraverser*);
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700427 virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000428
429 TIntermTyped* fold(TOperator, TIntermTyped*, TInfoSink&);
430
Jamie Madilldd0d3422014-03-26 14:01:56 -0400431 virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const {}
432
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000433protected:
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000434 ConstantUnion *unionArrayPointer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000435};
436
437//
438// Intermediate class for node types that hold operators.
439//
440class TIntermOperator : public TIntermTyped {
441public:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000442 TOperator getOp() const { return op; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000443 void setOp(TOperator o) { op = o; }
444
Jamie Madillf4b79ba2013-11-26 10:38:18 -0500445 bool isAssignment() const;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000446 bool isConstructor() const;
alokp@chromium.org58e54292010-08-24 21:40:03 +0000447
Jamie Madillf4b79ba2013-11-26 10:38:18 -0500448 virtual bool hasSideEffects() const { return isAssignment(); }
449
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000450protected:
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000451 TIntermOperator(TOperator o) : TIntermTyped(TType(EbtFloat, EbpUndefined)), op(o) {}
Jamie Madille53c98b2014-02-03 11:57:13 -0500452 TIntermOperator(TOperator o, const TType& t) : TIntermTyped(t), op(o) {}
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000453 TOperator op;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000454};
455
456//
457// Nodes for all the basic binary math operators.
458//
459class TIntermBinary : public TIntermOperator {
460public:
daniel@transgaming.com4167cc92013-01-11 04:11:53 +0000461 TIntermBinary(TOperator o) : TIntermOperator(o), addIndexClamp(false) {}
alokp@chromium.org58e54292010-08-24 21:40:03 +0000462
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000463 virtual TIntermBinary* getAsBinaryNode() { return this; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000464 virtual void traverse(TIntermTraverser*);
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700465 virtual bool replaceChildNode(
466 TIntermNode *original, TIntermNode *replacement);
alokp@chromium.org58e54292010-08-24 21:40:03 +0000467
Jamie Madillf4b79ba2013-11-26 10:38:18 -0500468 virtual bool hasSideEffects() const { return (isAssignment() || left->hasSideEffects() || right->hasSideEffects()); }
Jamie Madill3c9eeb92013-11-04 11:09:26 -0500469
alokp@chromium.org58e54292010-08-24 21:40:03 +0000470 void setLeft(TIntermTyped* n) { left = n; }
471 void setRight(TIntermTyped* n) { right = n; }
472 TIntermTyped* getLeft() const { return left; }
473 TIntermTyped* getRight() const { return right; }
474 bool promote(TInfoSink&);
475
daniel@transgaming.com4167cc92013-01-11 04:11:53 +0000476 void setAddIndexClamp() { addIndexClamp = true; }
477 bool getAddIndexClamp() { return addIndexClamp; }
478
Jamie Madilldd0d3422014-03-26 14:01:56 -0400479 virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const;
480
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000481protected:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000482 TIntermTyped* left;
483 TIntermTyped* right;
daniel@transgaming.com4167cc92013-01-11 04:11:53 +0000484
485 // If set to true, wrap any EOpIndexIndirect with a clamp to bounds.
486 bool addIndexClamp;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000487};
488
489//
490// Nodes for unary math operators.
491//
492class TIntermUnary : public TIntermOperator {
493public:
Jamie Madille53c98b2014-02-03 11:57:13 -0500494 TIntermUnary(TOperator o, const TType& t) : TIntermOperator(o, t), operand(0), useEmulatedFunction(false) {}
zmo@google.come4eb9912011-08-29 21:13:12 +0000495 TIntermUnary(TOperator o) : TIntermOperator(o), operand(0), useEmulatedFunction(false) {}
alokp@chromium.org58e54292010-08-24 21:40:03 +0000496
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000497 virtual void traverse(TIntermTraverser*);
daniel@transgaming.com4a35ef22010-04-08 03:51:06 +0000498 virtual TIntermUnary* getAsUnaryNode() { return this; }
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700499 virtual bool replaceChildNode(
500 TIntermNode *original, TIntermNode *replacement);
alokp@chromium.org58e54292010-08-24 21:40:03 +0000501
Jamie Madillf4b79ba2013-11-26 10:38:18 -0500502 virtual bool hasSideEffects() const { return (isAssignment() || operand->hasSideEffects()); }
Jamie Madill3c9eeb92013-11-04 11:09:26 -0500503
alokp@chromium.org58e54292010-08-24 21:40:03 +0000504 void setOperand(TIntermTyped* o) { operand = o; }
505 TIntermTyped* getOperand() { return operand; }
506 bool promote(TInfoSink&);
507
zmo@google.com32e97312011-08-24 01:03:11 +0000508 void setUseEmulatedFunction() { useEmulatedFunction = true; }
509 bool getUseEmulatedFunction() { return useEmulatedFunction; }
510
Jamie Madilldd0d3422014-03-26 14:01:56 -0400511 virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const;
512
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000513protected:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000514 TIntermTyped* operand;
zmo@google.comf420c422011-09-12 18:27:59 +0000515
516 // If set to true, replace the built-in function call with an emulated one
517 // to work around driver bugs.
518 bool useEmulatedFunction;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000519};
520
521typedef TVector<TIntermNode*> TIntermSequence;
522typedef TVector<int> TQualifierList;
alokp@chromium.org8b851c62012-06-15 16:25:11 +0000523
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000524//
525// Nodes that operate on an arbitrary sized set of children.
526//
527class TIntermAggregate : public TIntermOperator {
528public:
Jamie Madill075edd82013-07-08 13:30:19 -0400529 TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false), useEmulatedFunction(false) { }
alokp@chromium.org8b851c62012-06-15 16:25:11 +0000530 TIntermAggregate(TOperator o) : TIntermOperator(o), useEmulatedFunction(false) { }
531 ~TIntermAggregate() { }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000532
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000533 virtual TIntermAggregate* getAsAggregate() { return this; }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000534 virtual void traverse(TIntermTraverser*);
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700535 virtual bool replaceChildNode(
536 TIntermNode *original, TIntermNode *replacement);
alokp@chromium.org58e54292010-08-24 21:40:03 +0000537
Jamie Madill3c9eeb92013-11-04 11:09:26 -0500538 // Conservatively assume function calls and other aggregate operators have side-effects
539 virtual bool hasSideEffects() const { return true; }
540
alokp@chromium.org58e54292010-08-24 21:40:03 +0000541 TIntermSequence& getSequence() { return sequence; }
alokp@chromium.orgb19403a2010-09-08 17:56:26 +0000542
alokp@chromium.org58e54292010-08-24 21:40:03 +0000543 void setName(const TString& n) { name = n; }
544 const TString& getName() const { return name; }
545
546 void setUserDefined() { userDefined = true; }
maxvujovic@gmail.com66ebd012012-05-30 22:18:11 +0000547 bool isUserDefined() const { return userDefined; }
alokp@chromium.orgb19403a2010-09-08 17:56:26 +0000548
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000549 void setOptimize(bool o) { optimize = o; }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000550 bool getOptimize() { return optimize; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000551 void setDebug(bool d) { debug = d; }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000552 bool getDebug() { return debug; }
alokp@chromium.org8b851c62012-06-15 16:25:11 +0000553
zmo@google.comf420c422011-09-12 18:27:59 +0000554 void setUseEmulatedFunction() { useEmulatedFunction = true; }
555 bool getUseEmulatedFunction() { return useEmulatedFunction; }
556
Jamie Madilldd0d3422014-03-26 14:01:56 -0400557 virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const;
558
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000559protected:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000560 TIntermAggregate(const TIntermAggregate&); // disallow copy constructor
561 TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator
562 TIntermSequence sequence;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000563 TString name;
564 bool userDefined; // used for user defined function names
alokp@chromium.orgb19403a2010-09-08 17:56:26 +0000565
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000566 bool optimize;
567 bool debug;
zmo@google.comf420c422011-09-12 18:27:59 +0000568
569 // If set to true, replace the built-in function call with an emulated one
570 // to work around driver bugs.
571 bool useEmulatedFunction;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000572};
573
574//
575// For if tests. Simplified since there is no switch statement.
576//
577class TIntermSelection : public TIntermTyped {
578public:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000579 TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB) :
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000580 TIntermTyped(TType(EbtVoid, EbpUndefined)), condition(cond), trueBlock(trueB), falseBlock(falseB) {}
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000581 TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB, const TType& type) :
582 TIntermTyped(type), condition(cond), trueBlock(trueB), falseBlock(falseB) {}
alokp@chromium.org58e54292010-08-24 21:40:03 +0000583
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000584 virtual void traverse(TIntermTraverser*);
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700585 virtual bool replaceChildNode(
586 TIntermNode *original, TIntermNode *replacement);
alokp@chromium.org58e54292010-08-24 21:40:03 +0000587
Jamie Madill3c9eeb92013-11-04 11:09:26 -0500588 // Conservatively assume selections have side-effects
589 virtual bool hasSideEffects() const { return true; }
590
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000591 bool usesTernaryOperator() const { return getBasicType() != EbtVoid; }
alokp@chromium.org58e54292010-08-24 21:40:03 +0000592 TIntermNode* getCondition() const { return condition; }
593 TIntermNode* getTrueBlock() const { return trueBlock; }
594 TIntermNode* getFalseBlock() const { return falseBlock; }
595 TIntermSelection* getAsSelectionNode() { return this; }
596
Jamie Madilldd0d3422014-03-26 14:01:56 -0400597 virtual void enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const;
598
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000599protected:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000600 TIntermTyped* condition;
601 TIntermNode* trueBlock;
602 TIntermNode* falseBlock;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000603};
604
605enum Visit
606{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000607 PreVisit,
608 InVisit,
609 PostVisit
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000610};
611
612//
613// For traversing the tree. User should derive from this,
614// put their traversal specific data in it, and then pass
615// it to a Traverse method.
616//
617// When using this, just fill in the methods for nodes you want visited.
618// Return false from a pre-visit to skip visiting that node's subtree.
619//
620class TIntermTraverser
621{
622public:
Alok Priyadarshi8156b6b2013-09-23 14:56:58 -0400623 POOL_ALLOCATOR_NEW_DELETE();
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000624 TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false, bool rightToLeft = false) :
625 preVisit(preVisit),
626 inVisit(inVisit),
627 postVisit(postVisit),
628 rightToLeft(rightToLeft),
Jamie Madilleb1a0102013-07-08 13:31:38 -0400629 depth(0),
630 maxDepth(0) {}
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700631 virtual ~TIntermTraverser() {}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000632
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000633 virtual void visitSymbol(TIntermSymbol*) {}
Jamie Madill4cfb1e82014-07-07 12:49:23 -0400634 virtual void visitRaw(TIntermRaw*) {}
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000635 virtual void visitConstantUnion(TIntermConstantUnion*) {}
636 virtual bool visitBinary(Visit visit, TIntermBinary*) {return true;}
637 virtual bool visitUnary(Visit visit, TIntermUnary*) {return true;}
638 virtual bool visitSelection(Visit visit, TIntermSelection*) {return true;}
639 virtual bool visitAggregate(Visit visit, TIntermAggregate*) {return true;}
640 virtual bool visitLoop(Visit visit, TIntermLoop*) {return true;}
641 virtual bool visitBranch(Visit visit, TIntermBranch*) {return true;}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000642
Jamie Madilleb1a0102013-07-08 13:31:38 -0400643 int getMaxDepth() const {return maxDepth;}
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700644
645 void incrementDepth(TIntermNode *current)
646 {
647 depth++;
648 maxDepth = std::max(maxDepth, depth);
649 path.push_back(current);
650 }
651
652 void decrementDepth()
653 {
654 depth--;
655 path.pop_back();
656 }
657
658 TIntermNode *getParentNode()
659 {
660 return path.size() == 0 ? NULL : path.back();
661 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000662
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +0000663 // Return the original name if hash function pointer is NULL;
664 // otherwise return the hashed name.
665 static TString hash(const TString& name, ShHashFunction64 hashFunction);
666
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000667 const bool preVisit;
668 const bool inVisit;
669 const bool postVisit;
670 const bool rightToLeft;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000671
672protected:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000673 int depth;
Jamie Madilleb1a0102013-07-08 13:31:38 -0400674 int maxDepth;
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700675
676 // All the nodes from root to the current node's parent during traversing.
677 TVector<TIntermNode *> path;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000678};
679
Jamie Madill6654bc92014-03-26 14:01:57 -0400680//
681// For traversing the tree, and computing max depth.
682// Takes a maximum depth limit to prevent stack overflow.
683//
684class TMaxDepthTraverser : public TIntermTraverser
685{
686public:
687 POOL_ALLOCATOR_NEW_DELETE();
688 TMaxDepthTraverser(int depthLimit)
689 : TIntermTraverser(true, true, false, false),
690 depthLimit(depthLimit)
691 {}
692
693 virtual bool visitBinary(Visit visit, TIntermBinary*) { return depthCheck(); }
694 virtual bool visitUnary(Visit visit, TIntermUnary*) { return depthCheck(); }
695 virtual bool visitSelection(Visit visit, TIntermSelection*) { return depthCheck(); }
696 virtual bool visitAggregate(Visit visit, TIntermAggregate*) { return depthCheck(); }
697 virtual bool visitLoop(Visit visit, TIntermLoop*) { return depthCheck(); }
698 virtual bool visitBranch(Visit visit, TIntermBranch*) { return depthCheck(); }
699
700protected:
701 int depthLimit;
702
703 bool depthCheck() const { return maxDepth < depthLimit; }
704};
705
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000706#endif // __INTERMEDIATE_H