blob: bec0e29b79996836be663ec99e891e7f40e61441 [file] [log] [blame]
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001//
shannon.woods%transgaming.com@gtempaccount.comc0d0c222013-04-13 03:29:36 +00002// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7//
8// 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
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000191 //
192 // First try converting the children to compatible types.
193 //
alokp@chromium.org8f0f24a2010-09-01 21:06:24 +0000194 if (left->getType().getStruct() && right->getType().getStruct()) {
195 if (left->getType() != right->getType())
196 return 0;
197 } else {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000198 TIntermTyped* child = addConversion(op, left->getType(), right);
199 if (child)
200 right = child;
201 else {
202 child = addConversion(op, right->getType(), left);
203 if (child)
204 left = child;
205 else
206 return 0;
207 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000208 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000209
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000210 //
211 // Need a new node holding things together then. Make
212 // one and promote it to the right type.
213 //
214 TIntermBinary* node = new TIntermBinary(op);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000215 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000216
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000217 node->setLeft(left);
218 node->setRight(right);
alokp@chromium.org8f0f24a2010-09-01 21:06:24 +0000219 if (!node->promote(infoSink))
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000220 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000221
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000222 //
223 // See if we can fold constants.
224 //
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000225 TIntermTyped* typedReturnNode = 0;
alokp@chromium.org8f0f24a2010-09-01 21:06:24 +0000226 TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion();
227 TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion();
228 if (leftTempConstant && rightTempConstant) {
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000229 typedReturnNode = leftTempConstant->fold(node->getOp(), rightTempConstant, infoSink);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000230
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000231 if (typedReturnNode)
232 return typedReturnNode;
233 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000234
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000235 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000236}
237
238//
239// Connect two nodes through an assignment.
240//
241// Returns the added node.
242//
Jamie Madill075edd82013-07-08 13:30:19 -0400243TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc& line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000244{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000245 //
246 // Like adding binary math, except the conversion can only go
247 // from right to left.
248 //
249 TIntermBinary* node = new TIntermBinary(op);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000250 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000251
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000252 TIntermTyped* child = addConversion(op, left->getType(), right);
253 if (child == 0)
254 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000255
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000256 node->setLeft(left);
257 node->setRight(child);
258 if (! node->promote(infoSink))
259 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000260
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000261 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000262}
263
264//
265// Connect two nodes through an index operator, where the left node is the base
266// of an array or struct, and the right node is a direct or indirect offset.
267//
268// Returns the added node.
269// The caller should set the type of the returned node.
270//
Jamie Madill075edd82013-07-08 13:30:19 -0400271TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, const TSourceLoc& line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000272{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000273 TIntermBinary* node = new TIntermBinary(op);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000274 node->setLine(line);
275 node->setLeft(base);
276 node->setRight(index);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000277
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000278 // caller should set the type
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000279
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000280 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000281}
282
283//
284// Add one node as the parent of another that it operates on.
285//
286// Returns the added node.
287//
Jamie Madill075edd82013-07-08 13:30:19 -0400288TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode, const TSourceLoc& line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000289{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000290 TIntermUnary* node;
291 TIntermTyped* child = childNode->getAsTyped();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000292
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000293 if (child == 0) {
Jamie Madill075edd82013-07-08 13:30:19 -0400294 infoSink.info.message(EPrefixInternalError, line, "Bad type in AddUnaryMath");
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000295 return 0;
296 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000297
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000298 switch (op) {
299 case EOpLogicalNot:
300 if (child->getType().getBasicType() != EbtBool || child->getType().isMatrix() || child->getType().isArray() || child->getType().isVector()) {
301 return 0;
302 }
303 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000304
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000305 case EOpPostIncrement:
306 case EOpPreIncrement:
307 case EOpPostDecrement:
308 case EOpPreDecrement:
309 case EOpNegative:
310 if (child->getType().getBasicType() == EbtStruct || child->getType().isArray())
311 return 0;
312 default: break;
313 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000314
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000315 //
316 // Do we need to promote the operand?
317 //
318 // Note: Implicit promotions were removed from the language.
319 //
320 TBasicType newType = EbtVoid;
321 switch (op) {
322 case EOpConstructInt: newType = EbtInt; break;
Nicolas Capensab60b932013-06-05 10:31:21 -0400323 case EOpConstructUInt: newType = EbtUInt; break;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000324 case EOpConstructBool: newType = EbtBool; break;
325 case EOpConstructFloat: newType = EbtFloat; break;
326 default: break;
327 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000328
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000329 if (newType != EbtVoid) {
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000330 child = addConversion(op, TType(newType, child->getPrecision(), EvqTemporary,
331 child->getNominalSize(),
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +0000332 child->getSecondarySize(),
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000333 child->isArray()),
334 child);
335 if (child == 0)
336 return 0;
337 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000338
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000339 //
340 // For constructors, we are now done, it's all in the conversion.
341 //
342 switch (op) {
343 case EOpConstructInt:
Nicolas Capensab60b932013-06-05 10:31:21 -0400344 case EOpConstructUInt:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000345 case EOpConstructBool:
346 case EOpConstructFloat:
347 return child;
348 default: break;
349 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000350
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000351 TIntermConstantUnion *childTempConstant = 0;
352 if (child->getAsConstantUnion())
353 childTempConstant = child->getAsConstantUnion();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000354
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000355 //
356 // Make a new node for the operator.
357 //
358 node = new TIntermUnary(op);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000359 node->setLine(line);
360 node->setOperand(child);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000361
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000362 if (! node->promote(infoSink))
363 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000364
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000365 if (childTempConstant) {
366 TIntermTyped* newChild = childTempConstant->fold(op, 0, infoSink);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000367
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000368 if (newChild)
369 return newChild;
370 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000371
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000372 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000373}
374
375//
376// This is the safe way to change the operator on an aggregate, as it
377// does lots of error checking and fixing. Especially for establishing
378// a function call's operation on it's set of parameters. Sequences
379// of instructions are also aggregates, but they just direnctly set
380// their operator to EOpSequence.
381//
382// Returns an aggregate node, which could be the one passed in if
daniel@transgaming.com978702d2012-04-04 15:05:58 +0000383// it was already an aggregate but no operator was set.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000384//
Jamie Madill075edd82013-07-08 13:30:19 -0400385TIntermAggregate* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator op, const TSourceLoc& line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000386{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000387 TIntermAggregate* aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000388
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000389 //
390 // Make sure we have an aggregate. If not turn it into one.
391 //
392 if (node) {
393 aggNode = node->getAsAggregate();
394 if (aggNode == 0 || aggNode->getOp() != EOpNull) {
395 //
396 // Make an aggregate containing this node.
397 //
398 aggNode = new TIntermAggregate();
399 aggNode->getSequence().push_back(node);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000400 }
401 } else
402 aggNode = new TIntermAggregate();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000403
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000404 //
405 // Set the operator.
406 //
alokp@chromium.org58e54292010-08-24 21:40:03 +0000407 aggNode->setOp(op);
Jamie Madill075edd82013-07-08 13:30:19 -0400408 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000409
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000410 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000411}
412
413//
414// Convert one type to another.
415//
416// Returns the node representing the conversion, which could be the same
417// node passed in if no conversion was needed.
418//
419// Return 0 if a conversion can't be done.
420//
421TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TIntermTyped* node)
422{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000423 //
424 // Does the base type allow operation?
425 //
Nicolas Capens344e7142013-06-24 15:39:21 -0400426 if (node->getBasicType() == EbtVoid ||
427 IsSampler(node->getBasicType()))
428 {
429 return 0;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000430 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000431
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000432 //
433 // Otherwise, if types are identical, no problem
434 //
435 if (type == node->getType())
436 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000437
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000438 //
439 // If one's a structure, then no conversions.
440 //
441 if (type.getStruct() || node->getType().getStruct())
442 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000443
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000444 //
445 // If one's an array, then no conversions.
446 //
447 if (type.isArray() || node->getType().isArray())
448 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000449
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000450 TBasicType promoteTo;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000451
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000452 switch (op) {
453 //
454 // Explicit conversions
455 //
456 case EOpConstructBool:
457 promoteTo = EbtBool;
458 break;
459 case EOpConstructFloat:
460 promoteTo = EbtFloat;
461 break;
462 case EOpConstructInt:
463 promoteTo = EbtInt;
464 break;
Nicolas Capensab60b932013-06-05 10:31:21 -0400465 case EOpConstructUInt:
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000466 promoteTo = EbtUInt;
467 break;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000468 default:
469 //
470 // implicit conversions were removed from the language.
471 //
472 if (type.getBasicType() != node->getType().getBasicType())
473 return 0;
474 //
475 // Size and structure could still differ, but that's
476 // handled by operator promotion.
477 //
478 return node;
479 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000480
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000481 if (node->getAsConstantUnion()) {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000482
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000483 return (promoteConstantUnion(promoteTo, node->getAsConstantUnion()));
484 } else {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000485
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000486 //
487 // Add a new newNode for the conversion.
488 //
489 TIntermUnary* newNode = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000490
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000491 TOperator newOp = EOpNull;
492 switch (promoteTo) {
493 case EbtFloat:
494 switch (node->getBasicType()) {
Nicolas Capensab60b932013-06-05 10:31:21 -0400495 case EbtInt: newOp = EOpConvIntToFloat; break;
496 case EbtUInt: newOp = EOpConvFloatToUInt; break;
497 case EbtBool: newOp = EOpConvBoolToFloat; break;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000498 default:
Jamie Madill075edd82013-07-08 13:30:19 -0400499 infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion node");
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000500 return 0;
501 }
502 break;
503 case EbtBool:
504 switch (node->getBasicType()) {
Nicolas Capensab60b932013-06-05 10:31:21 -0400505 case EbtInt: newOp = EOpConvIntToBool; break;
506 case EbtUInt: newOp = EOpConvBoolToUInt; break;
507 case EbtFloat: newOp = EOpConvFloatToBool; break;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000508 default:
Jamie Madill075edd82013-07-08 13:30:19 -0400509 infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion node");
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000510 return 0;
511 }
512 break;
513 case EbtInt:
514 switch (node->getBasicType()) {
Nicolas Capensab60b932013-06-05 10:31:21 -0400515 case EbtUInt: newOp = EOpConvUIntToInt; break;
516 case EbtBool: newOp = EOpConvBoolToInt; break;
517 case EbtFloat: newOp = EOpConvFloatToInt; break;
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000518 default:
Jamie Madill075edd82013-07-08 13:30:19 -0400519 infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion node");
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +0000520 return 0;
521 }
522 break;
523 case EbtUInt:
524 switch (node->getBasicType()) {
Nicolas Capensab60b932013-06-05 10:31:21 -0400525 case EbtInt: newOp = EOpConvIntToUInt; break;
526 case EbtBool: newOp = EOpConvBoolToUInt; break;
527 case EbtFloat: newOp = EOpConvFloatToUInt; break;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000528 default:
Jamie Madill075edd82013-07-08 13:30:19 -0400529 infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion node");
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000530 return 0;
531 }
532 break;
533 default:
Jamie Madill075edd82013-07-08 13:30:19 -0400534 infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion type");
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000535 return 0;
536 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000537
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +0000538 TType type(promoteTo, node->getPrecision(), EvqTemporary, node->getNominalSize(), node->getSecondarySize(), node->isArray());
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000539 newNode = new TIntermUnary(newOp, type);
540 newNode->setLine(node->getLine());
541 newNode->setOperand(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000542
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000543 return newNode;
544 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000545}
546
547//
548// Safe way to combine two nodes into an aggregate. Works with null pointers,
549// a node that's not a aggregate yet, etc.
550//
551// Returns the resulting aggregate, unless 0 was passed in for
552// both existing nodes.
553//
Jamie Madill075edd82013-07-08 13:30:19 -0400554TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc& line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000555{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000556 if (left == 0 && right == 0)
557 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000558
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000559 TIntermAggregate* aggNode = 0;
560 if (left)
561 aggNode = left->getAsAggregate();
562 if (!aggNode || aggNode->getOp() != EOpNull) {
563 aggNode = new TIntermAggregate;
564 if (left)
565 aggNode->getSequence().push_back(left);
566 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000567
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000568 if (right)
569 aggNode->getSequence().push_back(right);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000570
Jamie Madill075edd82013-07-08 13:30:19 -0400571 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000572
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000573 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000574}
575
576//
577// Turn an existing node into an aggregate.
578//
579// Returns an aggregate, unless 0 was passed in for the existing node.
580//
Jamie Madill075edd82013-07-08 13:30:19 -0400581TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, const TSourceLoc& line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000582{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000583 if (node == 0)
584 return 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000585
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000586 TIntermAggregate* aggNode = new TIntermAggregate;
587 aggNode->getSequence().push_back(node);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000588
Jamie Madill075edd82013-07-08 13:30:19 -0400589 aggNode->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000590
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000591 return aggNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000592}
593
594//
595// For "if" test nodes. There are three children; a condition,
596// a true path, and a false path. The two paths are in the
597// nodePair.
598//
599// Returns the selection node created.
600//
Jamie Madill075edd82013-07-08 13:30:19 -0400601TIntermNode* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nodePair, const TSourceLoc& line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000602{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000603 //
604 // For compile time constant selections, prune the code and
605 // test now.
606 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000607
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000608 if (cond->getAsTyped() && cond->getAsTyped()->getAsConstantUnion()) {
shannon.woods%transgaming.com@gtempaccount.comc0d0c222013-04-13 03:29:36 +0000609 if (cond->getAsConstantUnion()->getBConst(0) == true)
daniel@transgaming.com978702d2012-04-04 15:05:58 +0000610 return nodePair.node1 ? setAggregateOperator(nodePair.node1, EOpSequence, nodePair.node1->getLine()) : NULL;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000611 else
daniel@transgaming.com978702d2012-04-04 15:05:58 +0000612 return nodePair.node2 ? setAggregateOperator(nodePair.node2, EOpSequence, nodePair.node2->getLine()) : NULL;
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000613 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000614
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000615 TIntermSelection* node = new TIntermSelection(cond, nodePair.node1, nodePair.node2);
616 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000617
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000618 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000619}
620
621
Jamie Madill075edd82013-07-08 13:30:19 -0400622TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc& line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000623{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000624 if (left->getType().getQualifier() == EvqConst && right->getType().getQualifier() == EvqConst) {
625 return right;
626 } else {
627 TIntermTyped *commaAggregate = growAggregate(left, right, line);
alokp@chromium.org58e54292010-08-24 21:40:03 +0000628 commaAggregate->getAsAggregate()->setOp(EOpComma);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000629 commaAggregate->setType(right->getType());
alokp@chromium.org58e54292010-08-24 21:40:03 +0000630 commaAggregate->getTypePointer()->setQualifier(EvqTemporary);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000631 return commaAggregate;
632 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000633}
634
635//
636// For "?:" test nodes. There are three children; a condition,
637// a true path, and a false path. The two paths are specified
638// as separate parameters.
639//
640// Returns the selection node created, or 0 if one could not be.
641//
Jamie Madill075edd82013-07-08 13:30:19 -0400642TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc& line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000643{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000644 //
645 // Get compatible types.
646 //
647 TIntermTyped* child = addConversion(EOpSequence, trueBlock->getType(), falseBlock);
648 if (child)
649 falseBlock = child;
650 else {
651 child = addConversion(EOpSequence, falseBlock->getType(), trueBlock);
652 if (child)
653 trueBlock = child;
654 else
655 return 0;
656 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000657
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000658 //
659 // See if all the operands are constant, then fold it otherwise not.
660 //
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000661
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000662 if (cond->getAsConstantUnion() && trueBlock->getAsConstantUnion() && falseBlock->getAsConstantUnion()) {
shannon.woods%transgaming.com@gtempaccount.comc0d0c222013-04-13 03:29:36 +0000663 if (cond->getAsConstantUnion()->getBConst(0))
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000664 return trueBlock;
665 else
666 return falseBlock;
667 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000668
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000669 //
670 // Make a selection node.
671 //
672 TIntermSelection* node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType());
daniel@transgaming.com43affc52012-03-28 14:55:39 +0000673 node->getTypePointer()->setQualifier(EvqTemporary);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000674 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000675
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000676 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000677}
678
679//
680// Constant terminal nodes. Has a union that contains bool, float or int constants
681//
682// Returns the constant union node created.
683//
684
Jamie Madill075edd82013-07-08 13:30:19 -0400685TIntermConstantUnion* TIntermediate::addConstantUnion(ConstantUnion* unionArrayPointer, const TType& t, const TSourceLoc& line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000686{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000687 TIntermConstantUnion* node = new TIntermConstantUnion(unionArrayPointer, t);
688 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000689
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000690 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000691}
692
Jamie Madill075edd82013-07-08 13:30:19 -0400693TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, const TSourceLoc& line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000694{
695
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000696 TIntermAggregate* node = new TIntermAggregate(EOpSequence);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000697
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000698 node->setLine(line);
699 TIntermConstantUnion* constIntNode;
700 TIntermSequence &sequenceVector = node->getSequence();
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000701 ConstantUnion* unionArray;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000702
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000703 for (int i = 0; i < fields.num; i++) {
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +0000704 unionArray = new ConstantUnion[1];
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000705 unionArray->setIConst(fields.offsets[i]);
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000706 constIntNode = addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), line);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000707 sequenceVector.push_back(constIntNode);
708 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000709
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000710 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000711}
712
713//
714// Create loop nodes.
715//
Jamie Madill075edd82013-07-08 13:30:19 -0400716TIntermNode* TIntermediate::addLoop(TLoopType type, TIntermNode* init, TIntermTyped* cond, TIntermTyped* expr, TIntermNode* body, const TSourceLoc& line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000717{
alokp@chromium.org52813552010-11-16 18:36:09 +0000718 TIntermNode* node = new TIntermLoop(type, init, cond, expr, body);
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000719 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000720
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000721 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000722}
723
724//
725// Add branches.
726//
Jamie Madill075edd82013-07-08 13:30:19 -0400727TIntermBranch* TIntermediate::addBranch(TOperator branchOp, const TSourceLoc& line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000728{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000729 return addBranch(branchOp, 0, line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000730}
731
Jamie Madill075edd82013-07-08 13:30:19 -0400732TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expression, const TSourceLoc& line)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000733{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000734 TIntermBranch* node = new TIntermBranch(branchOp, expression);
735 node->setLine(line);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000736
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000737 return node;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000738}
739
740//
741// This is to be executed once the final root is put on top by the parsing
742// process.
743//
alokp@chromium.org07620a52010-09-23 17:53:56 +0000744bool TIntermediate::postProcess(TIntermNode* root)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000745{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000746 if (root == 0)
747 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000748
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000749 //
750 // First, finish off the top level sequence, if any
751 //
752 TIntermAggregate* aggRoot = root->getAsAggregate();
753 if (aggRoot && aggRoot->getOp() == EOpNull)
alokp@chromium.org58e54292010-08-24 21:40:03 +0000754 aggRoot->setOp(EOpSequence);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000755
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000756 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000757}
758
759//
760// This deletes the tree.
761//
762void TIntermediate::remove(TIntermNode* root)
763{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000764 if (root)
765 RemoveAllTreeNodes(root);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000766}
767
768////////////////////////////////////////////////////////////////
769//
770// Member functions of the nodes used for building the tree.
771//
772////////////////////////////////////////////////////////////////
773
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700774#define REPLACE_IF_IS(node, type, original, replacement) \
775 if (node == original) { \
776 node = static_cast<type *>(replacement); \
777 return true; \
778 }
779
780bool TIntermLoop::replaceChildNode(
781 TIntermNode *original, TIntermNode *replacement)
782{
783 REPLACE_IF_IS(init, TIntermNode, original, replacement);
784 REPLACE_IF_IS(cond, TIntermTyped, original, replacement);
785 REPLACE_IF_IS(expr, TIntermTyped, original, replacement);
786 REPLACE_IF_IS(body, TIntermNode, original, replacement);
787 return false;
788}
789
790bool TIntermBranch::replaceChildNode(
791 TIntermNode *original, TIntermNode *replacement)
792{
793 REPLACE_IF_IS(expression, TIntermTyped, original, replacement);
794 return false;
795}
796
797bool TIntermBinary::replaceChildNode(
798 TIntermNode *original, TIntermNode *replacement)
799{
800 REPLACE_IF_IS(left, TIntermTyped, original, replacement);
801 REPLACE_IF_IS(right, TIntermTyped, original, replacement);
802 return false;
803}
804
805bool TIntermUnary::replaceChildNode(
806 TIntermNode *original, TIntermNode *replacement)
807{
808 REPLACE_IF_IS(operand, TIntermTyped, original, replacement);
809 return false;
810}
811
812bool TIntermAggregate::replaceChildNode(
813 TIntermNode *original, TIntermNode *replacement)
814{
815 for (size_t ii = 0; ii < sequence.size(); ++ii)
816 {
817 REPLACE_IF_IS(sequence[ii], TIntermNode, original, replacement);
818 }
819 return false;
820}
821
822bool TIntermSelection::replaceChildNode(
823 TIntermNode *original, TIntermNode *replacement)
824{
825 REPLACE_IF_IS(condition, TIntermTyped, original, replacement);
826 REPLACE_IF_IS(trueBlock, TIntermNode, original, replacement);
827 REPLACE_IF_IS(falseBlock, TIntermNode, original, replacement);
828 return false;
829}
830
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000831//
832// Say whether or not an operation node changes the value of a variable.
833//
Jamie Madillf4b79ba2013-11-26 10:38:18 -0500834bool TIntermOperator::isAssignment() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000835{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000836 switch (op) {
837 case EOpPostIncrement:
838 case EOpPostDecrement:
839 case EOpPreIncrement:
840 case EOpPreDecrement:
841 case EOpAssign:
842 case EOpAddAssign:
843 case EOpSubAssign:
844 case EOpMulAssign:
845 case EOpVectorTimesMatrixAssign:
846 case EOpVectorTimesScalarAssign:
847 case EOpMatrixTimesScalarAssign:
848 case EOpMatrixTimesMatrixAssign:
849 case EOpDivAssign:
850 return true;
851 default:
852 return false;
853 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000854}
855
856//
857// returns true if the operator is for one of the constructors
858//
859bool TIntermOperator::isConstructor() const
860{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000861 switch (op) {
862 case EOpConstructVec2:
863 case EOpConstructVec3:
864 case EOpConstructVec4:
865 case EOpConstructMat2:
866 case EOpConstructMat3:
867 case EOpConstructMat4:
868 case EOpConstructFloat:
869 case EOpConstructIVec2:
870 case EOpConstructIVec3:
871 case EOpConstructIVec4:
872 case EOpConstructInt:
shannonwoods@chromium.org8c788e82013-05-30 00:20:21 +0000873 case EOpConstructUVec2:
874 case EOpConstructUVec3:
875 case EOpConstructUVec4:
Nicolas Capensab60b932013-06-05 10:31:21 -0400876 case EOpConstructUInt:
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000877 case EOpConstructBVec2:
878 case EOpConstructBVec3:
879 case EOpConstructBVec4:
880 case EOpConstructBool:
881 case EOpConstructStruct:
882 return true;
883 default:
884 return false;
885 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000886}
Zhenyao Mo7cab38b2013-10-15 12:59:30 -0700887
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000888//
889// Make sure the type of a unary operator is appropriate for its
890// combination of operation and operand type.
891//
892// Returns false in nothing makes sense.
893//
894bool TIntermUnary::promote(TInfoSink&)
895{
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000896 switch (op) {
897 case EOpLogicalNot:
898 if (operand->getBasicType() != EbtBool)
899 return false;
900 break;
901 case EOpNegative:
902 case EOpPostIncrement:
903 case EOpPostDecrement:
904 case EOpPreIncrement:
905 case EOpPreDecrement:
906 if (operand->getBasicType() == EbtBool)
907 return false;
908 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000909
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000910 // operators for built-ins are already type checked against their prototype
911 case EOpAny:
912 case EOpAll:
913 case EOpVectorLogicalNot:
914 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000915
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000916 default:
917 if (operand->getBasicType() != EbtFloat)
918 return false;
919 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000920
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000921 setType(operand->getType());
shannon.woods%transgaming.com@gtempaccount.comac1fc752013-04-13 03:29:52 +0000922 type.setQualifier(EvqTemporary);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000923
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000924 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000925}
926
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +0000927bool validateMultiplication(TOperator op, const TType &left, const TType &right)
928{
929 switch (op)
930 {
931 case EOpMul:
932 case EOpMulAssign:
933 return left.getNominalSize() == right.getNominalSize() && left.getSecondarySize() == right.getSecondarySize();
934 case EOpVectorTimesScalar:
935 case EOpVectorTimesScalarAssign:
936 return true;
937 case EOpVectorTimesMatrix:
938 return left.getNominalSize() == right.getRows();
939 case EOpVectorTimesMatrixAssign:
940 return left.getNominalSize() == right.getRows() && left.getNominalSize() == right.getCols();
941 case EOpMatrixTimesVector:
942 return left.getCols() == right.getNominalSize();
943 case EOpMatrixTimesScalar:
944 case EOpMatrixTimesScalarAssign:
945 return true;
946 case EOpMatrixTimesMatrix:
947 return left.getCols() == right.getRows();
948 case EOpMatrixTimesMatrixAssign:
949 return left.getCols() == right.getCols() && left.getRows() == right.getRows();
950
951 default:
952 UNREACHABLE();
953 return false;
954 }
955}
956
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000957//
958// Establishes the type of the resultant operation, as well as
959// makes the operator the correct one for the operands.
960//
961// Returns false if operator can't work on operands.
962//
963bool TIntermBinary::promote(TInfoSink& infoSink)
964{
alokp@chromium.org8f0f24a2010-09-01 21:06:24 +0000965 // This function only handles scalars, vectors, and matrices.
shannonwoods@chromium.orgb7dc4032013-05-30 00:18:18 +0000966 if (left->isArray() || right->isArray())
967 {
Jamie Madill075edd82013-07-08 13:30:19 -0400968 infoSink.info.message(EPrefixInternalError, getLine(), "Invalid operation for arrays");
alokp@chromium.org8f0f24a2010-09-01 21:06:24 +0000969 return false;
970 }
971
alokp@chromium.org32cfaf42010-08-23 21:01:13 +0000972 // GLSL ES 2.0 does not support implicit type casting.
973 // So the basic type should always match.
974 if (left->getBasicType() != right->getBasicType())
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000975 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000976
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000977 //
978 // Base assumption: just make the type the same as the left
979 // operand. Then only deviations from this need be coded.
980 //
daniel@transgaming.comfe565152010-04-10 05:29:07 +0000981 setType(left->getType());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000982
alokp@chromium.org32cfaf42010-08-23 21:01:13 +0000983 // The result gets promoted to the highest precision.
984 TPrecision higherPrecision = GetHigherPrecision(left->getPrecision(), right->getPrecision());
alokp@chromium.org58e54292010-08-24 21:40:03 +0000985 getTypePointer()->setPrecision(higherPrecision);
alokp@chromium.org32cfaf42010-08-23 21:01:13 +0000986
987 // Binary operations results in temporary variables unless both
988 // operands are const.
shannonwoods@chromium.orgb7dc4032013-05-30 00:18:18 +0000989 if (left->getQualifier() != EvqConst || right->getQualifier() != EvqConst)
990 {
alokp@chromium.org58e54292010-08-24 21:40:03 +0000991 getTypePointer()->setQualifier(EvqTemporary);
alokp@chromium.org32cfaf42010-08-23 21:01:13 +0000992 }
daniel@transgaming.coma5d76232010-05-17 09:58:47 +0000993
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +0000994 const int nominalSize = std::max(left->getNominalSize(), right->getNominalSize());
alokp@chromium.org32cfaf42010-08-23 21:01:13 +0000995
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000996 //
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +0000997 // All scalars or structs. Code after this test assumes this case is removed!
alokp@chromium.org2cf17712010-03-30 20:33:18 +0000998 //
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +0000999 if (nominalSize == 1)
shannonwoods@chromium.orgb7dc4032013-05-30 00:18:18 +00001000 {
1001 switch (op)
1002 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001003 //
1004 // Promote to conditional
1005 //
1006 case EOpEqual:
1007 case EOpNotEqual:
1008 case EOpLessThan:
1009 case EOpGreaterThan:
1010 case EOpLessThanEqual:
1011 case EOpGreaterThanEqual:
daniel@transgaming.coma5d76232010-05-17 09:58:47 +00001012 setType(TType(EbtBool, EbpUndefined));
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001013 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001014
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001015 //
1016 // And and Or operate on conditionals
1017 //
1018 case EOpLogicalAnd:
1019 case EOpLogicalOr:
alokp@chromium.org32cfaf42010-08-23 21:01:13 +00001020 // Both operands must be of type bool.
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001021 if (left->getBasicType() != EbtBool || right->getBasicType() != EbtBool)
shannonwoods@chromium.orgb7dc4032013-05-30 00:18:18 +00001022 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001023 return false;
shannonwoods@chromium.orgb7dc4032013-05-30 00:18:18 +00001024 }
daniel@transgaming.coma5d76232010-05-17 09:58:47 +00001025 setType(TType(EbtBool, EbpUndefined));
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001026 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001027
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001028 default:
alokp@chromium.org32cfaf42010-08-23 21:01:13 +00001029 break;
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001030 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001031 return true;
1032 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001033
alokp@chromium.org32cfaf42010-08-23 21:01:13 +00001034 // If we reach here, at least one of the operands is vector or matrix.
1035 // The other operand could be a scalar, vector, or matrix.
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001036 // Can these two operands be combined?
1037 //
alokp@chromium.org32cfaf42010-08-23 21:01:13 +00001038 TBasicType basicType = left->getBasicType();
shannonwoods@chromium.orgb7dc4032013-05-30 00:18:18 +00001039 switch (op)
1040 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001041 case EOpMul:
shannonwoods@chromium.orgb7dc4032013-05-30 00:18:18 +00001042 if (!left->isMatrix() && right->isMatrix())
1043 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001044 if (left->isVector())
shannonwoods@chromium.orgb7dc4032013-05-30 00:18:18 +00001045 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001046 op = EOpVectorTimesMatrix;
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +00001047 setType(TType(basicType, higherPrecision, EvqTemporary, right->getCols(), 1));
shannonwoods@chromium.orgb7dc4032013-05-30 00:18:18 +00001048 }
1049 else
1050 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001051 op = EOpMatrixTimesScalar;
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00001052 setType(TType(basicType, higherPrecision, EvqTemporary, right->getCols(), right->getRows()));
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001053 }
shannonwoods@chromium.orgb7dc4032013-05-30 00:18:18 +00001054 }
1055 else if (left->isMatrix() && !right->isMatrix())
1056 {
1057 if (right->isVector())
1058 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001059 op = EOpMatrixTimesVector;
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00001060 setType(TType(basicType, higherPrecision, EvqTemporary, left->getRows(), 1));
shannonwoods@chromium.orgb7dc4032013-05-30 00:18:18 +00001061 }
1062 else
1063 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001064 op = EOpMatrixTimesScalar;
1065 }
shannonwoods@chromium.orgb7dc4032013-05-30 00:18:18 +00001066 }
1067 else if (left->isMatrix() && right->isMatrix())
1068 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001069 op = EOpMatrixTimesMatrix;
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +00001070 setType(TType(basicType, higherPrecision, EvqTemporary, right->getCols(), left->getRows()));
shannonwoods@chromium.orgb7dc4032013-05-30 00:18:18 +00001071 }
1072 else if (!left->isMatrix() && !right->isMatrix())
1073 {
1074 if (left->isVector() && right->isVector())
1075 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001076 // leave as component product
shannonwoods@chromium.orgb7dc4032013-05-30 00:18:18 +00001077 }
1078 else if (left->isVector() || right->isVector())
1079 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001080 op = EOpVectorTimesScalar;
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00001081 setType(TType(basicType, higherPrecision, EvqTemporary, nominalSize, 1));
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001082 }
shannonwoods@chromium.orgb7dc4032013-05-30 00:18:18 +00001083 }
1084 else
1085 {
Jamie Madill075edd82013-07-08 13:30:19 -04001086 infoSink.info.message(EPrefixInternalError, getLine(), "Missing elses");
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001087 return false;
1088 }
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00001089
1090 if (!validateMultiplication(op, left->getType(), right->getType()))
1091 {
1092 return false;
1093 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001094 break;
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00001095
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001096 case EOpMulAssign:
shannonwoods@chromium.orgb7dc4032013-05-30 00:18:18 +00001097 if (!left->isMatrix() && right->isMatrix())
1098 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001099 if (left->isVector())
shannonwoods@chromium.orgb7dc4032013-05-30 00:18:18 +00001100 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001101 op = EOpVectorTimesMatrixAssign;
shannonwoods@chromium.orgb7dc4032013-05-30 00:18:18 +00001102 }
1103 else
1104 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001105 return false;
1106 }
shannonwoods@chromium.orgb7dc4032013-05-30 00:18:18 +00001107 }
1108 else if (left->isMatrix() && !right->isMatrix())
1109 {
1110 if (right->isVector())
1111 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001112 return false;
shannonwoods@chromium.orgb7dc4032013-05-30 00:18:18 +00001113 }
1114 else
1115 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001116 op = EOpMatrixTimesScalarAssign;
1117 }
shannonwoods@chromium.orgb7dc4032013-05-30 00:18:18 +00001118 }
1119 else if (left->isMatrix() && right->isMatrix())
1120 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001121 op = EOpMatrixTimesMatrixAssign;
shannonwoods@chromium.org9bd22fa2013-05-30 00:18:47 +00001122 setType(TType(basicType, higherPrecision, EvqTemporary, right->getCols(), left->getRows()));
shannonwoods@chromium.orgb7dc4032013-05-30 00:18:18 +00001123 }
1124 else if (!left->isMatrix() && !right->isMatrix())
1125 {
1126 if (left->isVector() && right->isVector())
1127 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001128 // leave as component product
shannonwoods@chromium.orgb7dc4032013-05-30 00:18:18 +00001129 }
1130 else if (left->isVector() || right->isVector())
1131 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001132 if (! left->isVector())
1133 return false;
1134 op = EOpVectorTimesScalarAssign;
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00001135 setType(TType(basicType, higherPrecision, EvqTemporary, left->getNominalSize(), 1));
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001136 }
shannonwoods@chromium.orgb7dc4032013-05-30 00:18:18 +00001137 }
1138 else
1139 {
Jamie Madill075edd82013-07-08 13:30:19 -04001140 infoSink.info.message(EPrefixInternalError, getLine(), "Missing elses");
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001141 return false;
1142 }
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00001143
1144 if (!validateMultiplication(op, left->getType(), right->getType()))
1145 {
1146 return false;
1147 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001148 break;
alokp@chromium.org32cfaf42010-08-23 21:01:13 +00001149
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001150 case EOpAssign:
1151 case EOpInitialize:
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001152 case EOpAdd:
1153 case EOpSub:
1154 case EOpDiv:
1155 case EOpAddAssign:
1156 case EOpSubAssign:
1157 case EOpDivAssign:
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00001158 {
1159 if ((left->isMatrix() && right->isVector()) ||
1160 (left->isVector() && right->isMatrix()))
1161 return false;
1162
1163 // Are the sizes compatible?
1164 if (left->getNominalSize() != right->getNominalSize() || left->getSecondarySize() != right->getSecondarySize())
1165 {
1166 // If the nominal size of operands do not match:
1167 // One of them must be scalar.
1168 if (!left->isScalar() && !right->isScalar())
1169 return false;
1170
1171 // Operator cannot be of type pure assignment.
1172 if (op == EOpAssign || op == EOpInitialize)
1173 return false;
1174 }
1175
1176 const int secondarySize = std::max(left->getSecondarySize(), right->getSecondarySize());
1177
1178 setType(TType(basicType, higherPrecision, EvqTemporary, nominalSize, secondarySize));
1179 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001180 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001181
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001182 case EOpEqual:
1183 case EOpNotEqual:
1184 case EOpLessThan:
1185 case EOpGreaterThan:
1186 case EOpLessThanEqual:
1187 case EOpGreaterThanEqual:
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00001188 if ((left->getNominalSize() != right->getNominalSize()) ||
1189 (left->getSecondarySize() != right->getSecondarySize()))
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001190 return false;
daniel@transgaming.coma5d76232010-05-17 09:58:47 +00001191 setType(TType(EbtBool, EbpUndefined));
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001192 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001193
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001194 default:
1195 return false;
1196 }
alokp@chromium.org32cfaf42010-08-23 21:01:13 +00001197
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001198 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001199}
1200
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001201bool CompareStruct(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001202{
Jamie Madill98493dd2013-07-08 14:39:03 -04001203 const TFieldList& fields = leftNodeType.getStruct()->fields();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001204
Jamie Madill98493dd2013-07-08 14:39:03 -04001205 size_t structSize = fields.size();
Jamie Madill94bf7f22013-07-08 13:31:15 -04001206 size_t index = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001207
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001208 for (size_t j = 0; j < structSize; j++) {
Jamie Madill98493dd2013-07-08 14:39:03 -04001209 size_t size = fields[j]->type()->getObjectSize();
Jamie Madill94bf7f22013-07-08 13:31:15 -04001210 for (size_t i = 0; i < size; i++) {
Jamie Madill98493dd2013-07-08 14:39:03 -04001211 if (fields[j]->type()->getBasicType() == EbtStruct) {
1212 if (!CompareStructure(*fields[j]->type(), &rightUnionArray[index], &leftUnionArray[index]))
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001213 return false;
1214 } else {
1215 if (leftUnionArray[index] != rightUnionArray[index])
1216 return false;
1217 index++;
1218 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001219
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001220 }
1221 }
1222 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001223}
1224
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001225bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001226{
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001227 if (leftNodeType.isArray()) {
1228 TType typeWithoutArrayness = leftNodeType;
1229 typeWithoutArrayness.clearArrayness();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001230
Jamie Madill94bf7f22013-07-08 13:31:15 -04001231 size_t arraySize = leftNodeType.getArraySize();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001232
Jamie Madill94bf7f22013-07-08 13:31:15 -04001233 for (size_t i = 0; i < arraySize; ++i) {
1234 size_t offset = typeWithoutArrayness.getObjectSize() * i;
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001235 if (!CompareStruct(typeWithoutArrayness, &rightUnionArray[offset], &leftUnionArray[offset]))
1236 return false;
1237 }
1238 } else
1239 return CompareStruct(leftNodeType, rightUnionArray, leftUnionArray);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001240
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001241 return true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001242}
1243
1244//
1245// The fold functions see if an operation on a constant can be done in place,
1246// without generating run-time code.
1247//
1248// Returns the node to keep using, which may or may not be the node passed in.
1249//
1250
1251TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNode, TInfoSink& infoSink)
1252{
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001253 ConstantUnion *unionArray = getUnionArrayPointer();
Jamie Madill94bf7f22013-07-08 13:31:15 -04001254 size_t objectSize = getType().getObjectSize();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001255
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001256 if (constantNode)
1257 {
1258 // binary operations
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001259 TIntermConstantUnion *node = constantNode->getAsConstantUnion();
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001260 ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001261 TType returnType = getType();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001262
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001263 // for a case like float f = 1.2 + vec4(2,3,4,5);
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001264 if (constantNode->getType().getObjectSize() == 1 && objectSize > 1)
1265 {
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001266 rightUnionArray = new ConstantUnion[objectSize];
Jamie Madill94bf7f22013-07-08 13:31:15 -04001267 for (size_t i = 0; i < objectSize; ++i)
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001268 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001269 rightUnionArray[i] = *node->getUnionArrayPointer();
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001270 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001271 returnType = getType();
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001272 }
1273 else if (constantNode->getType().getObjectSize() > 1 && objectSize == 1)
1274 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001275 // for a case like float f = vec4(2,3,4,5) + 1.2;
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001276 unionArray = new ConstantUnion[constantNode->getType().getObjectSize()];
Jamie Madill94bf7f22013-07-08 13:31:15 -04001277 for (size_t i = 0; i < constantNode->getType().getObjectSize(); ++i)
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001278 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001279 unionArray[i] = *getUnionArrayPointer();
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001280 }
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001281 returnType = node->getType();
1282 objectSize = constantNode->getType().getObjectSize();
1283 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001284
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001285 ConstantUnion* tempConstArray = 0;
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001286 TIntermConstantUnion *tempNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001287
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001288 bool boolNodeFlag = false;
1289 switch(op) {
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001290 case EOpAdd:
1291 tempConstArray = new ConstantUnion[objectSize];
1292 {
Jamie Madill94bf7f22013-07-08 13:31:15 -04001293 for (size_t i = 0; i < objectSize; i++)
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001294 tempConstArray[i] = unionArray[i] + rightUnionArray[i];
1295 }
1296 break;
1297 case EOpSub:
1298 tempConstArray = new ConstantUnion[objectSize];
1299 {
Jamie Madill94bf7f22013-07-08 13:31:15 -04001300 for (size_t i = 0; i < objectSize; i++)
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001301 tempConstArray[i] = unionArray[i] - rightUnionArray[i];
1302 }
1303 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001304
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001305 case EOpMul:
1306 case EOpVectorTimesScalar:
1307 case EOpMatrixTimesScalar:
1308 tempConstArray = new ConstantUnion[objectSize];
1309 {
Jamie Madill94bf7f22013-07-08 13:31:15 -04001310 for (size_t i = 0; i < objectSize; i++)
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001311 tempConstArray[i] = unionArray[i] * rightUnionArray[i];
1312 }
1313 break;
1314
1315 case EOpMatrixTimesMatrix:
1316 {
1317 if (getType().getBasicType() != EbtFloat || node->getBasicType() != EbtFloat)
1318 {
Jamie Madill075edd82013-07-08 13:30:19 -04001319 infoSink.info.message(EPrefixInternalError, getLine(), "Constant Folding cannot be done for matrix multiply");
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001320 return 0;
1321 }
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001322
Shannon Woods3841b8e2013-09-10 18:23:12 -04001323 const int leftCols = getCols();
1324 const int leftRows = getRows();
1325 const int rightCols = constantNode->getType().getCols();
1326 const int rightRows = constantNode->getType().getRows();
1327 const int resultCols = rightCols;
1328 const int resultRows = leftRows;
shannonwoods@chromium.org50733332013-05-30 00:19:07 +00001329
1330 tempConstArray = new ConstantUnion[resultCols*resultRows];
1331 for (int row = 0; row < resultRows; row++)
1332 {
1333 for (int column = 0; column < resultCols; column++)
1334 {
1335 tempConstArray[resultRows * column + row].setFConst(0.0f);
1336 for (int i = 0; i < leftCols; i++)
1337 {
1338 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 +00001339 }
1340 }
1341 }
shannonwoods@chromium.org50733332013-05-30 00:19:07 +00001342
1343 // update return type for matrix product
1344 returnType.setPrimarySize(resultCols);
1345 returnType.setSecondarySize(resultRows);
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001346 }
1347 break;
1348
1349 case EOpDiv:
1350 {
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001351 tempConstArray = new ConstantUnion[objectSize];
Jamie Madill94bf7f22013-07-08 13:31:15 -04001352 for (size_t i = 0; i < objectSize; i++)
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001353 {
1354 switch (getType().getBasicType())
1355 {
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +00001356 case EbtFloat:
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001357 if (rightUnionArray[i] == 0.0f)
1358 {
Jamie Madill075edd82013-07-08 13:30:19 -04001359 infoSink.info.message(EPrefixWarning, getLine(), "Divide by zero error during constant folding");
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001360 tempConstArray[i].setFConst(unionArray[i].getFConst() < 0 ? -FLT_MAX : FLT_MAX);
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001361 }
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001362 else
1363 {
1364 tempConstArray[i].setFConst(unionArray[i].getFConst() / rightUnionArray[i].getFConst());
1365 }
1366 break;
1367
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +00001368 case EbtInt:
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001369 if (rightUnionArray[i] == 0)
1370 {
Jamie Madill075edd82013-07-08 13:30:19 -04001371 infoSink.info.message(EPrefixWarning, getLine(), "Divide by zero error during constant folding");
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001372 tempConstArray[i].setIConst(INT_MAX);
1373 }
1374 else
1375 {
1376 tempConstArray[i].setIConst(unionArray[i].getIConst() / rightUnionArray[i].getIConst());
1377 }
1378 break;
1379
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +00001380 case EbtUInt:
1381 if (rightUnionArray[i] == 0)
1382 {
Jamie Madill075edd82013-07-08 13:30:19 -04001383 infoSink.info.message(EPrefixWarning, getLine(), "Divide by zero error during constant folding");
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +00001384 tempConstArray[i].setUConst(UINT_MAX);
1385 }
1386 else
1387 {
1388 tempConstArray[i].setUConst(unionArray[i].getUConst() / rightUnionArray[i].getUConst());
1389 }
1390 break;
1391
1392 default:
Jamie Madill075edd82013-07-08 13:30:19 -04001393 infoSink.info.message(EPrefixInternalError, getLine(), "Constant folding cannot be done for \"/\"");
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001394 return 0;
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001395 }
1396 }
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001397 }
1398 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001399
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001400 case EOpMatrixTimesVector:
1401 {
1402 if (node->getBasicType() != EbtFloat)
1403 {
Jamie Madill075edd82013-07-08 13:30:19 -04001404 infoSink.info.message(EPrefixInternalError, getLine(), "Constant Folding cannot be done for matrix times vector");
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001405 return 0;
1406 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001407
Shannon Woods3841b8e2013-09-10 18:23:12 -04001408 const int matrixCols = getCols();
1409 const int matrixRows = getRows();
shannonwoods@chromium.org50733332013-05-30 00:19:07 +00001410
1411 tempConstArray = new ConstantUnion[matrixRows];
1412
1413 for (int matrixRow = 0; matrixRow < matrixRows; matrixRow++)
1414 {
1415 tempConstArray[matrixRow].setFConst(0.0f);
1416 for (int col = 0; col < matrixCols; col++)
1417 {
1418 tempConstArray[matrixRow].setFConst(tempConstArray[matrixRow].getFConst() + ((unionArray[col * matrixRows + matrixRow].getFConst()) * rightUnionArray[col].getFConst()));
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001419 }
1420 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001421
shannonwoods@chromium.org50733332013-05-30 00:19:07 +00001422 returnType = node->getType();
1423 returnType.setPrimarySize(matrixRows);
1424
1425 tempNode = new TIntermConstantUnion(tempConstArray, returnType);
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001426 tempNode->setLine(getLine());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001427
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001428 return tempNode;
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001429 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001430
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001431 case EOpVectorTimesMatrix:
1432 {
1433 if (getType().getBasicType() != EbtFloat)
1434 {
Jamie Madill075edd82013-07-08 13:30:19 -04001435 infoSink.info.message(EPrefixInternalError, getLine(), "Constant Folding cannot be done for vector times matrix");
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001436 return 0;
1437 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001438
Shannon Woods3841b8e2013-09-10 18:23:12 -04001439 const int matrixCols = constantNode->getType().getCols();
1440 const int matrixRows = constantNode->getType().getRows();
shannonwoods@chromium.org50733332013-05-30 00:19:07 +00001441
1442 tempConstArray = new ConstantUnion[matrixCols];
1443
1444 for (int matrixCol = 0; matrixCol < matrixCols; matrixCol++)
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001445 {
shannonwoods@chromium.org50733332013-05-30 00:19:07 +00001446 tempConstArray[matrixCol].setFConst(0.0f);
1447 for (int matrixRow = 0; matrixRow < matrixRows; matrixRow++)
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001448 {
shannonwoods@chromium.org50733332013-05-30 00:19:07 +00001449 tempConstArray[matrixCol].setFConst(tempConstArray[matrixCol].getFConst() + ((unionArray[matrixRow].getFConst()) * rightUnionArray[matrixCol * matrixRows + matrixRow].getFConst()));
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001450 }
1451 }
shannonwoods@chromium.org50733332013-05-30 00:19:07 +00001452
1453 returnType.setPrimarySize(matrixCols);
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001454 }
1455 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001456
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001457 case EOpLogicalAnd: // this code is written for possible future use, will not get executed currently
1458 {
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001459 tempConstArray = new ConstantUnion[objectSize];
Jamie Madill94bf7f22013-07-08 13:31:15 -04001460 for (size_t i = 0; i < objectSize; i++)
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001461 {
1462 tempConstArray[i] = unionArray[i] && rightUnionArray[i];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001463 }
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001464 }
1465 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001466
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001467 case EOpLogicalOr: // this code is written for possible future use, will not get executed currently
1468 {
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001469 tempConstArray = new ConstantUnion[objectSize];
Jamie Madill94bf7f22013-07-08 13:31:15 -04001470 for (size_t i = 0; i < objectSize; i++)
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001471 {
1472 tempConstArray[i] = unionArray[i] || rightUnionArray[i];
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001473 }
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001474 }
1475 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001476
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001477 case EOpLogicalXor:
1478 {
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001479 tempConstArray = new ConstantUnion[objectSize];
Jamie Madill94bf7f22013-07-08 13:31:15 -04001480 for (size_t i = 0; i < objectSize; i++)
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001481 {
1482 switch (getType().getBasicType())
1483 {
1484 case EbtBool:
1485 tempConstArray[i].setBConst((unionArray[i] == rightUnionArray[i]) ? false : true);
1486 break;
1487 default:
1488 UNREACHABLE();
1489 break;
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001490 }
1491 }
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001492 }
1493 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001494
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001495 case EOpLessThan:
1496 assert(objectSize == 1);
1497 tempConstArray = new ConstantUnion[1];
1498 tempConstArray->setBConst(*unionArray < *rightUnionArray);
1499 returnType = TType(EbtBool, EbpUndefined, EvqConst);
1500 break;
1501
1502 case EOpGreaterThan:
1503 assert(objectSize == 1);
1504 tempConstArray = new ConstantUnion[1];
1505 tempConstArray->setBConst(*unionArray > *rightUnionArray);
1506 returnType = TType(EbtBool, EbpUndefined, EvqConst);
1507 break;
1508
1509 case EOpLessThanEqual:
1510 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001511 assert(objectSize == 1);
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001512 ConstantUnion constant;
1513 constant.setBConst(*unionArray > *rightUnionArray);
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001514 tempConstArray = new ConstantUnion[1];
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001515 tempConstArray->setBConst(!constant.getBConst());
daniel@transgaming.coma5d76232010-05-17 09:58:47 +00001516 returnType = TType(EbtBool, EbpUndefined, EvqConst);
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001517 break;
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001518 }
1519
1520 case EOpGreaterThanEqual:
1521 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001522 assert(objectSize == 1);
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001523 ConstantUnion constant;
1524 constant.setBConst(*unionArray < *rightUnionArray);
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001525 tempConstArray = new ConstantUnion[1];
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001526 tempConstArray->setBConst(!constant.getBConst());
daniel@transgaming.coma5d76232010-05-17 09:58:47 +00001527 returnType = TType(EbtBool, EbpUndefined, EvqConst);
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001528 break;
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001529 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001530
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001531 case EOpEqual:
1532 if (getType().getBasicType() == EbtStruct)
1533 {
1534 if (!CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray))
1535 boolNodeFlag = true;
1536 }
1537 else
1538 {
Jamie Madill94bf7f22013-07-08 13:31:15 -04001539 for (size_t i = 0; i < objectSize; i++)
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001540 {
1541 if (unionArray[i] != rightUnionArray[i])
1542 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001543 boolNodeFlag = true;
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001544 break; // break out of for loop
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001545 }
1546 }
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001547 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001548
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001549 tempConstArray = new ConstantUnion[1];
1550 if (!boolNodeFlag)
1551 {
1552 tempConstArray->setBConst(true);
1553 }
1554 else
1555 {
1556 tempConstArray->setBConst(false);
1557 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001558
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001559 tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConst));
1560 tempNode->setLine(getLine());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001561
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001562 return tempNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001563
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001564 case EOpNotEqual:
1565 if (getType().getBasicType() == EbtStruct)
1566 {
1567 if (CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray))
1568 boolNodeFlag = true;
1569 }
1570 else
1571 {
Jamie Madill94bf7f22013-07-08 13:31:15 -04001572 for (size_t i = 0; i < objectSize; i++)
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001573 {
1574 if (unionArray[i] == rightUnionArray[i])
1575 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001576 boolNodeFlag = true;
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001577 break; // break out of for loop
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001578 }
1579 }
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001580 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001581
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001582 tempConstArray = new ConstantUnion[1];
1583 if (!boolNodeFlag)
1584 {
1585 tempConstArray->setBConst(true);
1586 }
1587 else
1588 {
1589 tempConstArray->setBConst(false);
1590 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001591
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001592 tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConst));
1593 tempNode->setLine(getLine());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001594
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001595 return tempNode;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001596
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001597 default:
Jamie Madill075edd82013-07-08 13:30:19 -04001598 infoSink.info.message(EPrefixInternalError, getLine(), "Invalid operator for constant folding");
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001599 return 0;
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001600 }
1601 tempNode = new TIntermConstantUnion(tempConstArray, returnType);
1602 tempNode->setLine(getLine());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001603
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001604 return tempNode;
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001605 }
1606 else
1607 {
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001608 //
1609 // Do unary operations
1610 //
1611 TIntermConstantUnion *newNode = 0;
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001612 ConstantUnion* tempConstArray = new ConstantUnion[objectSize];
Jamie Madill94bf7f22013-07-08 13:31:15 -04001613 for (size_t i = 0; i < objectSize; i++)
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001614 {
1615 switch(op)
1616 {
1617 case EOpNegative:
1618 switch (getType().getBasicType())
1619 {
Nicolas Capensc0f7c612013-06-05 11:46:09 -04001620 case EbtFloat: tempConstArray[i].setFConst(-unionArray[i].getFConst()); break;
1621 case EbtInt: tempConstArray[i].setIConst(-unionArray[i].getIConst()); break;
1622 case EbtUInt: tempConstArray[i].setUConst(static_cast<unsigned int>(-static_cast<int>(unionArray[i].getUConst()))); break;
1623 default:
Jamie Madill075edd82013-07-08 13:30:19 -04001624 infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
Nicolas Capensc0f7c612013-06-05 11:46:09 -04001625 return 0;
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001626 }
1627 break;
1628
1629 case EOpLogicalNot: // this code is written for possible future use, will not get executed currently
1630 switch (getType().getBasicType())
1631 {
Nicolas Capensc0f7c612013-06-05 11:46:09 -04001632 case EbtBool: tempConstArray[i].setBConst(!unionArray[i].getBConst()); break;
1633 default:
Jamie Madill075edd82013-07-08 13:30:19 -04001634 infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
Nicolas Capensc0f7c612013-06-05 11:46:09 -04001635 return 0;
shannonwoods@chromium.org9fc85b12013-05-30 00:19:00 +00001636 }
1637 break;
1638
1639 default:
1640 return 0;
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001641 }
1642 }
1643 newNode = new TIntermConstantUnion(tempConstArray, getType());
1644 newNode->setLine(getLine());
1645 return newNode;
1646 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001647}
1648
1649TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermConstantUnion* node)
1650{
Jamie Madill94bf7f22013-07-08 13:31:15 -04001651 size_t size = node->getType().getObjectSize();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001652
alokp@chromium.org6ff56fd2010-05-05 16:37:50 +00001653 ConstantUnion *leftUnionArray = new ConstantUnion[size];
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001654
Jamie Madill94bf7f22013-07-08 13:31:15 -04001655 for (size_t i=0; i < size; i++) {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001656
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001657 switch (promoteTo) {
1658 case EbtFloat:
1659 switch (node->getType().getBasicType()) {
1660 case EbtInt:
shannon.woods%transgaming.com@gtempaccount.com812c3f12013-04-13 03:30:01 +00001661 leftUnionArray[i].setFConst(static_cast<float>(node->getIConst(i)));
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001662 break;
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +00001663 case EbtUInt:
1664 leftUnionArray[i].setFConst(static_cast<float>(node->getUConst(i)));
1665 break;
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001666 case EbtBool:
shannon.woods%transgaming.com@gtempaccount.com812c3f12013-04-13 03:30:01 +00001667 leftUnionArray[i].setFConst(static_cast<float>(node->getBConst(i)));
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001668 break;
1669 case EbtFloat:
shannon.woods%transgaming.com@gtempaccount.com812c3f12013-04-13 03:30:01 +00001670 leftUnionArray[i].setFConst(static_cast<float>(node->getFConst(i)));
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001671 break;
1672 default:
Jamie Madill075edd82013-07-08 13:30:19 -04001673 infoSink.info.message(EPrefixInternalError, node->getLine(), "Cannot promote");
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001674 return 0;
1675 }
1676 break;
1677 case EbtInt:
1678 switch (node->getType().getBasicType()) {
1679 case EbtInt:
shannon.woods%transgaming.com@gtempaccount.com812c3f12013-04-13 03:30:01 +00001680 leftUnionArray[i].setIConst(static_cast<int>(node->getIConst(i)));
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001681 break;
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +00001682 case EbtUInt:
1683 leftUnionArray[i].setIConst(static_cast<int>(node->getUConst(i)));
1684 break;
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001685 case EbtBool:
shannon.woods%transgaming.com@gtempaccount.com812c3f12013-04-13 03:30:01 +00001686 leftUnionArray[i].setIConst(static_cast<int>(node->getBConst(i)));
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001687 break;
1688 case EbtFloat:
shannon.woods%transgaming.com@gtempaccount.com812c3f12013-04-13 03:30:01 +00001689 leftUnionArray[i].setIConst(static_cast<int>(node->getFConst(i)));
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001690 break;
1691 default:
Jamie Madill075edd82013-07-08 13:30:19 -04001692 infoSink.info.message(EPrefixInternalError, node->getLine(), "Cannot promote");
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001693 return 0;
1694 }
1695 break;
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +00001696 case EbtUInt:
1697 switch (node->getType().getBasicType()) {
1698 case EbtInt:
1699 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getIConst(i)));
1700 break;
1701 case EbtUInt:
1702 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getUConst(i)));
1703 break;
1704 case EbtBool:
1705 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getBConst(i)));
1706 break;
1707 case EbtFloat:
1708 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getFConst(i)));
1709 break;
1710 default:
Jamie Madill075edd82013-07-08 13:30:19 -04001711 infoSink.info.message(EPrefixInternalError, node->getLine(), "Cannot promote");
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +00001712 return 0;
1713 }
1714 break;
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001715 case EbtBool:
1716 switch (node->getType().getBasicType()) {
1717 case EbtInt:
shannon.woods%transgaming.com@gtempaccount.com812c3f12013-04-13 03:30:01 +00001718 leftUnionArray[i].setBConst(node->getIConst(i) != 0);
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001719 break;
shannonwoods@chromium.org6b709912013-05-30 00:20:04 +00001720 case EbtUInt:
1721 leftUnionArray[i].setBConst(node->getUConst(i) != 0);
1722 break;
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001723 case EbtBool:
shannon.woods%transgaming.com@gtempaccount.com812c3f12013-04-13 03:30:01 +00001724 leftUnionArray[i].setBConst(node->getBConst(i));
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001725 break;
1726 case EbtFloat:
shannon.woods%transgaming.com@gtempaccount.com812c3f12013-04-13 03:30:01 +00001727 leftUnionArray[i].setBConst(node->getFConst(i) != 0.0f);
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001728 break;
1729 default:
Jamie Madill075edd82013-07-08 13:30:19 -04001730 infoSink.info.message(EPrefixInternalError, node->getLine(), "Cannot promote");
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001731 return 0;
1732 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001733
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001734 break;
1735 default:
Jamie Madill075edd82013-07-08 13:30:19 -04001736 infoSink.info.message(EPrefixInternalError, node->getLine(), "Incorrect data type found");
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001737 return 0;
1738 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001739
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001740 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001741
alokp@chromium.org2cf17712010-03-30 20:33:18 +00001742 const TType& t = node->getType();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001743
shannonwoods@chromium.org09e09882013-05-30 00:18:25 +00001744 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 +00001745}
1746
daniel@transgaming.com0aa3b5a2012-11-28 19:43:24 +00001747// static
1748TString TIntermTraverser::hash(const TString& name, ShHashFunction64 hashFunction)
1749{
1750 if (hashFunction == NULL || name.empty())
1751 return name;
1752 khronos_uint64_t number = (*hashFunction)(name.c_str(), name.length());
1753 TStringStream stream;
1754 stream << HASHED_NAME_PREFIX << std::hex << number;
1755 TString hashedName = stream.str();
1756 return hashedName;
1757}