blob: f4f35f3443a94d7a94c9602584d281a4f42221d7 [file] [log] [blame]
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001//
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -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// Build the intermediate representation.
9//
10
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000011#include <float.h>
alokp@chromium.org1bcc3fd2010-05-19 17:08:44 +000012#include <limits.h>
alokp@chromium.org32cfaf42010-08-23 21:01:13 +000013#include <algorithm>
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000014
Geoff Lang17732822013-08-29 13:46:49 -040015#include "compiler/translator/HashNames.h"
16#include "compiler/translator/localintermediate.h"
17#include "compiler/translator/QualifierAlive.h"
18#include "compiler/translator/RemoveTree.h"
19#include "compiler/translator/SymbolTable.h"
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000020
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +000021bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000022
Zhenyao Mo7cab38b2013-10-15 12:59:30 -070023static TPrecision GetHigherPrecision(TPrecision left, TPrecision right)
24{
daniel@transgaming.com9abe9562010-06-24 13:02:21 +000025 return left > right ? left : right;
daniel@transgaming.coma5d76232010-05-17 09:58:47 +000026}
alokp@chromium.org32cfaf42010-08-23 21:01:13 +000027
Zhenyao Mo7cab38b2013-10-15 12:59:30 -070028const char* getOperatorString(TOperator op)
29{
alokp@chromium.orgb59a7782010-11-24 18:38:33 +000030 switch (op) {
31 case EOpInitialize: return "=";
32 case EOpAssign: return "=";
33 case EOpAddAssign: return "+=";
34 case EOpSubAssign: return "-=";
35 case EOpDivAssign: return "/=";
36
37 // Fall-through.
38 case EOpMulAssign:
39 case EOpVectorTimesMatrixAssign:
40 case EOpVectorTimesScalarAssign:
41 case EOpMatrixTimesScalarAssign:
42 case EOpMatrixTimesMatrixAssign: return "*=";
43
44 // Fall-through.
45 case EOpIndexDirect:
46 case EOpIndexIndirect: return "[]";
47
shannonwoods@chromium.org4430b0d2013-05-30 00:12:34 +000048 case EOpIndexDirectStruct:
49 case EOpIndexDirectInterfaceBlock: return ".";
alokp@chromium.orgb59a7782010-11-24 18:38:33 +000050 case EOpVectorSwizzle: return ".";
51 case EOpAdd: return "+";
52 case EOpSub: return "-";
53 case EOpMul: return "*";
54 case EOpDiv: return "/";
55 case EOpMod: UNIMPLEMENTED(); break;
56 case EOpEqual: return "==";
57 case EOpNotEqual: return "!=";
58 case EOpLessThan: return "<";
59 case EOpGreaterThan: return ">";
60 case EOpLessThanEqual: return "<=";
61 case EOpGreaterThanEqual: return ">=";
62
63 // Fall-through.
64 case EOpVectorTimesScalar:
65 case EOpVectorTimesMatrix:
66 case EOpMatrixTimesVector:
67 case EOpMatrixTimesScalar:
68 case EOpMatrixTimesMatrix: return "*";
69
70 case EOpLogicalOr: return "||";
71 case EOpLogicalXor: return "^^";
72 case EOpLogicalAnd: return "&&";
73 case EOpNegative: return "-";
74 case EOpVectorLogicalNot: return "not";
75 case EOpLogicalNot: return "!";
76 case EOpPostIncrement: return "++";
77 case EOpPostDecrement: return "--";
78 case EOpPreIncrement: return "++";
79 case EOpPreDecrement: return "--";
80
81 // Fall-through.
82 case EOpConvIntToBool:
Nicolas Capensab60b932013-06-05 10:31:21 -040083 case EOpConvUIntToBool:
alokp@chromium.orgb59a7782010-11-24 18:38:33 +000084 case EOpConvFloatToBool: return "bool";
85
86 // Fall-through.
87 case EOpConvBoolToFloat:
Nicolas Capensab60b932013-06-05 10:31:21 -040088 case EOpConvUIntToFloat:
alokp@chromium.orgb59a7782010-11-24 18:38:33 +000089 case EOpConvIntToFloat: return "float";
90
91 // Fall-through.
92 case EOpConvFloatToInt:
Nicolas Capensab60b932013-06-05 10:31:21 -040093 case EOpConvUIntToInt:
alokp@chromium.orgb59a7782010-11-24 18:38:33 +000094 case EOpConvBoolToInt: return "int";
95
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +000096 // Fall-through.
Nicolas Capensab60b932013-06-05 10:31:21 -040097 case EOpConvIntToUInt:
98 case EOpConvFloatToUInt:
99 case EOpConvBoolToUInt: return "uint";
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000100
alokp@chromium.orgb59a7782010-11-24 18:38:33 +0000101 case EOpRadians: return "radians";
102 case EOpDegrees: return "degrees";
103 case EOpSin: return "sin";
104 case EOpCos: return "cos";
105 case EOpTan: return "tan";
106 case EOpAsin: return "asin";
107 case EOpAcos: return "acos";
108 case EOpAtan: return "atan";
109 case EOpExp: return "exp";
110 case EOpLog: return "log";
111 case EOpExp2: return "exp2";
112 case EOpLog2: return "log2";
113 case EOpSqrt: return "sqrt";
114 case EOpInverseSqrt: return "inversesqrt";
115 case EOpAbs: return "abs";
116 case EOpSign: return "sign";
117 case EOpFloor: return "floor";
118 case EOpCeil: return "ceil";
119 case EOpFract: return "fract";
120 case EOpLength: return "length";
121 case EOpNormalize: return "normalize";
122 case EOpDFdx: return "dFdx";
123 case EOpDFdy: return "dFdy";
124 case EOpFwidth: return "fwidth";
125 case EOpAny: return "any";
126 case EOpAll: return "all";
127
128 default: break;
129 }
130 return "";
131}
132
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000133////////////////////////////////////////////////////////////////////////////
134//
135// First set of functions are to help build the intermediate representation.
136// These functions are not member functions of the nodes.
137// They are called from parser productions.
138//
139/////////////////////////////////////////////////////////////////////////////
140
141//
142// Add a terminal node for an identifier in an expression.
143//
144// Returns the added node.
145//
Jamie Madill075edd82013-07-08 13:30:19 -0400146TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, const TSourceLoc& line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000147{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000148 TIntermSymbol* node = new TIntermSymbol(id, name, type);
149 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000150
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000151 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000152}
153
154//
155// Connect two nodes with a new parent that does a binary operation on the nodes.
156//
157// Returns the added node.
158//
Jamie Madill075edd82013-07-08 13:30:19 -0400159TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc& line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000160{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000161 switch (op) {
alokp@chromium.org8f0f24a2010-09-01 21:06:24 +0000162 case EOpEqual:
163 case EOpNotEqual:
164 if (left->isArray())
165 return 0;
166 break;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000167 case EOpLessThan:
168 case EOpGreaterThan:
169 case EOpLessThanEqual:
170 case EOpGreaterThanEqual:
alokp@chromium.org8f0f24a2010-09-01 21:06:24 +0000171 if (left->isMatrix() || left->isArray() || left->isVector() || left->getBasicType() == EbtStruct) {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000172 return 0;
173 }
174 break;
175 case EOpLogicalOr:
176 case EOpLogicalXor:
177 case EOpLogicalAnd:
alokp@chromium.org8f0f24a2010-09-01 21:06:24 +0000178 if (left->getBasicType() != EbtBool || left->isMatrix() || left->isArray() || left->isVector()) {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000179 return 0;
180 }
181 break;
182 case EOpAdd:
183 case EOpSub:
184 case EOpDiv:
185 case EOpMul:
alokp@chromium.org8f0f24a2010-09-01 21:06:24 +0000186 if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool)
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000187 return 0;
188 default: break;
189 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000190
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -0400191 if (left->getBasicType() != right->getBasicType())
192 {
193 return 0;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000194 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000195
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000196 //
197 // Need a new node holding things together then. Make
198 // one and promote it to the right type.
199 //
200 TIntermBinary* node = new TIntermBinary(op);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000201 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000202
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000203 node->setLeft(left);
204 node->setRight(right);
alokp@chromium.org8f0f24a2010-09-01 21:06:24 +0000205 if (!node->promote(infoSink))
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000206 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000207
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000208 //
209 // See if we can fold constants.
210 //
alokp@chromium.org8f0f24a2010-09-01 21:06:24 +0000211 TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion();
212 TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion();
213 if (leftTempConstant && rightTempConstant) {
Nicolas Capensbd0ea9c2014-03-04 13:53:29 -0500214 TIntermTyped *typedReturnNode = leftTempConstant->fold(node->getOp(), rightTempConstant, infoSink);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000215
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000216 if (typedReturnNode)
217 return typedReturnNode;
218 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000219
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000220 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000221}
222
223//
224// Connect two nodes through an assignment.
225//
226// Returns the added node.
227//
Jamie Madill075edd82013-07-08 13:30:19 -0400228TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc& line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000229{
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -0400230 if (left->getType().getStruct() || right->getType().getStruct())
231 {
232 if (left->getType() != right->getType())
233 {
234 return 0;
235 }
236 }
237
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000238 TIntermBinary* node = new TIntermBinary(op);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000239 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000240
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000241 node->setLeft(left);
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -0400242 node->setRight(right);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000243 if (! node->promote(infoSink))
244 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000245
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000246 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000247}
248
249//
250// Connect two nodes through an index operator, where the left node is the base
251// of an array or struct, and the right node is a direct or indirect offset.
252//
253// Returns the added node.
254// The caller should set the type of the returned node.
255//
Jamie Madill075edd82013-07-08 13:30:19 -0400256TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, const TSourceLoc& line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000257{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000258 TIntermBinary* node = new TIntermBinary(op);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000259 node->setLine(line);
260 node->setLeft(base);
261 node->setRight(index);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000262
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000263 // caller should set the type
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000264
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000265 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000266}
267
268//
269// Add one node as the parent of another that it operates on.
270//
271// Returns the added node.
272//
Jamie Madill075edd82013-07-08 13:30:19 -0400273TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode, const TSourceLoc& line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000274{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000275 TIntermUnary* node;
276 TIntermTyped* child = childNode->getAsTyped();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000277
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000278 if (child == 0) {
Jamie Madill075edd82013-07-08 13:30:19 -0400279 infoSink.info.message(EPrefixInternalError, line, "Bad type in AddUnaryMath");
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000280 return 0;
281 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000282
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000283 switch (op) {
284 case EOpLogicalNot:
285 if (child->getType().getBasicType() != EbtBool || child->getType().isMatrix() || child->getType().isArray() || child->getType().isVector()) {
286 return 0;
287 }
288 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000289
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000290 case EOpPostIncrement:
291 case EOpPreIncrement:
292 case EOpPostDecrement:
293 case EOpPreDecrement:
294 case EOpNegative:
295 if (child->getType().getBasicType() == EbtStruct || child->getType().isArray())
296 return 0;
297 default: break;
298 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000299
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000300 TIntermConstantUnion *childTempConstant = 0;
301 if (child->getAsConstantUnion())
302 childTempConstant = child->getAsConstantUnion();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000303
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000304 //
305 // Make a new node for the operator.
306 //
307 node = new TIntermUnary(op);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000308 node->setLine(line);
309 node->setOperand(child);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000310
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000311 if (! node->promote(infoSink))
312 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000313
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000314 if (childTempConstant) {
315 TIntermTyped* newChild = childTempConstant->fold(op, 0, infoSink);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000316
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000317 if (newChild)
318 return newChild;
319 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000320
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000321 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000322}
323
324//
325// This is the safe way to change the operator on an aggregate, as it
326// does lots of error checking and fixing. Especially for establishing
327// a function call's operation on it's set of parameters. Sequences
328// of instructions are also aggregates, but they just direnctly set
329// their operator to EOpSequence.
330//
331// Returns an aggregate node, which could be the one passed in if
daniel@transgaming.com978702d2012-04-04 15:05:58 +0000332// it was already an aggregate but no operator was set.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000333//
Jamie Madill075edd82013-07-08 13:30:19 -0400334TIntermAggregate* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator op, const TSourceLoc& line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000335{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000336 TIntermAggregate* aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000337
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000338 //
339 // Make sure we have an aggregate. If not turn it into one.
340 //
341 if (node) {
342 aggNode = node->getAsAggregate();
343 if (aggNode == 0 || aggNode->getOp() != EOpNull) {
344 //
345 // Make an aggregate containing this node.
346 //
347 aggNode = new TIntermAggregate();
348 aggNode->getSequence().push_back(node);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000349 }
350 } else
351 aggNode = new TIntermAggregate();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000352
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000353 //
354 // Set the operator.
355 //
alokp@chromium.org58e54292010-08-24 21:40:03 +0000356 aggNode->setOp(op);
Jamie Madill075edd82013-07-08 13:30:19 -0400357 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000358
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000359 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000360}
361
362//
363// Convert one type to another.
364//
365// Returns the node representing the conversion, which could be the same
366// node passed in if no conversion was needed.
367//
368// Return 0 if a conversion can't be done.
369//
370TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TIntermTyped* node)
371{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000372 //
373 // Does the base type allow operation?
374 //
Nicolas Capens344e7142013-06-24 15:39:21 -0400375 if (node->getBasicType() == EbtVoid ||
376 IsSampler(node->getBasicType()))
377 {
378 return 0;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000379 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000380
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000381 //
382 // Otherwise, if types are identical, no problem
383 //
384 if (type == node->getType())
385 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000386
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000387 //
388 // If one's a structure, then no conversions.
389 //
390 if (type.getStruct() || node->getType().getStruct())
391 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000392
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000393 //
394 // If one's an array, then no conversions.
395 //
396 if (type.isArray() || node->getType().isArray())
397 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000398
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000399 TBasicType promoteTo;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000400
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000401 switch (op) {
402 //
403 // Explicit conversions
404 //
405 case EOpConstructBool:
406 promoteTo = EbtBool;
407 break;
408 case EOpConstructFloat:
409 promoteTo = EbtFloat;
410 break;
411 case EOpConstructInt:
412 promoteTo = EbtInt;
413 break;
Nicolas Capensab60b932013-06-05 10:31:21 -0400414 case EOpConstructUInt:
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000415 promoteTo = EbtUInt;
416 break;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000417 default:
418 //
419 // implicit conversions were removed from the language.
420 //
421 if (type.getBasicType() != node->getType().getBasicType())
422 return 0;
423 //
424 // Size and structure could still differ, but that's
425 // handled by operator promotion.
426 //
427 return node;
428 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000429
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000430 if (node->getAsConstantUnion()) {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000431
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000432 return (promoteConstantUnion(promoteTo, node->getAsConstantUnion()));
433 } else {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000434
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000435 //
436 // Add a new newNode for the conversion.
437 //
438 TIntermUnary* newNode = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000439
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000440 TOperator newOp = EOpNull;
441 switch (promoteTo) {
442 case EbtFloat:
443 switch (node->getBasicType()) {
Nicolas Capensab60b932013-06-05 10:31:21 -0400444 case EbtInt: newOp = EOpConvIntToFloat; break;
445 case EbtUInt: newOp = EOpConvFloatToUInt; break;
446 case EbtBool: newOp = EOpConvBoolToFloat; break;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000447 default:
Jamie Madill075edd82013-07-08 13:30:19 -0400448 infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion node");
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000449 return 0;
450 }
451 break;
452 case EbtBool:
453 switch (node->getBasicType()) {
Nicolas Capensab60b932013-06-05 10:31:21 -0400454 case EbtInt: newOp = EOpConvIntToBool; break;
455 case EbtUInt: newOp = EOpConvBoolToUInt; break;
456 case EbtFloat: newOp = EOpConvFloatToBool; break;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000457 default:
Jamie Madill075edd82013-07-08 13:30:19 -0400458 infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion node");
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000459 return 0;
460 }
461 break;
462 case EbtInt:
463 switch (node->getBasicType()) {
Nicolas Capensab60b932013-06-05 10:31:21 -0400464 case EbtUInt: newOp = EOpConvUIntToInt; break;
465 case EbtBool: newOp = EOpConvBoolToInt; break;
466 case EbtFloat: newOp = EOpConvFloatToInt; break;
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000467 default:
Jamie Madill075edd82013-07-08 13:30:19 -0400468 infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion node");
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000469 return 0;
470 }
471 break;
472 case EbtUInt:
473 switch (node->getBasicType()) {
Nicolas Capensab60b932013-06-05 10:31:21 -0400474 case EbtInt: newOp = EOpConvIntToUInt; break;
475 case EbtBool: newOp = EOpConvBoolToUInt; break;
476 case EbtFloat: newOp = EOpConvFloatToUInt; break;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000477 default:
Jamie Madill075edd82013-07-08 13:30:19 -0400478 infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion node");
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000479 return 0;
480 }
481 break;
482 default:
Jamie Madill075edd82013-07-08 13:30:19 -0400483 infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion type");
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000484 return 0;
485 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000486
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +0000487 TType type(promoteTo, node->getPrecision(), EvqTemporary, node->getNominalSize(), node->getSecondarySize(), node->isArray());
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000488 newNode = new TIntermUnary(newOp, type);
489 newNode->setLine(node->getLine());
490 newNode->setOperand(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000491
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000492 return newNode;
493 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000494}
495
496//
497// Safe way to combine two nodes into an aggregate. Works with null pointers,
498// a node that's not a aggregate yet, etc.
499//
500// Returns the resulting aggregate, unless 0 was passed in for
501// both existing nodes.
502//
Jamie Madill075edd82013-07-08 13:30:19 -0400503TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc& line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000504{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000505 if (left == 0 && right == 0)
506 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000507
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000508 TIntermAggregate* aggNode = 0;
509 if (left)
510 aggNode = left->getAsAggregate();
511 if (!aggNode || aggNode->getOp() != EOpNull) {
512 aggNode = new TIntermAggregate;
513 if (left)
514 aggNode->getSequence().push_back(left);
515 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000516
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000517 if (right)
518 aggNode->getSequence().push_back(right);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000519
Jamie Madill075edd82013-07-08 13:30:19 -0400520 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000521
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000522 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000523}
524
525//
526// Turn an existing node into an aggregate.
527//
528// Returns an aggregate, unless 0 was passed in for the existing node.
529//
Jamie Madill075edd82013-07-08 13:30:19 -0400530TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, const TSourceLoc& line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000531{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000532 if (node == 0)
533 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000534
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000535 TIntermAggregate* aggNode = new TIntermAggregate;
536 aggNode->getSequence().push_back(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000537
Jamie Madill075edd82013-07-08 13:30:19 -0400538 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000539
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000540 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000541}
542
543//
544// For "if" test nodes. There are three children; a condition,
545// a true path, and a false path. The two paths are in the
546// nodePair.
547//
548// Returns the selection node created.
549//
Jamie Madill075edd82013-07-08 13:30:19 -0400550TIntermNode* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nodePair, const TSourceLoc& line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000551{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000552 //
553 // For compile time constant selections, prune the code and
554 // test now.
555 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000556
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000557 if (cond->getAsTyped() && cond->getAsTyped()->getAsConstantUnion()) {
shannon.woods%transgaming.com@gtempaccount.comc0d0c222013-04-13 03:29:36 +0000558 if (cond->getAsConstantUnion()->getBConst(0) == true)
daniel@transgaming.com978702d2012-04-04 15:05:58 +0000559 return nodePair.node1 ? setAggregateOperator(nodePair.node1, EOpSequence, nodePair.node1->getLine()) : NULL;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000560 else
daniel@transgaming.com978702d2012-04-04 15:05:58 +0000561 return nodePair.node2 ? setAggregateOperator(nodePair.node2, EOpSequence, nodePair.node2->getLine()) : NULL;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000562 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000563
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000564 TIntermSelection* node = new TIntermSelection(cond, nodePair.node1, nodePair.node2);
565 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000566
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000567 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000568}
569
570
Jamie Madill075edd82013-07-08 13:30:19 -0400571TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc& line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000572{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000573 if (left->getType().getQualifier() == EvqConst && right->getType().getQualifier() == EvqConst) {
574 return right;
575 } else {
576 TIntermTyped *commaAggregate = growAggregate(left, right, line);
alokp@chromium.org58e54292010-08-24 21:40:03 +0000577 commaAggregate->getAsAggregate()->setOp(EOpComma);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000578 commaAggregate->setType(right->getType());
alokp@chromium.org58e54292010-08-24 21:40:03 +0000579 commaAggregate->getTypePointer()->setQualifier(EvqTemporary);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000580 return commaAggregate;
581 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000582}
583
584//
585// For "?:" test nodes. There are three children; a condition,
586// a true path, and a false path. The two paths are specified
587// as separate parameters.
588//
589// Returns the selection node created, or 0 if one could not be.
590//
Jamie Madill075edd82013-07-08 13:30:19 -0400591TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc& line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000592{
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -0400593 if (trueBlock->getType() != falseBlock->getType())
594 {
595 return 0;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000596 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000597
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000598 //
599 // See if all the operands are constant, then fold it otherwise not.
600 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000601
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000602 if (cond->getAsConstantUnion() && trueBlock->getAsConstantUnion() && falseBlock->getAsConstantUnion()) {
shannon.woods%transgaming.com@gtempaccount.comc0d0c222013-04-13 03:29:36 +0000603 if (cond->getAsConstantUnion()->getBConst(0))
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000604 return trueBlock;
605 else
606 return falseBlock;
607 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000608
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000609 //
610 // Make a selection node.
611 //
612 TIntermSelection* node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType());
daniel@transgaming.com43affc52012-03-28 14:55:39 +0000613 node->getTypePointer()->setQualifier(EvqTemporary);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000614 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000615
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000616 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000617}
618
619//
620// Constant terminal nodes. Has a union that contains bool, float or int constants
621//
622// Returns the constant union node created.
623//
624
Jamie Madill075edd82013-07-08 13:30:19 -0400625TIntermConstantUnion* TIntermediate::addConstantUnion(ConstantUnion* unionArrayPointer, const TType& t, const TSourceLoc& line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000626{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000627 TIntermConstantUnion* node = new TIntermConstantUnion(unionArrayPointer, t);
628 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000629
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000630 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000631}
632
Jamie Madill075edd82013-07-08 13:30:19 -0400633TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, const TSourceLoc& line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000634{
635
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000636 TIntermAggregate* node = new TIntermAggregate(EOpSequence);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000637
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000638 node->setLine(line);
639 TIntermConstantUnion* constIntNode;
640 TIntermSequence &sequenceVector = node->getSequence();
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000641 ConstantUnion* unionArray;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000642
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000643 for (int i = 0; i < fields.num; i++) {
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000644 unionArray = new ConstantUnion[1];
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000645 unionArray->setIConst(fields.offsets[i]);
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000646 constIntNode = addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), line);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000647 sequenceVector.push_back(constIntNode);
648 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000649
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000650 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000651}
652
653//
654// Create loop nodes.
655//
Jamie Madill075edd82013-07-08 13:30:19 -0400656TIntermNode* TIntermediate::addLoop(TLoopType type, TIntermNode* init, TIntermTyped* cond, TIntermTyped* expr, TIntermNode* body, const TSourceLoc& line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000657{
alokp@chromium.org52813552010-11-16 18:36:09 +0000658 TIntermNode* node = new TIntermLoop(type, init, cond, expr, body);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000659 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000660
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000661 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000662}
663
664//
665// Add branches.
666//
Jamie Madill075edd82013-07-08 13:30:19 -0400667TIntermBranch* TIntermediate::addBranch(TOperator branchOp, const TSourceLoc& line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000668{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000669 return addBranch(branchOp, 0, line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000670}
671
Jamie Madill075edd82013-07-08 13:30:19 -0400672TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expression, const TSourceLoc& line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000673{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000674 TIntermBranch* node = new TIntermBranch(branchOp, expression);
675 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000676
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000677 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000678}
679
680//
681// This is to be executed once the final root is put on top by the parsing
682// process.
683//
alokp@chromium.org07620a52010-09-23 17:53:56 +0000684bool TIntermediate::postProcess(TIntermNode* root)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000685{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000686 if (root == 0)
687 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000688
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000689 //
690 // First, finish off the top level sequence, if any
691 //
692 TIntermAggregate* aggRoot = root->getAsAggregate();
693 if (aggRoot && aggRoot->getOp() == EOpNull)
alokp@chromium.org58e54292010-08-24 21:40:03 +0000694 aggRoot->setOp(EOpSequence);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000695
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000696 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000697}
698
699//
700// This deletes the tree.
701//
702void TIntermediate::remove(TIntermNode* root)
703{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000704 if (root)
705 RemoveAllTreeNodes(root);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000706}
707
708////////////////////////////////////////////////////////////////
709//
710// Member functions of the nodes used for building the tree.
711//
712////////////////////////////////////////////////////////////////
713
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700714#define REPLACE_IF_IS(node, type, original, replacement) \
715 if (node == original) { \
716 node = static_cast<type *>(replacement); \
717 return true; \
718 }
719
720bool TIntermLoop::replaceChildNode(
721 TIntermNode *original, TIntermNode *replacement)
722{
723 REPLACE_IF_IS(init, TIntermNode, original, replacement);
724 REPLACE_IF_IS(cond, TIntermTyped, original, replacement);
725 REPLACE_IF_IS(expr, TIntermTyped, original, replacement);
726 REPLACE_IF_IS(body, TIntermNode, original, replacement);
727 return false;
728}
729
Jamie Madilldd0d3422014-03-26 14:01:56 -0400730void TIntermLoop::enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const
731{
732 if (init)
733 {
734 nodeQueue->push(init);
735 }
736 if (cond)
737 {
738 nodeQueue->push(cond);
739 }
740 if (expr)
741 {
742 nodeQueue->push(expr);
743 }
744 if (body)
745 {
746 nodeQueue->push(body);
747 }
748}
749
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700750bool TIntermBranch::replaceChildNode(
751 TIntermNode *original, TIntermNode *replacement)
752{
753 REPLACE_IF_IS(expression, TIntermTyped, original, replacement);
754 return false;
755}
756
Jamie Madilldd0d3422014-03-26 14:01:56 -0400757void TIntermBranch::enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const
758{
759 if (expression)
760 {
761 nodeQueue->push(expression);
762 }
763}
764
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700765bool TIntermBinary::replaceChildNode(
766 TIntermNode *original, TIntermNode *replacement)
767{
768 REPLACE_IF_IS(left, TIntermTyped, original, replacement);
769 REPLACE_IF_IS(right, TIntermTyped, original, replacement);
770 return false;
771}
772
Jamie Madilldd0d3422014-03-26 14:01:56 -0400773void TIntermBinary::enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const
774{
775 if (left)
776 {
777 nodeQueue->push(left);
778 }
779 if (right)
780 {
781 nodeQueue->push(right);
782 }
783}
784
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700785bool TIntermUnary::replaceChildNode(
786 TIntermNode *original, TIntermNode *replacement)
787{
788 REPLACE_IF_IS(operand, TIntermTyped, original, replacement);
789 return false;
790}
791
Jamie Madilldd0d3422014-03-26 14:01:56 -0400792void TIntermUnary::enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const
793{
794 if (operand)
795 {
796 nodeQueue->push(operand);
797 }
798}
799
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700800bool TIntermAggregate::replaceChildNode(
801 TIntermNode *original, TIntermNode *replacement)
802{
803 for (size_t ii = 0; ii < sequence.size(); ++ii)
804 {
805 REPLACE_IF_IS(sequence[ii], TIntermNode, original, replacement);
806 }
807 return false;
808}
809
Jamie Madilldd0d3422014-03-26 14:01:56 -0400810void TIntermAggregate::enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const
811{
812 for (size_t childIndex = 0; childIndex < sequence.size(); childIndex++)
813 {
814 nodeQueue->push(sequence[childIndex]);
815 }
816}
817
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700818bool TIntermSelection::replaceChildNode(
819 TIntermNode *original, TIntermNode *replacement)
820{
821 REPLACE_IF_IS(condition, TIntermTyped, original, replacement);
822 REPLACE_IF_IS(trueBlock, TIntermNode, original, replacement);
823 REPLACE_IF_IS(falseBlock, TIntermNode, original, replacement);
824 return false;
825}
826
Jamie Madilldd0d3422014-03-26 14:01:56 -0400827void TIntermSelection::enqueueChildren(std::queue<TIntermNode*> *nodeQueue) const
828{
829 if (condition)
830 {
831 nodeQueue->push(condition);
832 }
833 if (trueBlock)
834 {
835 nodeQueue->push(trueBlock);
836 }
837 if (falseBlock)
838 {
839 nodeQueue->push(falseBlock);
840 }
841}
842
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000843//
844// Say whether or not an operation node changes the value of a variable.
845//
Jamie Madillf4b79ba2013-11-26 10:38:18 -0500846bool TIntermOperator::isAssignment() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000847{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000848 switch (op) {
849 case EOpPostIncrement:
850 case EOpPostDecrement:
851 case EOpPreIncrement:
852 case EOpPreDecrement:
853 case EOpAssign:
854 case EOpAddAssign:
855 case EOpSubAssign:
856 case EOpMulAssign:
857 case EOpVectorTimesMatrixAssign:
858 case EOpVectorTimesScalarAssign:
859 case EOpMatrixTimesScalarAssign:
860 case EOpMatrixTimesMatrixAssign:
861 case EOpDivAssign:
862 return true;
863 default:
864 return false;
865 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000866}
867
868//
869// returns true if the operator is for one of the constructors
870//
871bool TIntermOperator::isConstructor() const
872{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000873 switch (op) {
874 case EOpConstructVec2:
875 case EOpConstructVec3:
876 case EOpConstructVec4:
877 case EOpConstructMat2:
878 case EOpConstructMat3:
879 case EOpConstructMat4:
880 case EOpConstructFloat:
881 case EOpConstructIVec2:
882 case EOpConstructIVec3:
883 case EOpConstructIVec4:
884 case EOpConstructInt:
shannonwoods@chromium.org8c788e82013-05-30 00:20:21 +0000885 case EOpConstructUVec2:
886 case EOpConstructUVec3:
887 case EOpConstructUVec4:
Nicolas Capensab60b932013-06-05 10:31:21 -0400888 case EOpConstructUInt:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000889 case EOpConstructBVec2:
890 case EOpConstructBVec3:
891 case EOpConstructBVec4:
892 case EOpConstructBool:
893 case EOpConstructStruct:
894 return true;
895 default:
896 return false;
897 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000898}
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700899
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000900//
901// Make sure the type of a unary operator is appropriate for its
902// combination of operation and operand type.
903//
904// Returns false in nothing makes sense.
905//
906bool TIntermUnary::promote(TInfoSink&)
907{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000908 switch (op) {
909 case EOpLogicalNot:
910 if (operand->getBasicType() != EbtBool)
911 return false;
912 break;
913 case EOpNegative:
914 case EOpPostIncrement:
915 case EOpPostDecrement:
916 case EOpPreIncrement:
917 case EOpPreDecrement:
918 if (operand->getBasicType() == EbtBool)
919 return false;
920 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000921
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000922 // operators for built-ins are already type checked against their prototype
923 case EOpAny:
924 case EOpAll:
925 case EOpVectorLogicalNot:
926 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000927
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000928 default:
929 if (operand->getBasicType() != EbtFloat)
930 return false;
931 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000932
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000933 setType(operand->getType());
shannon.woods%transgaming.com@gtempaccount.comac1fc752013-04-13 03:29:52 +0000934 type.setQualifier(EvqTemporary);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000935
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000936 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000937}
938
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +0000939bool validateMultiplication(TOperator op, const TType &left, const TType &right)
940{
941 switch (op)
942 {
943 case EOpMul:
944 case EOpMulAssign:
945 return left.getNominalSize() == right.getNominalSize() && left.getSecondarySize() == right.getSecondarySize();
946 case EOpVectorTimesScalar:
947 case EOpVectorTimesScalarAssign:
948 return true;
949 case EOpVectorTimesMatrix:
950 return left.getNominalSize() == right.getRows();
951 case EOpVectorTimesMatrixAssign:
952 return left.getNominalSize() == right.getRows() && left.getNominalSize() == right.getCols();
953 case EOpMatrixTimesVector:
954 return left.getCols() == right.getNominalSize();
955 case EOpMatrixTimesScalar:
956 case EOpMatrixTimesScalarAssign:
957 return true;
958 case EOpMatrixTimesMatrix:
959 return left.getCols() == right.getRows();
960 case EOpMatrixTimesMatrixAssign:
961 return left.getCols() == right.getCols() && left.getRows() == right.getRows();
962
963 default:
964 UNREACHABLE();
965 return false;
966 }
967}
968
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000969//
970// Establishes the type of the resultant operation, as well as
971// makes the operator the correct one for the operands.
972//
973// Returns false if operator can't work on operands.
974//
975bool TIntermBinary::promote(TInfoSink& infoSink)
976{
alokp@chromium.org8f0f24a2010-09-01 21:06:24 +0000977 // This function only handles scalars, vectors, and matrices.
shannonwoods@chromium.orgb7dc4032013-05-30 00:18:18 +0000978 if (left->isArray() || right->isArray())
979 {
Jamie Madill075edd82013-07-08 13:30:19 -0400980 infoSink.info.message(EPrefixInternalError, getLine(), "Invalid operation for arrays");
alokp@chromium.org8f0f24a2010-09-01 21:06:24 +0000981 return false;
982 }
983
alokp@chromium.org32cfaf42010-08-23 21:01:13 +0000984 // GLSL ES 2.0 does not support implicit type casting.
985 // So the basic type should always match.
986 if (left->getBasicType() != right->getBasicType())
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -0400987 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000988 return false;
Nicolas Capens6ed8d8a2014-06-11 11:25:20 -0400989 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000990
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000991 //
992 // Base assumption: just make the type the same as the left
993 // operand. Then only deviations from this need be coded.
994 //
daniel@transgaming.comfe565152010-04-10 05:29:07 +0000995 setType(left->getType());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000996
alokp@chromium.org32cfaf42010-08-23 21:01:13 +0000997 // The result gets promoted to the highest precision.
998 TPrecision higherPrecision = GetHigherPrecision(left->getPrecision(), right->getPrecision());
alokp@chromium.org58e54292010-08-24 21:40:03 +0000999 getTypePointer()->setPrecision(higherPrecision);
alokp@chromium.org32cfaf42010-08-23 21:01:13 +00001000
1001 // Binary operations results in temporary variables unless both
1002 // operands are const.
shannonwoods@chromium.orgb7dc4032013-05-30 00:18:18 +00001003 if (left->getQualifier() != EvqConst || right->getQualifier() != EvqConst)
1004 {
alokp@chromium.org58e54292010-08-24 21:40:03 +00001005 getTypePointer()->setQualifier(EvqTemporary);
alokp@chromium.org32cfaf42010-08-23 21:01:13 +00001006 }
daniel@transgaming.coma5d76232010-05-17 09:58:47 +00001007
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00001008 const int nominalSize = std::max(left->getNominalSize(), right->getNominalSize());
alokp@chromium.org32cfaf42010-08-23 21:01:13 +00001009
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001010 //
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00001011 // All scalars or structs. Code after this test assumes this case is removed!
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001012 //
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00001013 if (nominalSize == 1)
shannonwoods@chromium.orgb7dc4032013-05-30 00:18:18 +00001014 {
1015 switch (op)
1016 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001017 //
1018 // Promote to conditional
1019 //
1020 case EOpEqual:
1021 case EOpNotEqual:
1022 case EOpLessThan:
1023 case EOpGreaterThan:
1024 case EOpLessThanEqual:
1025 case EOpGreaterThanEqual:
daniel@transgaming.coma5d76232010-05-17 09:58:47 +00001026 setType(TType(EbtBool, EbpUndefined));
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001027 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001028
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001029 //
1030 // And and Or operate on conditionals
1031 //
1032 case EOpLogicalAnd:
1033 case EOpLogicalOr:
alokp@chromium.org32cfaf42010-08-23 21:01:13 +00001034 // Both operands must be of type bool.
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001035 if (left->getBasicType() != EbtBool || right->getBasicType() != EbtBool)
shannonwoods@chromium.orgb7dc4032013-05-30 00:18:18 +00001036 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001037 return false;
shannonwoods@chromium.orgb7dc4032013-05-30 00:18:18 +00001038 }
daniel@transgaming.coma5d76232010-05-17 09:58:47 +00001039 setType(TType(EbtBool, EbpUndefined));
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001040 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001041
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001042 default:
alokp@chromium.org32cfaf42010-08-23 21:01:13 +00001043 break;
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001044 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001045 return true;
1046 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001047
alokp@chromium.org32cfaf42010-08-23 21:01:13 +00001048 // If we reach here, at least one of the operands is vector or matrix.
1049 // The other operand could be a scalar, vector, or matrix.
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001050 // Can these two operands be combined?
1051 //
alokp@chromium.org32cfaf42010-08-23 21:01:13 +00001052 TBasicType basicType = left->getBasicType();
shannonwoods@chromium.orgb7dc4032013-05-30 00:18:18 +00001053 switch (op)
1054 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001055 case EOpMul:
shannonwoods@chromium.orgb7dc4032013-05-30 00:18:18 +00001056 if (!left->isMatrix() && right->isMatrix())
1057 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001058 if (left->isVector())
shannonwoods@chromium.orgb7dc4032013-05-30 00:18:18 +00001059 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001060 op = EOpVectorTimesMatrix;
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +00001061 setType(TType(basicType, higherPrecision, EvqTemporary, right->getCols(), 1));
shannonwoods@chromium.orgb7dc4032013-05-30 00:18:18 +00001062 }
1063 else
1064 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001065 op = EOpMatrixTimesScalar;
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00001066 setType(TType(basicType, higherPrecision, EvqTemporary, right->getCols(), right->getRows()));
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001067 }
shannonwoods@chromium.orgb7dc4032013-05-30 00:18:18 +00001068 }
1069 else if (left->isMatrix() && !right->isMatrix())
1070 {
1071 if (right->isVector())
1072 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001073 op = EOpMatrixTimesVector;
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00001074 setType(TType(basicType, higherPrecision, EvqTemporary, left->getRows(), 1));
shannonwoods@chromium.orgb7dc4032013-05-30 00:18:18 +00001075 }
1076 else
1077 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001078 op = EOpMatrixTimesScalar;
1079 }
shannonwoods@chromium.orgb7dc4032013-05-30 00:18:18 +00001080 }
1081 else if (left->isMatrix() && right->isMatrix())
1082 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001083 op = EOpMatrixTimesMatrix;
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +00001084 setType(TType(basicType, higherPrecision, EvqTemporary, right->getCols(), left->getRows()));
shannonwoods@chromium.orgb7dc4032013-05-30 00:18:18 +00001085 }
1086 else if (!left->isMatrix() && !right->isMatrix())
1087 {
1088 if (left->isVector() && right->isVector())
1089 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001090 // leave as component product
shannonwoods@chromium.orgb7dc4032013-05-30 00:18:18 +00001091 }
1092 else if (left->isVector() || right->isVector())
1093 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001094 op = EOpVectorTimesScalar;
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00001095 setType(TType(basicType, higherPrecision, EvqTemporary, nominalSize, 1));
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001096 }
shannonwoods@chromium.orgb7dc4032013-05-30 00:18:18 +00001097 }
1098 else
1099 {
Jamie Madill075edd82013-07-08 13:30:19 -04001100 infoSink.info.message(EPrefixInternalError, getLine(), "Missing elses");
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001101 return false;
1102 }
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00001103
1104 if (!validateMultiplication(op, left->getType(), right->getType()))
1105 {
1106 return false;
1107 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001108 break;
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00001109
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001110 case EOpMulAssign:
shannonwoods@chromium.orgb7dc4032013-05-30 00:18:18 +00001111 if (!left->isMatrix() && right->isMatrix())
1112 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001113 if (left->isVector())
shannonwoods@chromium.orgb7dc4032013-05-30 00:18:18 +00001114 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001115 op = EOpVectorTimesMatrixAssign;
shannonwoods@chromium.orgb7dc4032013-05-30 00:18:18 +00001116 }
1117 else
1118 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001119 return false;
1120 }
shannonwoods@chromium.orgb7dc4032013-05-30 00:18:18 +00001121 }
1122 else if (left->isMatrix() && !right->isMatrix())
1123 {
1124 if (right->isVector())
1125 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001126 return false;
shannonwoods@chromium.orgb7dc4032013-05-30 00:18:18 +00001127 }
1128 else
1129 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001130 op = EOpMatrixTimesScalarAssign;
1131 }
shannonwoods@chromium.orgb7dc4032013-05-30 00:18:18 +00001132 }
1133 else if (left->isMatrix() && right->isMatrix())
1134 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001135 op = EOpMatrixTimesMatrixAssign;
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +00001136 setType(TType(basicType, higherPrecision, EvqTemporary, right->getCols(), left->getRows()));
shannonwoods@chromium.orgb7dc4032013-05-30 00:18:18 +00001137 }
1138 else if (!left->isMatrix() && !right->isMatrix())
1139 {
1140 if (left->isVector() && right->isVector())
1141 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001142 // leave as component product
shannonwoods@chromium.orgb7dc4032013-05-30 00:18:18 +00001143 }
1144 else if (left->isVector() || right->isVector())
1145 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001146 if (! left->isVector())
1147 return false;
1148 op = EOpVectorTimesScalarAssign;
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00001149 setType(TType(basicType, higherPrecision, EvqTemporary, left->getNominalSize(), 1));
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001150 }
shannonwoods@chromium.orgb7dc4032013-05-30 00:18:18 +00001151 }
1152 else
1153 {
Jamie Madill075edd82013-07-08 13:30:19 -04001154 infoSink.info.message(EPrefixInternalError, getLine(), "Missing elses");
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001155 return false;
1156 }
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00001157
1158 if (!validateMultiplication(op, left->getType(), right->getType()))
1159 {
1160 return false;
1161 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001162 break;
alokp@chromium.org32cfaf42010-08-23 21:01:13 +00001163
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001164 case EOpAssign:
1165 case EOpInitialize:
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001166 case EOpAdd:
1167 case EOpSub:
1168 case EOpDiv:
1169 case EOpAddAssign:
1170 case EOpSubAssign:
1171 case EOpDivAssign:
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00001172 {
1173 if ((left->isMatrix() && right->isVector()) ||
1174 (left->isVector() && right->isMatrix()))
1175 return false;
1176
1177 // Are the sizes compatible?
1178 if (left->getNominalSize() != right->getNominalSize() || left->getSecondarySize() != right->getSecondarySize())
1179 {
1180 // If the nominal size of operands do not match:
1181 // One of them must be scalar.
1182 if (!left->isScalar() && !right->isScalar())
1183 return false;
1184
1185 // Operator cannot be of type pure assignment.
1186 if (op == EOpAssign || op == EOpInitialize)
1187 return false;
1188 }
1189
1190 const int secondarySize = std::max(left->getSecondarySize(), right->getSecondarySize());
1191
1192 setType(TType(basicType, higherPrecision, EvqTemporary, nominalSize, secondarySize));
1193 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001194 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001195
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001196 case EOpEqual:
1197 case EOpNotEqual:
1198 case EOpLessThan:
1199 case EOpGreaterThan:
1200 case EOpLessThanEqual:
1201 case EOpGreaterThanEqual:
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00001202 if ((left->getNominalSize() != right->getNominalSize()) ||
1203 (left->getSecondarySize() != right->getSecondarySize()))
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001204 return false;
daniel@transgaming.coma5d76232010-05-17 09:58:47 +00001205 setType(TType(EbtBool, EbpUndefined));
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001206 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001207
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001208 default:
1209 return false;
1210 }
alokp@chromium.org32cfaf42010-08-23 21:01:13 +00001211
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001212 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001213}
1214
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001215bool CompareStruct(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001216{
Jamie Madill98493dd2013-07-08 14:39:03 -04001217 const TFieldList& fields = leftNodeType.getStruct()->fields();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001218
Jamie Madill98493dd2013-07-08 14:39:03 -04001219 size_t structSize = fields.size();
Jamie Madill94bf7f22013-07-08 13:31:15 -04001220 size_t index = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001221
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001222 for (size_t j = 0; j < structSize; j++) {
Jamie Madill98493dd2013-07-08 14:39:03 -04001223 size_t size = fields[j]->type()->getObjectSize();
Jamie Madill94bf7f22013-07-08 13:31:15 -04001224 for (size_t i = 0; i < size; i++) {
Jamie Madill98493dd2013-07-08 14:39:03 -04001225 if (fields[j]->type()->getBasicType() == EbtStruct) {
1226 if (!CompareStructure(*fields[j]->type(), &rightUnionArray[index], &leftUnionArray[index]))
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001227 return false;
1228 } else {
1229 if (leftUnionArray[index] != rightUnionArray[index])
1230 return false;
1231 index++;
1232 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001233
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001234 }
1235 }
1236 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001237}
1238
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001239bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001240{
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001241 if (leftNodeType.isArray()) {
1242 TType typeWithoutArrayness = leftNodeType;
1243 typeWithoutArrayness.clearArrayness();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001244
Jamie Madill94bf7f22013-07-08 13:31:15 -04001245 size_t arraySize = leftNodeType.getArraySize();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001246
Jamie Madill94bf7f22013-07-08 13:31:15 -04001247 for (size_t i = 0; i < arraySize; ++i) {
1248 size_t offset = typeWithoutArrayness.getObjectSize() * i;
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001249 if (!CompareStruct(typeWithoutArrayness, &rightUnionArray[offset], &leftUnionArray[offset]))
1250 return false;
1251 }
1252 } else
1253 return CompareStruct(leftNodeType, rightUnionArray, leftUnionArray);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001254
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001255 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001256}
1257
1258//
1259// The fold functions see if an operation on a constant can be done in place,
1260// without generating run-time code.
1261//
1262// Returns the node to keep using, which may or may not be the node passed in.
1263//
1264
1265TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNode, TInfoSink& infoSink)
1266{
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001267 ConstantUnion *unionArray = getUnionArrayPointer();
Nicolas Capensbd0ea9c2014-03-04 13:53:29 -05001268
1269 if (!unionArray)
1270 return 0;
1271
Jamie Madill94bf7f22013-07-08 13:31:15 -04001272 size_t objectSize = getType().getObjectSize();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001273
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001274 if (constantNode)
1275 {
1276 // binary operations
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001277 TIntermConstantUnion *node = constantNode->getAsConstantUnion();
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001278 ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001279 TType returnType = getType();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001280
Nicolas Capensbd0ea9c2014-03-04 13:53:29 -05001281 if (!rightUnionArray)
1282 return 0;
1283
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001284 // for a case like float f = 1.2 + vec4(2,3,4,5);
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001285 if (constantNode->getType().getObjectSize() == 1 && objectSize > 1)
1286 {
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001287 rightUnionArray = new ConstantUnion[objectSize];
Jamie Madill94bf7f22013-07-08 13:31:15 -04001288 for (size_t i = 0; i < objectSize; ++i)
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001289 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001290 rightUnionArray[i] = *node->getUnionArrayPointer();
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001291 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001292 returnType = getType();
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001293 }
1294 else if (constantNode->getType().getObjectSize() > 1 && objectSize == 1)
1295 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001296 // for a case like float f = vec4(2,3,4,5) + 1.2;
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001297 unionArray = new ConstantUnion[constantNode->getType().getObjectSize()];
Jamie Madill94bf7f22013-07-08 13:31:15 -04001298 for (size_t i = 0; i < constantNode->getType().getObjectSize(); ++i)
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001299 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001300 unionArray[i] = *getUnionArrayPointer();
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001301 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001302 returnType = node->getType();
1303 objectSize = constantNode->getType().getObjectSize();
1304 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001305
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001306 ConstantUnion* tempConstArray = 0;
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001307 TIntermConstantUnion *tempNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001308
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001309 bool boolNodeFlag = false;
1310 switch(op) {
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001311 case EOpAdd:
1312 tempConstArray = new ConstantUnion[objectSize];
1313 {
Jamie Madill94bf7f22013-07-08 13:31:15 -04001314 for (size_t i = 0; i < objectSize; i++)
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001315 tempConstArray[i] = unionArray[i] + rightUnionArray[i];
1316 }
1317 break;
1318 case EOpSub:
1319 tempConstArray = new ConstantUnion[objectSize];
1320 {
Jamie Madill94bf7f22013-07-08 13:31:15 -04001321 for (size_t i = 0; i < objectSize; i++)
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001322 tempConstArray[i] = unionArray[i] - rightUnionArray[i];
1323 }
1324 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001325
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001326 case EOpMul:
1327 case EOpVectorTimesScalar:
1328 case EOpMatrixTimesScalar:
1329 tempConstArray = new ConstantUnion[objectSize];
1330 {
Jamie Madill94bf7f22013-07-08 13:31:15 -04001331 for (size_t i = 0; i < objectSize; i++)
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001332 tempConstArray[i] = unionArray[i] * rightUnionArray[i];
1333 }
1334 break;
1335
1336 case EOpMatrixTimesMatrix:
1337 {
1338 if (getType().getBasicType() != EbtFloat || node->getBasicType() != EbtFloat)
1339 {
Jamie Madill075edd82013-07-08 13:30:19 -04001340 infoSink.info.message(EPrefixInternalError, getLine(), "Constant Folding cannot be done for matrix multiply");
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001341 return 0;
1342 }
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001343
Shannon Woods3841b8e2013-09-10 18:23:12 -04001344 const int leftCols = getCols();
1345 const int leftRows = getRows();
1346 const int rightCols = constantNode->getType().getCols();
1347 const int rightRows = constantNode->getType().getRows();
1348 const int resultCols = rightCols;
1349 const int resultRows = leftRows;
shannonwoods@chromium.org50733332013-05-30 00:19:07 +00001350
1351 tempConstArray = new ConstantUnion[resultCols*resultRows];
1352 for (int row = 0; row < resultRows; row++)
1353 {
1354 for (int column = 0; column < resultCols; column++)
1355 {
1356 tempConstArray[resultRows * column + row].setFConst(0.0f);
1357 for (int i = 0; i < leftCols; i++)
1358 {
1359 tempConstArray[resultRows * column + row].setFConst(tempConstArray[resultRows * column + row].getFConst() + unionArray[i * leftRows + row].getFConst() * (rightUnionArray[column * rightRows + i].getFConst()));
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001360 }
1361 }
1362 }
shannonwoods@chromium.org50733332013-05-30 00:19:07 +00001363
1364 // update return type for matrix product
1365 returnType.setPrimarySize(resultCols);
1366 returnType.setSecondarySize(resultRows);
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001367 }
1368 break;
1369
1370 case EOpDiv:
1371 {
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001372 tempConstArray = new ConstantUnion[objectSize];
Jamie Madill94bf7f22013-07-08 13:31:15 -04001373 for (size_t i = 0; i < objectSize; i++)
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001374 {
1375 switch (getType().getBasicType())
1376 {
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +00001377 case EbtFloat:
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001378 if (rightUnionArray[i] == 0.0f)
1379 {
Jamie Madill075edd82013-07-08 13:30:19 -04001380 infoSink.info.message(EPrefixWarning, getLine(), "Divide by zero error during constant folding");
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001381 tempConstArray[i].setFConst(unionArray[i].getFConst() < 0 ? -FLT_MAX : FLT_MAX);
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001382 }
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001383 else
1384 {
1385 tempConstArray[i].setFConst(unionArray[i].getFConst() / rightUnionArray[i].getFConst());
1386 }
1387 break;
1388
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +00001389 case EbtInt:
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001390 if (rightUnionArray[i] == 0)
1391 {
Jamie Madill075edd82013-07-08 13:30:19 -04001392 infoSink.info.message(EPrefixWarning, getLine(), "Divide by zero error during constant folding");
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001393 tempConstArray[i].setIConst(INT_MAX);
1394 }
1395 else
1396 {
1397 tempConstArray[i].setIConst(unionArray[i].getIConst() / rightUnionArray[i].getIConst());
1398 }
1399 break;
1400
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +00001401 case EbtUInt:
1402 if (rightUnionArray[i] == 0)
1403 {
Jamie Madill075edd82013-07-08 13:30:19 -04001404 infoSink.info.message(EPrefixWarning, getLine(), "Divide by zero error during constant folding");
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +00001405 tempConstArray[i].setUConst(UINT_MAX);
1406 }
1407 else
1408 {
1409 tempConstArray[i].setUConst(unionArray[i].getUConst() / rightUnionArray[i].getUConst());
1410 }
1411 break;
1412
1413 default:
Jamie Madill075edd82013-07-08 13:30:19 -04001414 infoSink.info.message(EPrefixInternalError, getLine(), "Constant folding cannot be done for \"/\"");
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001415 return 0;
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001416 }
1417 }
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001418 }
1419 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001420
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001421 case EOpMatrixTimesVector:
1422 {
1423 if (node->getBasicType() != EbtFloat)
1424 {
Jamie Madill075edd82013-07-08 13:30:19 -04001425 infoSink.info.message(EPrefixInternalError, getLine(), "Constant Folding cannot be done for matrix times vector");
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001426 return 0;
1427 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001428
Shannon Woods3841b8e2013-09-10 18:23:12 -04001429 const int matrixCols = getCols();
1430 const int matrixRows = getRows();
shannonwoods@chromium.org50733332013-05-30 00:19:07 +00001431
1432 tempConstArray = new ConstantUnion[matrixRows];
1433
1434 for (int matrixRow = 0; matrixRow < matrixRows; matrixRow++)
1435 {
1436 tempConstArray[matrixRow].setFConst(0.0f);
1437 for (int col = 0; col < matrixCols; col++)
1438 {
1439 tempConstArray[matrixRow].setFConst(tempConstArray[matrixRow].getFConst() + ((unionArray[col * matrixRows + matrixRow].getFConst()) * rightUnionArray[col].getFConst()));
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001440 }
1441 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001442
shannonwoods@chromium.org50733332013-05-30 00:19:07 +00001443 returnType = node->getType();
1444 returnType.setPrimarySize(matrixRows);
1445
1446 tempNode = new TIntermConstantUnion(tempConstArray, returnType);
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001447 tempNode->setLine(getLine());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001448
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001449 return tempNode;
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001450 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001451
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001452 case EOpVectorTimesMatrix:
1453 {
1454 if (getType().getBasicType() != EbtFloat)
1455 {
Jamie Madill075edd82013-07-08 13:30:19 -04001456 infoSink.info.message(EPrefixInternalError, getLine(), "Constant Folding cannot be done for vector times matrix");
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001457 return 0;
1458 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001459
Shannon Woods3841b8e2013-09-10 18:23:12 -04001460 const int matrixCols = constantNode->getType().getCols();
1461 const int matrixRows = constantNode->getType().getRows();
shannonwoods@chromium.org50733332013-05-30 00:19:07 +00001462
1463 tempConstArray = new ConstantUnion[matrixCols];
1464
1465 for (int matrixCol = 0; matrixCol < matrixCols; matrixCol++)
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001466 {
shannonwoods@chromium.org50733332013-05-30 00:19:07 +00001467 tempConstArray[matrixCol].setFConst(0.0f);
1468 for (int matrixRow = 0; matrixRow < matrixRows; matrixRow++)
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001469 {
shannonwoods@chromium.org50733332013-05-30 00:19:07 +00001470 tempConstArray[matrixCol].setFConst(tempConstArray[matrixCol].getFConst() + ((unionArray[matrixRow].getFConst()) * rightUnionArray[matrixCol * matrixRows + matrixRow].getFConst()));
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001471 }
1472 }
shannonwoods@chromium.org50733332013-05-30 00:19:07 +00001473
1474 returnType.setPrimarySize(matrixCols);
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001475 }
1476 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001477
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001478 case EOpLogicalAnd: // this code is written for possible future use, will not get executed currently
1479 {
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001480 tempConstArray = new ConstantUnion[objectSize];
Jamie Madill94bf7f22013-07-08 13:31:15 -04001481 for (size_t i = 0; i < objectSize; i++)
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001482 {
1483 tempConstArray[i] = unionArray[i] && rightUnionArray[i];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001484 }
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001485 }
1486 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001487
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001488 case EOpLogicalOr: // this code is written for possible future use, will not get executed currently
1489 {
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001490 tempConstArray = new ConstantUnion[objectSize];
Jamie Madill94bf7f22013-07-08 13:31:15 -04001491 for (size_t i = 0; i < objectSize; i++)
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001492 {
1493 tempConstArray[i] = unionArray[i] || rightUnionArray[i];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001494 }
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001495 }
1496 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001497
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001498 case EOpLogicalXor:
1499 {
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001500 tempConstArray = new ConstantUnion[objectSize];
Jamie Madill94bf7f22013-07-08 13:31:15 -04001501 for (size_t i = 0; i < objectSize; i++)
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001502 {
1503 switch (getType().getBasicType())
1504 {
1505 case EbtBool:
1506 tempConstArray[i].setBConst((unionArray[i] == rightUnionArray[i]) ? false : true);
1507 break;
1508 default:
1509 UNREACHABLE();
1510 break;
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001511 }
1512 }
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001513 }
1514 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001515
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001516 case EOpLessThan:
1517 assert(objectSize == 1);
1518 tempConstArray = new ConstantUnion[1];
1519 tempConstArray->setBConst(*unionArray < *rightUnionArray);
1520 returnType = TType(EbtBool, EbpUndefined, EvqConst);
1521 break;
1522
1523 case EOpGreaterThan:
1524 assert(objectSize == 1);
1525 tempConstArray = new ConstantUnion[1];
1526 tempConstArray->setBConst(*unionArray > *rightUnionArray);
1527 returnType = TType(EbtBool, EbpUndefined, EvqConst);
1528 break;
1529
1530 case EOpLessThanEqual:
1531 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001532 assert(objectSize == 1);
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001533 ConstantUnion constant;
1534 constant.setBConst(*unionArray > *rightUnionArray);
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001535 tempConstArray = new ConstantUnion[1];
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001536 tempConstArray->setBConst(!constant.getBConst());
daniel@transgaming.coma5d76232010-05-17 09:58:47 +00001537 returnType = TType(EbtBool, EbpUndefined, EvqConst);
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001538 break;
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001539 }
1540
1541 case EOpGreaterThanEqual:
1542 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001543 assert(objectSize == 1);
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001544 ConstantUnion constant;
1545 constant.setBConst(*unionArray < *rightUnionArray);
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001546 tempConstArray = new ConstantUnion[1];
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001547 tempConstArray->setBConst(!constant.getBConst());
daniel@transgaming.coma5d76232010-05-17 09:58:47 +00001548 returnType = TType(EbtBool, EbpUndefined, EvqConst);
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001549 break;
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001550 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001551
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001552 case EOpEqual:
1553 if (getType().getBasicType() == EbtStruct)
1554 {
1555 if (!CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray))
1556 boolNodeFlag = true;
1557 }
1558 else
1559 {
Jamie Madill94bf7f22013-07-08 13:31:15 -04001560 for (size_t i = 0; i < objectSize; i++)
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001561 {
1562 if (unionArray[i] != rightUnionArray[i])
1563 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001564 boolNodeFlag = true;
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001565 break; // break out of for loop
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001566 }
1567 }
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001568 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001569
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001570 tempConstArray = new ConstantUnion[1];
1571 if (!boolNodeFlag)
1572 {
1573 tempConstArray->setBConst(true);
1574 }
1575 else
1576 {
1577 tempConstArray->setBConst(false);
1578 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001579
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001580 tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConst));
1581 tempNode->setLine(getLine());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001582
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001583 return tempNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001584
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001585 case EOpNotEqual:
1586 if (getType().getBasicType() == EbtStruct)
1587 {
1588 if (CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray))
1589 boolNodeFlag = true;
1590 }
1591 else
1592 {
Jamie Madill94bf7f22013-07-08 13:31:15 -04001593 for (size_t i = 0; i < objectSize; i++)
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001594 {
1595 if (unionArray[i] == rightUnionArray[i])
1596 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001597 boolNodeFlag = true;
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001598 break; // break out of for loop
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001599 }
1600 }
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001601 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001602
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001603 tempConstArray = new ConstantUnion[1];
1604 if (!boolNodeFlag)
1605 {
1606 tempConstArray->setBConst(true);
1607 }
1608 else
1609 {
1610 tempConstArray->setBConst(false);
1611 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001612
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001613 tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConst));
1614 tempNode->setLine(getLine());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001615
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001616 return tempNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001617
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001618 default:
Jamie Madill075edd82013-07-08 13:30:19 -04001619 infoSink.info.message(EPrefixInternalError, getLine(), "Invalid operator for constant folding");
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001620 return 0;
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001621 }
1622 tempNode = new TIntermConstantUnion(tempConstArray, returnType);
1623 tempNode->setLine(getLine());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001624
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001625 return tempNode;
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001626 }
1627 else
1628 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001629 //
1630 // Do unary operations
1631 //
1632 TIntermConstantUnion *newNode = 0;
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001633 ConstantUnion* tempConstArray = new ConstantUnion[objectSize];
Jamie Madill94bf7f22013-07-08 13:31:15 -04001634 for (size_t i = 0; i < objectSize; i++)
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001635 {
1636 switch(op)
1637 {
1638 case EOpNegative:
1639 switch (getType().getBasicType())
1640 {
Nicolas Capensc0f7c612013-06-05 11:46:09 -04001641 case EbtFloat: tempConstArray[i].setFConst(-unionArray[i].getFConst()); break;
1642 case EbtInt: tempConstArray[i].setIConst(-unionArray[i].getIConst()); break;
1643 case EbtUInt: tempConstArray[i].setUConst(static_cast<unsigned int>(-static_cast<int>(unionArray[i].getUConst()))); break;
1644 default:
Jamie Madill075edd82013-07-08 13:30:19 -04001645 infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
Nicolas Capensc0f7c612013-06-05 11:46:09 -04001646 return 0;
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001647 }
1648 break;
1649
1650 case EOpLogicalNot: // this code is written for possible future use, will not get executed currently
1651 switch (getType().getBasicType())
1652 {
Nicolas Capensc0f7c612013-06-05 11:46:09 -04001653 case EbtBool: tempConstArray[i].setBConst(!unionArray[i].getBConst()); break;
1654 default:
Jamie Madill075edd82013-07-08 13:30:19 -04001655 infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
Nicolas Capensc0f7c612013-06-05 11:46:09 -04001656 return 0;
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001657 }
1658 break;
1659
1660 default:
1661 return 0;
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001662 }
1663 }
1664 newNode = new TIntermConstantUnion(tempConstArray, getType());
1665 newNode->setLine(getLine());
1666 return newNode;
1667 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001668}
1669
1670TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermConstantUnion* node)
1671{
Jamie Madill94bf7f22013-07-08 13:31:15 -04001672 size_t size = node->getType().getObjectSize();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001673
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001674 ConstantUnion *leftUnionArray = new ConstantUnion[size];
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001675
Jamie Madill94bf7f22013-07-08 13:31:15 -04001676 for (size_t i=0; i < size; i++) {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001677
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001678 switch (promoteTo) {
1679 case EbtFloat:
1680 switch (node->getType().getBasicType()) {
1681 case EbtInt:
shannon.woods%transgaming.com@gtempaccount.com812c3f12013-04-13 03:30:01 +00001682 leftUnionArray[i].setFConst(static_cast<float>(node->getIConst(i)));
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001683 break;
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +00001684 case EbtUInt:
1685 leftUnionArray[i].setFConst(static_cast<float>(node->getUConst(i)));
1686 break;
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001687 case EbtBool:
shannon.woods%transgaming.com@gtempaccount.com812c3f12013-04-13 03:30:01 +00001688 leftUnionArray[i].setFConst(static_cast<float>(node->getBConst(i)));
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001689 break;
1690 case EbtFloat:
shannon.woods%transgaming.com@gtempaccount.com812c3f12013-04-13 03:30:01 +00001691 leftUnionArray[i].setFConst(static_cast<float>(node->getFConst(i)));
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001692 break;
1693 default:
Jamie Madill075edd82013-07-08 13:30:19 -04001694 infoSink.info.message(EPrefixInternalError, node->getLine(), "Cannot promote");
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001695 return 0;
1696 }
1697 break;
1698 case EbtInt:
1699 switch (node->getType().getBasicType()) {
1700 case EbtInt:
shannon.woods%transgaming.com@gtempaccount.com812c3f12013-04-13 03:30:01 +00001701 leftUnionArray[i].setIConst(static_cast<int>(node->getIConst(i)));
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001702 break;
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +00001703 case EbtUInt:
1704 leftUnionArray[i].setIConst(static_cast<int>(node->getUConst(i)));
1705 break;
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001706 case EbtBool:
shannon.woods%transgaming.com@gtempaccount.com812c3f12013-04-13 03:30:01 +00001707 leftUnionArray[i].setIConst(static_cast<int>(node->getBConst(i)));
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001708 break;
1709 case EbtFloat:
shannon.woods%transgaming.com@gtempaccount.com812c3f12013-04-13 03:30:01 +00001710 leftUnionArray[i].setIConst(static_cast<int>(node->getFConst(i)));
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001711 break;
1712 default:
Jamie Madill075edd82013-07-08 13:30:19 -04001713 infoSink.info.message(EPrefixInternalError, node->getLine(), "Cannot promote");
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001714 return 0;
1715 }
1716 break;
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +00001717 case EbtUInt:
1718 switch (node->getType().getBasicType()) {
1719 case EbtInt:
1720 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getIConst(i)));
1721 break;
1722 case EbtUInt:
1723 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getUConst(i)));
1724 break;
1725 case EbtBool:
1726 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getBConst(i)));
1727 break;
1728 case EbtFloat:
1729 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getFConst(i)));
1730 break;
1731 default:
Jamie Madill075edd82013-07-08 13:30:19 -04001732 infoSink.info.message(EPrefixInternalError, node->getLine(), "Cannot promote");
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +00001733 return 0;
1734 }
1735 break;
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001736 case EbtBool:
1737 switch (node->getType().getBasicType()) {
1738 case EbtInt:
shannon.woods%transgaming.com@gtempaccount.com812c3f12013-04-13 03:30:01 +00001739 leftUnionArray[i].setBConst(node->getIConst(i) != 0);
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001740 break;
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +00001741 case EbtUInt:
1742 leftUnionArray[i].setBConst(node->getUConst(i) != 0);
1743 break;
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001744 case EbtBool:
shannon.woods%transgaming.com@gtempaccount.com812c3f12013-04-13 03:30:01 +00001745 leftUnionArray[i].setBConst(node->getBConst(i));
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001746 break;
1747 case EbtFloat:
shannon.woods%transgaming.com@gtempaccount.com812c3f12013-04-13 03:30:01 +00001748 leftUnionArray[i].setBConst(node->getFConst(i) != 0.0f);
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001749 break;
1750 default:
Jamie Madill075edd82013-07-08 13:30:19 -04001751 infoSink.info.message(EPrefixInternalError, node->getLine(), "Cannot promote");
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001752 return 0;
1753 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001754
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001755 break;
1756 default:
Jamie Madill075edd82013-07-08 13:30:19 -04001757 infoSink.info.message(EPrefixInternalError, node->getLine(), "Incorrect data type found");
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001758 return 0;
1759 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001760
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001761 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001762
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001763 const TType& t = node->getType();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001764
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00001765 return addConstantUnion(leftUnionArray, TType(promoteTo, t.getPrecision(), t.getQualifier(), t.getNominalSize(), t.getSecondarySize(), t.isArray()), node->getLine());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001766}
1767
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +00001768// static
1769TString TIntermTraverser::hash(const TString& name, ShHashFunction64 hashFunction)
1770{
1771 if (hashFunction == NULL || name.empty())
1772 return name;
1773 khronos_uint64_t number = (*hashFunction)(name.c_str(), name.length());
1774 TStringStream stream;
1775 stream << HASHED_NAME_PREFIX << std::hex << number;
1776 TString hashedName = stream.str();
1777 return hashedName;
1778}