blob: ccb8d63e2e3dae930aa5464798d9a87d937a2a1a [file] [log] [blame]
John Bauman66b8ab22014-05-06 15:57:45 -04001//
John Baumand4ae8632014-05-06 16:18:33 -04002// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
John Bauman66b8ab22014-05-06 15:57:45 -04003// 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
11#include <float.h>
12#include <limits.h>
13#include <algorithm>
14
Nicolas Capenscc863da2015-01-21 15:50:55 -050015#include "localintermediate.h"
16#include "SymbolTable.h"
John Bauman66b8ab22014-05-06 15:57:45 -040017
18bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray);
19
20static TPrecision GetHigherPrecision( TPrecision left, TPrecision right ){
21 return left > right ? left : right;
22}
23
Alexis Hetu00106d42015-04-23 11:45:35 -040024static bool ValidateMultiplication(TOperator op, const TType &left, const TType &right)
25{
26 switch(op)
27 {
28 case EOpMul:
29 case EOpMulAssign:
30 return left.getNominalSize() == right.getNominalSize() &&
31 left.getSecondarySize() == right.getSecondarySize();
32 case EOpVectorTimesScalar:
33 case EOpVectorTimesScalarAssign:
34 return true;
35 case EOpVectorTimesMatrix:
36 return left.getNominalSize() == right.getSecondarySize();
37 case EOpVectorTimesMatrixAssign:
38 return left.getNominalSize() == right.getSecondarySize() &&
39 left.getNominalSize() == right.getNominalSize();
40 case EOpMatrixTimesVector:
41 return left.getNominalSize() == right.getNominalSize();
42 case EOpMatrixTimesScalar:
43 case EOpMatrixTimesScalarAssign:
44 return true;
45 case EOpMatrixTimesMatrix:
46 return left.getNominalSize() == right.getSecondarySize();
47 case EOpMatrixTimesMatrixAssign:
48 return left.getNominalSize() == right.getNominalSize() &&
49 left.getSecondarySize() == right.getSecondarySize();
50 default:
Nicolas Capens3713cd42015-06-22 10:41:54 -040051 UNREACHABLE(op);
Alexis Hetu00106d42015-04-23 11:45:35 -040052 return false;
53 }
54}
55
John Bauman66b8ab22014-05-06 15:57:45 -040056const char* getOperatorString(TOperator op) {
57 switch (op) {
58 case EOpInitialize: return "=";
59 case EOpAssign: return "=";
60 case EOpAddAssign: return "+=";
61 case EOpSubAssign: return "-=";
62 case EOpDivAssign: return "/=";
Alexis Hetu17809052015-05-13 11:28:22 -040063 case EOpIModAssign: return "%=";
64 case EOpBitShiftLeftAssign: return "<<=";
65 case EOpBitShiftRightAssign: return ">>=";
66 case EOpBitwiseAndAssign: return "&=";
67 case EOpBitwiseXorAssign: return "^=";
68 case EOpBitwiseOrAssign: return "|=";
John Bauman66b8ab22014-05-06 15:57:45 -040069
70 // Fall-through.
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -040071 case EOpMulAssign:
John Bauman66b8ab22014-05-06 15:57:45 -040072 case EOpVectorTimesMatrixAssign:
73 case EOpVectorTimesScalarAssign:
74 case EOpMatrixTimesScalarAssign:
75 case EOpMatrixTimesMatrixAssign: return "*=";
76
77 // Fall-through.
78 case EOpIndexDirect:
79 case EOpIndexIndirect: return "[]";
80
81 case EOpIndexDirectStruct: return ".";
82 case EOpVectorSwizzle: return ".";
83 case EOpAdd: return "+";
84 case EOpSub: return "-";
85 case EOpMul: return "*";
86 case EOpDiv: return "/";
87 case EOpMod: UNIMPLEMENTED(); break;
88 case EOpEqual: return "==";
89 case EOpNotEqual: return "!=";
90 case EOpLessThan: return "<";
91 case EOpGreaterThan: return ">";
92 case EOpLessThanEqual: return "<=";
93 case EOpGreaterThanEqual: return ">=";
94
95 // Fall-through.
96 case EOpVectorTimesScalar:
97 case EOpVectorTimesMatrix:
98 case EOpMatrixTimesVector:
99 case EOpMatrixTimesScalar:
100 case EOpMatrixTimesMatrix: return "*";
101
102 case EOpLogicalOr: return "||";
103 case EOpLogicalXor: return "^^";
104 case EOpLogicalAnd: return "&&";
Alexis Hetu17809052015-05-13 11:28:22 -0400105 case EOpIMod: return "%";
106 case EOpBitShiftLeft: return "<<";
107 case EOpBitShiftRight: return ">>";
108 case EOpBitwiseAnd: return "&";
109 case EOpBitwiseXor: return "^";
110 case EOpBitwiseOr: return "|";
John Bauman66b8ab22014-05-06 15:57:45 -0400111 case EOpNegative: return "-";
112 case EOpVectorLogicalNot: return "not";
113 case EOpLogicalNot: return "!";
Alexis Hetu17809052015-05-13 11:28:22 -0400114 case EOpBitwiseNot: return "~";
John Bauman66b8ab22014-05-06 15:57:45 -0400115 case EOpPostIncrement: return "++";
116 case EOpPostDecrement: return "--";
117 case EOpPreIncrement: return "++";
118 case EOpPreDecrement: return "--";
119
John Bauman66b8ab22014-05-06 15:57:45 -0400120 case EOpRadians: return "radians";
121 case EOpDegrees: return "degrees";
122 case EOpSin: return "sin";
123 case EOpCos: return "cos";
124 case EOpTan: return "tan";
125 case EOpAsin: return "asin";
126 case EOpAcos: return "acos";
127 case EOpAtan: return "atan";
Alexis Hetuaf1970c2015-04-17 14:26:07 -0400128 case EOpSinh: return "sinh";
129 case EOpCosh: return "cosh";
130 case EOpTanh: return "tanh";
131 case EOpAsinh: return "asinh";
132 case EOpAcosh: return "acosh";
133 case EOpAtanh: return "atanh";
John Bauman66b8ab22014-05-06 15:57:45 -0400134 case EOpExp: return "exp";
135 case EOpLog: return "log";
136 case EOpExp2: return "exp2";
137 case EOpLog2: return "log2";
138 case EOpSqrt: return "sqrt";
139 case EOpInverseSqrt: return "inversesqrt";
140 case EOpAbs: return "abs";
141 case EOpSign: return "sign";
142 case EOpFloor: return "floor";
Alexis Hetuaf1970c2015-04-17 14:26:07 -0400143 case EOpTrunc: return "trunc";
144 case EOpRound: return "round";
145 case EOpRoundEven: return "roundEven";
John Bauman66b8ab22014-05-06 15:57:45 -0400146 case EOpCeil: return "ceil";
147 case EOpFract: return "fract";
148 case EOpLength: return "length";
149 case EOpNormalize: return "normalize";
150 case EOpDFdx: return "dFdx";
151 case EOpDFdy: return "dFdy";
152 case EOpFwidth: return "fwidth";
153 case EOpAny: return "any";
154 case EOpAll: return "all";
Alexis Hetuaf1970c2015-04-17 14:26:07 -0400155 case EOpIsNan: return "isnan";
156 case EOpIsInf: return "isinf";
Alexis Hetu3815b6c2015-05-27 11:21:37 -0400157 case EOpOuterProduct: return "outerProduct";
158 case EOpTranspose: return "transpose";
159 case EOpDeterminant: return "determinant";
160 case EOpInverse: return "inverse";
John Bauman66b8ab22014-05-06 15:57:45 -0400161
162 default: break;
163 }
164 return "";
165}
166
167////////////////////////////////////////////////////////////////////////////
168//
169// First set of functions are to help build the intermediate representation.
170// These functions are not member functions of the nodes.
171// They are called from parser productions.
172//
173/////////////////////////////////////////////////////////////////////////////
174
175//
176// Add a terminal node for an identifier in an expression.
177//
178// Returns the added node.
179//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400180TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400181{
182 TIntermSymbol* node = new TIntermSymbol(id, name, type);
183 node->setLine(line);
184
185 return node;
186}
187
188//
189// Connect two nodes with a new parent that does a binary operation on the nodes.
190//
191// Returns the added node.
192//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400193TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400194{
195 switch (op) {
196 case EOpEqual:
197 case EOpNotEqual:
198 if (left->isArray())
199 return 0;
200 break;
201 case EOpLessThan:
202 case EOpGreaterThan:
203 case EOpLessThanEqual:
204 case EOpGreaterThanEqual:
205 if (left->isMatrix() || left->isArray() || left->isVector() || left->getBasicType() == EbtStruct) {
206 return 0;
207 }
208 break;
209 case EOpLogicalOr:
210 case EOpLogicalXor:
211 case EOpLogicalAnd:
212 if (left->getBasicType() != EbtBool || left->isMatrix() || left->isArray() || left->isVector()) {
213 return 0;
214 }
215 break;
Alexis Hetud061e422015-05-13 16:37:50 -0400216 case EOpBitwiseOr:
217 case EOpBitwiseXor:
218 case EOpBitwiseAnd:
Alexis Hetu9085c8d2015-06-01 13:48:07 -0400219 if (!IsInteger(left->getBasicType()) || left->isMatrix() || left->isArray()) {
Alexis Hetud061e422015-05-13 16:37:50 -0400220 return 0;
221 }
222 break;
John Bauman66b8ab22014-05-06 15:57:45 -0400223 case EOpAdd:
224 case EOpSub:
225 case EOpDiv:
226 case EOpMul:
Alexis Hetud061e422015-05-13 16:37:50 -0400227 if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool) {
John Bauman66b8ab22014-05-06 15:57:45 -0400228 return 0;
Alexis Hetud061e422015-05-13 16:37:50 -0400229 }
230 break;
231 case EOpIMod:
232 // Note that this is only for the % operator, not for mod()
233 if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool || left->getBasicType() == EbtFloat) {
234 return 0;
235 }
236 break;
John Bauman66b8ab22014-05-06 15:57:45 -0400237 default: break;
238 }
239
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400240 if (left->getBasicType() != right->getBasicType())
241 {
242 return 0;
John Bauman66b8ab22014-05-06 15:57:45 -0400243 }
244
245 //
246 // Need a new node holding things together then. Make
247 // one and promote it to the right type.
248 //
249 TIntermBinary* node = new TIntermBinary(op);
John Bauman66b8ab22014-05-06 15:57:45 -0400250 node->setLine(line);
251
252 node->setLeft(left);
253 node->setRight(right);
254 if (!node->promote(infoSink))
255 return 0;
256
257 //
258 // See if we can fold constants.
259 //
John Bauman66b8ab22014-05-06 15:57:45 -0400260 TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion();
261 TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion();
262 if (leftTempConstant && rightTempConstant) {
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400263 TIntermTyped *typedReturnNode = leftTempConstant->fold(node->getOp(), rightTempConstant, infoSink);
John Bauman66b8ab22014-05-06 15:57:45 -0400264
265 if (typedReturnNode)
266 return typedReturnNode;
267 }
268
269 return node;
270}
271
272//
273// Connect two nodes through an assignment.
274//
275// Returns the added node.
276//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400277TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400278{
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400279 if (left->getType().getStruct() || right->getType().getStruct())
280 {
281 if (left->getType() != right->getType())
282 {
283 return 0;
284 }
285 }
286
John Bauman66b8ab22014-05-06 15:57:45 -0400287 TIntermBinary* node = new TIntermBinary(op);
John Bauman66b8ab22014-05-06 15:57:45 -0400288 node->setLine(line);
289
John Bauman66b8ab22014-05-06 15:57:45 -0400290 node->setLeft(left);
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400291 node->setRight(right);
John Bauman66b8ab22014-05-06 15:57:45 -0400292 if (! node->promote(infoSink))
293 return 0;
294
295 return node;
296}
297
298//
299// Connect two nodes through an index operator, where the left node is the base
300// of an array or struct, and the right node is a direct or indirect offset.
301//
302// Returns the added node.
303// The caller should set the type of the returned node.
304//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400305TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400306{
307 TIntermBinary* node = new TIntermBinary(op);
John Bauman66b8ab22014-05-06 15:57:45 -0400308 node->setLine(line);
309 node->setLeft(base);
310 node->setRight(index);
311
312 // caller should set the type
313
314 return node;
315}
316
317//
318// Add one node as the parent of another that it operates on.
319//
320// Returns the added node.
321//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400322TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400323{
324 TIntermUnary* node;
325 TIntermTyped* child = childNode->getAsTyped();
326
327 if (child == 0) {
328 infoSink.info.message(EPrefixInternalError, "Bad type in AddUnaryMath", line);
329 return 0;
330 }
331
332 switch (op) {
Alexis Hetud061e422015-05-13 16:37:50 -0400333 case EOpBitwiseNot:
Alexis Hetu9085c8d2015-06-01 13:48:07 -0400334 if (!IsInteger(child->getType().getBasicType()) || child->getType().isMatrix() || child->getType().isArray()) {
Alexis Hetud061e422015-05-13 16:37:50 -0400335 return 0;
336 }
337 break;
338
John Bauman66b8ab22014-05-06 15:57:45 -0400339 case EOpLogicalNot:
340 if (child->getType().getBasicType() != EbtBool || child->getType().isMatrix() || child->getType().isArray() || child->getType().isVector()) {
341 return 0;
342 }
343 break;
344
345 case EOpPostIncrement:
346 case EOpPreIncrement:
347 case EOpPostDecrement:
348 case EOpPreDecrement:
349 case EOpNegative:
350 if (child->getType().getBasicType() == EbtStruct || child->getType().isArray())
351 return 0;
352 default: break;
353 }
354
John Bauman66b8ab22014-05-06 15:57:45 -0400355 TIntermConstantUnion *childTempConstant = 0;
356 if (child->getAsConstantUnion())
357 childTempConstant = child->getAsConstantUnion();
358
359 //
360 // Make a new node for the operator.
361 //
362 node = new TIntermUnary(op);
John Bauman66b8ab22014-05-06 15:57:45 -0400363 node->setLine(line);
364 node->setOperand(child);
365
366 if (! node->promote(infoSink))
367 return 0;
368
369 if (childTempConstant) {
370 TIntermTyped* newChild = childTempConstant->fold(op, 0, infoSink);
371
372 if (newChild)
373 return newChild;
374 }
375
376 return node;
377}
378
379//
380// This is the safe way to change the operator on an aggregate, as it
381// does lots of error checking and fixing. Especially for establishing
382// a function call's operation on it's set of parameters. Sequences
383// of instructions are also aggregates, but they just direnctly set
384// their operator to EOpSequence.
385//
386// Returns an aggregate node, which could be the one passed in if
387// it was already an aggregate but no operator was set.
388//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400389TIntermAggregate* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator op, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400390{
391 TIntermAggregate* aggNode;
392
393 //
394 // Make sure we have an aggregate. If not turn it into one.
395 //
396 if (node) {
397 aggNode = node->getAsAggregate();
398 if (aggNode == 0 || aggNode->getOp() != EOpNull) {
399 //
400 // Make an aggregate containing this node.
401 //
402 aggNode = new TIntermAggregate();
403 aggNode->getSequence().push_back(node);
John Bauman66b8ab22014-05-06 15:57:45 -0400404 }
405 } else
406 aggNode = new TIntermAggregate();
407
408 //
409 // Set the operator.
410 //
411 aggNode->setOp(op);
John Bauman66b8ab22014-05-06 15:57:45 -0400412
413 return aggNode;
414}
415
416//
John Bauman66b8ab22014-05-06 15:57:45 -0400417// Safe way to combine two nodes into an aggregate. Works with null pointers,
418// a node that's not a aggregate yet, etc.
419//
420// Returns the resulting aggregate, unless 0 was passed in for
421// both existing nodes.
422//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400423TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400424{
425 if (left == 0 && right == 0)
426 return 0;
427
428 TIntermAggregate* aggNode = 0;
429 if (left)
430 aggNode = left->getAsAggregate();
431 if (!aggNode || aggNode->getOp() != EOpNull) {
432 aggNode = new TIntermAggregate;
433 if (left)
434 aggNode->getSequence().push_back(left);
435 }
436
437 if (right)
438 aggNode->getSequence().push_back(right);
439
Alexis Hetu253fdd12015-07-07 15:12:46 -0400440 aggNode->setLine(line);
John Bauman66b8ab22014-05-06 15:57:45 -0400441
442 return aggNode;
443}
444
445//
446// Turn an existing node into an aggregate.
447//
448// Returns an aggregate, unless 0 was passed in for the existing node.
449//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400450TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400451{
452 if (node == 0)
453 return 0;
454
455 TIntermAggregate* aggNode = new TIntermAggregate;
456 aggNode->getSequence().push_back(node);
457
Alexis Hetu253fdd12015-07-07 15:12:46 -0400458 aggNode->setLine(line);
John Bauman66b8ab22014-05-06 15:57:45 -0400459
460 return aggNode;
461}
462
463//
464// For "if" test nodes. There are three children; a condition,
465// a true path, and a false path. The two paths are in the
466// nodePair.
467//
468// Returns the selection node created.
469//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400470TIntermNode* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nodePair, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400471{
472 //
473 // For compile time constant selections, prune the code and
474 // test now.
475 //
476
477 if (cond->getAsTyped() && cond->getAsTyped()->getAsConstantUnion()) {
Nicolas Capens198529d2015-02-10 13:54:19 -0500478 if (cond->getAsConstantUnion()->getBConst(0) == true)
John Bauman66b8ab22014-05-06 15:57:45 -0400479 return nodePair.node1 ? setAggregateOperator(nodePair.node1, EOpSequence, nodePair.node1->getLine()) : NULL;
480 else
481 return nodePair.node2 ? setAggregateOperator(nodePair.node2, EOpSequence, nodePair.node2->getLine()) : NULL;
482 }
483
484 TIntermSelection* node = new TIntermSelection(cond, nodePair.node1, nodePair.node2);
485 node->setLine(line);
486
487 return node;
488}
489
490
Alexis Hetu253fdd12015-07-07 15:12:46 -0400491TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400492{
Nicolas Capens31ad2aa2015-02-26 13:14:27 -0500493 if (left->getType().getQualifier() == EvqConstExpr && right->getType().getQualifier() == EvqConstExpr) {
John Bauman66b8ab22014-05-06 15:57:45 -0400494 return right;
495 } else {
496 TIntermTyped *commaAggregate = growAggregate(left, right, line);
497 commaAggregate->getAsAggregate()->setOp(EOpComma);
498 commaAggregate->setType(right->getType());
499 commaAggregate->getTypePointer()->setQualifier(EvqTemporary);
500 return commaAggregate;
501 }
502}
503
504//
505// For "?:" test nodes. There are three children; a condition,
506// a true path, and a false path. The two paths are specified
507// as separate parameters.
508//
509// Returns the selection node created, or 0 if one could not be.
510//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400511TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400512{
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400513 if (trueBlock->getType() != falseBlock->getType())
514 {
515 return 0;
John Bauman66b8ab22014-05-06 15:57:45 -0400516 }
517
518 //
519 // See if all the operands are constant, then fold it otherwise not.
520 //
521
522 if (cond->getAsConstantUnion() && trueBlock->getAsConstantUnion() && falseBlock->getAsConstantUnion()) {
Nicolas Capens198529d2015-02-10 13:54:19 -0500523 if (cond->getAsConstantUnion()->getBConst(0))
John Bauman66b8ab22014-05-06 15:57:45 -0400524 return trueBlock;
525 else
526 return falseBlock;
527 }
528
529 //
530 // Make a selection node.
531 //
532 TIntermSelection* node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType());
533 node->getTypePointer()->setQualifier(EvqTemporary);
534 node->setLine(line);
535
536 return node;
537}
538
Alexis Hetu76a343a2015-06-04 17:21:22 -0400539TIntermSwitch *TIntermediate::addSwitch(TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &line)
540{
541 TIntermSwitch *node = new TIntermSwitch(init, statementList);
542 node->setLine(line);
543
544 return node;
545}
546
547TIntermCase *TIntermediate::addCase(TIntermTyped *condition, const TSourceLoc &line)
548{
549 TIntermCase *node = new TIntermCase(condition);
550 node->setLine(line);
551
552 return node;
553}
554
John Bauman66b8ab22014-05-06 15:57:45 -0400555//
556// Constant terminal nodes. Has a union that contains bool, float or int constants
557//
558// Returns the constant union node created.
559//
560
Alexis Hetu253fdd12015-07-07 15:12:46 -0400561TIntermConstantUnion* TIntermediate::addConstantUnion(ConstantUnion* unionArrayPointer, const TType& t, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400562{
563 TIntermConstantUnion* node = new TIntermConstantUnion(unionArrayPointer, t);
564 node->setLine(line);
565
566 return node;
567}
568
Alexis Hetu253fdd12015-07-07 15:12:46 -0400569TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400570{
571
572 TIntermAggregate* node = new TIntermAggregate(EOpSequence);
573
574 node->setLine(line);
575 TIntermConstantUnion* constIntNode;
576 TIntermSequence &sequenceVector = node->getSequence();
577 ConstantUnion* unionArray;
578
579 for (int i = 0; i < fields.num; i++) {
580 unionArray = new ConstantUnion[1];
581 unionArray->setIConst(fields.offsets[i]);
Nicolas Capens31ad2aa2015-02-26 13:14:27 -0500582 constIntNode = addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConstExpr), line);
John Bauman66b8ab22014-05-06 15:57:45 -0400583 sequenceVector.push_back(constIntNode);
584 }
585
586 return node;
587}
588
589//
590// Create loop nodes.
591//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400592TIntermNode* TIntermediate::addLoop(TLoopType type, TIntermNode* init, TIntermTyped* cond, TIntermTyped* expr, TIntermNode* body, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400593{
594 TIntermNode* node = new TIntermLoop(type, init, cond, expr, body);
595 node->setLine(line);
596
597 return node;
598}
599
600//
601// Add branches.
602//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400603TIntermBranch* TIntermediate::addBranch(TOperator branchOp, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400604{
605 return addBranch(branchOp, 0, line);
606}
607
Alexis Hetu253fdd12015-07-07 15:12:46 -0400608TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expression, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400609{
610 TIntermBranch* node = new TIntermBranch(branchOp, expression);
611 node->setLine(line);
612
613 return node;
614}
615
616//
617// This is to be executed once the final root is put on top by the parsing
618// process.
619//
620bool TIntermediate::postProcess(TIntermNode* root)
621{
622 if (root == 0)
623 return true;
624
625 //
626 // First, finish off the top level sequence, if any
627 //
628 TIntermAggregate* aggRoot = root->getAsAggregate();
629 if (aggRoot && aggRoot->getOp() == EOpNull)
630 aggRoot->setOp(EOpSequence);
631
632 return true;
633}
634
John Bauman66b8ab22014-05-06 15:57:45 -0400635////////////////////////////////////////////////////////////////
636//
637// Member functions of the nodes used for building the tree.
638//
639////////////////////////////////////////////////////////////////
640
641//
642// Say whether or not an operation node changes the value of a variable.
643//
644// Returns true if state is modified.
645//
646bool TIntermOperator::modifiesState() const
647{
648 switch (op) {
649 case EOpPostIncrement:
650 case EOpPostDecrement:
651 case EOpPreIncrement:
652 case EOpPreDecrement:
653 case EOpAssign:
654 case EOpAddAssign:
655 case EOpSubAssign:
656 case EOpMulAssign:
657 case EOpVectorTimesMatrixAssign:
658 case EOpVectorTimesScalarAssign:
659 case EOpMatrixTimesScalarAssign:
660 case EOpMatrixTimesMatrixAssign:
661 case EOpDivAssign:
Alexis Hetu17809052015-05-13 11:28:22 -0400662 case EOpIModAssign:
663 case EOpBitShiftLeftAssign:
664 case EOpBitShiftRightAssign:
665 case EOpBitwiseAndAssign:
666 case EOpBitwiseXorAssign:
667 case EOpBitwiseOrAssign:
John Bauman66b8ab22014-05-06 15:57:45 -0400668 return true;
669 default:
670 return false;
671 }
672}
673
674//
675// returns true if the operator is for one of the constructors
676//
677bool TIntermOperator::isConstructor() const
678{
679 switch (op) {
680 case EOpConstructVec2:
681 case EOpConstructVec3:
682 case EOpConstructVec4:
683 case EOpConstructMat2:
Alexis Hetu00106d42015-04-23 11:45:35 -0400684 case EOpConstructMat2x3:
685 case EOpConstructMat2x4:
686 case EOpConstructMat3x2:
John Bauman66b8ab22014-05-06 15:57:45 -0400687 case EOpConstructMat3:
Alexis Hetu00106d42015-04-23 11:45:35 -0400688 case EOpConstructMat3x4:
689 case EOpConstructMat4x2:
690 case EOpConstructMat4x3:
John Bauman66b8ab22014-05-06 15:57:45 -0400691 case EOpConstructMat4:
692 case EOpConstructFloat:
693 case EOpConstructIVec2:
694 case EOpConstructIVec3:
695 case EOpConstructIVec4:
696 case EOpConstructInt:
Nicolas Capense4b1b1d2015-02-17 17:26:01 -0500697 case EOpConstructUVec2:
698 case EOpConstructUVec3:
699 case EOpConstructUVec4:
Nicolas Capens3c20f802015-02-17 17:17:20 -0500700 case EOpConstructUInt:
John Bauman66b8ab22014-05-06 15:57:45 -0400701 case EOpConstructBVec2:
702 case EOpConstructBVec3:
703 case EOpConstructBVec4:
704 case EOpConstructBool:
705 case EOpConstructStruct:
706 return true;
707 default:
708 return false;
709 }
710}
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400711
John Bauman66b8ab22014-05-06 15:57:45 -0400712//
713// Make sure the type of a unary operator is appropriate for its
714// combination of operation and operand type.
715//
716// Returns false in nothing makes sense.
717//
718bool TIntermUnary::promote(TInfoSink&)
719{
720 switch (op) {
721 case EOpLogicalNot:
722 if (operand->getBasicType() != EbtBool)
723 return false;
724 break;
Alexis Hetud061e422015-05-13 16:37:50 -0400725 case EOpBitwiseNot:
Alexis Hetu9085c8d2015-06-01 13:48:07 -0400726 if (!IsInteger(operand->getBasicType()))
Alexis Hetud061e422015-05-13 16:37:50 -0400727 return false;
728 break;
John Bauman66b8ab22014-05-06 15:57:45 -0400729 case EOpNegative:
730 case EOpPostIncrement:
731 case EOpPostDecrement:
732 case EOpPreIncrement:
733 case EOpPreDecrement:
734 if (operand->getBasicType() == EbtBool)
735 return false;
736 break;
737
738 // operators for built-ins are already type checked against their prototype
739 case EOpAny:
740 case EOpAll:
741 case EOpVectorLogicalNot:
742 return true;
743
744 default:
745 if (operand->getBasicType() != EbtFloat)
746 return false;
747 }
748
749 setType(operand->getType());
750
751 // Unary operations results in temporary variables unless const.
Nicolas Capens31ad2aa2015-02-26 13:14:27 -0500752 if (operand->getQualifier() != EvqConstExpr) {
John Bauman66b8ab22014-05-06 15:57:45 -0400753 getTypePointer()->setQualifier(EvqTemporary);
754 }
755
756 return true;
757}
758
759//
760// Establishes the type of the resultant operation, as well as
761// makes the operator the correct one for the operands.
762//
763// Returns false if operator can't work on operands.
764//
765bool TIntermBinary::promote(TInfoSink& infoSink)
766{
Alexis Hetue5246692015-06-18 12:34:52 -0400767 ASSERT(left->isArray() == right->isArray());
John Bauman66b8ab22014-05-06 15:57:45 -0400768
769 // GLSL ES 2.0 does not support implicit type casting.
770 // So the basic type should always match.
771 if (left->getBasicType() != right->getBasicType())
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400772 {
John Bauman66b8ab22014-05-06 15:57:45 -0400773 return false;
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400774 }
John Bauman66b8ab22014-05-06 15:57:45 -0400775
776 //
777 // Base assumption: just make the type the same as the left
778 // operand. Then only deviations from this need be coded.
779 //
780 setType(left->getType());
781
782 // The result gets promoted to the highest precision.
783 TPrecision higherPrecision = GetHigherPrecision(left->getPrecision(), right->getPrecision());
784 getTypePointer()->setPrecision(higherPrecision);
785
786 // Binary operations results in temporary variables unless both
787 // operands are const.
Nicolas Capens31ad2aa2015-02-26 13:14:27 -0500788 if (left->getQualifier() != EvqConstExpr || right->getQualifier() != EvqConstExpr) {
John Bauman66b8ab22014-05-06 15:57:45 -0400789 getTypePointer()->setQualifier(EvqTemporary);
790 }
791
Alexis Hetud061e422015-05-13 16:37:50 -0400792 int primarySize = std::max(left->getNominalSize(), right->getNominalSize());
John Bauman66b8ab22014-05-06 15:57:45 -0400793
794 //
795 // All scalars. Code after this test assumes this case is removed!
796 //
Alexis Hetud061e422015-05-13 16:37:50 -0400797 if (primarySize == 1) {
John Bauman66b8ab22014-05-06 15:57:45 -0400798 switch (op) {
799 //
800 // Promote to conditional
801 //
802 case EOpEqual:
803 case EOpNotEqual:
804 case EOpLessThan:
805 case EOpGreaterThan:
806 case EOpLessThanEqual:
807 case EOpGreaterThanEqual:
808 setType(TType(EbtBool, EbpUndefined));
809 break;
810
811 //
812 // And and Or operate on conditionals
813 //
814 case EOpLogicalAnd:
815 case EOpLogicalOr:
Alexis Hetud061e422015-05-13 16:37:50 -0400816 case EOpLogicalXor:
John Bauman66b8ab22014-05-06 15:57:45 -0400817 // Both operands must be of type bool.
818 if (left->getBasicType() != EbtBool || right->getBasicType() != EbtBool)
819 return false;
820 setType(TType(EbtBool, EbpUndefined));
821 break;
822
823 default:
824 break;
825 }
826 return true;
827 }
828
829 // If we reach here, at least one of the operands is vector or matrix.
830 // The other operand could be a scalar, vector, or matrix.
John Bauman66b8ab22014-05-06 15:57:45 -0400831 // Can these two operands be combined?
832 //
833 TBasicType basicType = left->getBasicType();
834 switch (op) {
835 case EOpMul:
836 if (!left->isMatrix() && right->isMatrix()) {
837 if (left->isVector())
Alexis Hetu00106d42015-04-23 11:45:35 -0400838 {
John Bauman66b8ab22014-05-06 15:57:45 -0400839 op = EOpVectorTimesMatrix;
Alexis Hetu00106d42015-04-23 11:45:35 -0400840 setType(TType(basicType, higherPrecision, EvqTemporary,
841 static_cast<unsigned char>(right->getNominalSize()), 1));
842 }
John Bauman66b8ab22014-05-06 15:57:45 -0400843 else {
844 op = EOpMatrixTimesScalar;
Alexis Hetu00106d42015-04-23 11:45:35 -0400845 setType(TType(basicType, higherPrecision, EvqTemporary,
846 static_cast<unsigned char>(right->getNominalSize()), static_cast<unsigned char>(right->getSecondarySize())));
John Bauman66b8ab22014-05-06 15:57:45 -0400847 }
848 } else if (left->isMatrix() && !right->isMatrix()) {
849 if (right->isVector()) {
850 op = EOpMatrixTimesVector;
Alexis Hetu00106d42015-04-23 11:45:35 -0400851 setType(TType(basicType, higherPrecision, EvqTemporary,
852 static_cast<unsigned char>(left->getSecondarySize()), 1));
John Bauman66b8ab22014-05-06 15:57:45 -0400853 } else {
854 op = EOpMatrixTimesScalar;
855 }
856 } else if (left->isMatrix() && right->isMatrix()) {
857 op = EOpMatrixTimesMatrix;
Alexis Hetu00106d42015-04-23 11:45:35 -0400858 setType(TType(basicType, higherPrecision, EvqTemporary,
859 static_cast<unsigned char>(right->getNominalSize()), static_cast<unsigned char>(left->getSecondarySize())));
John Bauman66b8ab22014-05-06 15:57:45 -0400860 } else if (!left->isMatrix() && !right->isMatrix()) {
861 if (left->isVector() && right->isVector()) {
862 // leave as component product
863 } else if (left->isVector() || right->isVector()) {
864 op = EOpVectorTimesScalar;
Alexis Hetu00106d42015-04-23 11:45:35 -0400865 setType(TType(basicType, higherPrecision, EvqTemporary,
866 static_cast<unsigned char>(primarySize), 1));
John Bauman66b8ab22014-05-06 15:57:45 -0400867 }
868 } else {
869 infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
870 return false;
871 }
Alexis Hetu00106d42015-04-23 11:45:35 -0400872
873 if(!ValidateMultiplication(op, left->getType(), right->getType()))
874 {
875 return false;
876 }
John Bauman66b8ab22014-05-06 15:57:45 -0400877 break;
878 case EOpMulAssign:
879 if (!left->isMatrix() && right->isMatrix()) {
880 if (left->isVector())
881 op = EOpVectorTimesMatrixAssign;
882 else {
883 return false;
884 }
885 } else if (left->isMatrix() && !right->isMatrix()) {
886 if (right->isVector()) {
887 return false;
888 } else {
889 op = EOpMatrixTimesScalarAssign;
890 }
891 } else if (left->isMatrix() && right->isMatrix()) {
892 op = EOpMatrixTimesMatrixAssign;
Alexis Hetu00106d42015-04-23 11:45:35 -0400893 setType(TType(basicType, higherPrecision, EvqTemporary,
894 static_cast<unsigned char>(right->getNominalSize()), static_cast<unsigned char>(left->getSecondarySize())));
John Bauman66b8ab22014-05-06 15:57:45 -0400895 } else if (!left->isMatrix() && !right->isMatrix()) {
896 if (left->isVector() && right->isVector()) {
897 // leave as component product
898 } else if (left->isVector() || right->isVector()) {
899 if (! left->isVector())
900 return false;
901 op = EOpVectorTimesScalarAssign;
Alexis Hetu00106d42015-04-23 11:45:35 -0400902 setType(TType(basicType, higherPrecision, EvqTemporary,
903 static_cast<unsigned char>(left->getNominalSize()), 1));
John Bauman66b8ab22014-05-06 15:57:45 -0400904 }
905 } else {
906 infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
907 return false;
908 }
Alexis Hetu00106d42015-04-23 11:45:35 -0400909
910 if(!ValidateMultiplication(op, left->getType(), right->getType()))
911 {
912 return false;
913 }
John Bauman66b8ab22014-05-06 15:57:45 -0400914 break;
915
916 case EOpAssign:
917 case EOpInitialize:
Alexis Hetu00106d42015-04-23 11:45:35 -0400918 // No more additional checks are needed.
919 if ((left->getNominalSize() != right->getNominalSize()) ||
920 (left->getSecondarySize() != right->getSecondarySize()))
921 return false;
922 break;
John Bauman66b8ab22014-05-06 15:57:45 -0400923 case EOpAdd:
924 case EOpSub:
925 case EOpDiv:
Alexis Hetud061e422015-05-13 16:37:50 -0400926 case EOpIMod:
927 case EOpBitShiftLeft:
928 case EOpBitShiftRight:
929 case EOpBitwiseAnd:
930 case EOpBitwiseXor:
931 case EOpBitwiseOr:
John Bauman66b8ab22014-05-06 15:57:45 -0400932 case EOpAddAssign:
933 case EOpSubAssign:
934 case EOpDivAssign:
Alexis Hetu17809052015-05-13 11:28:22 -0400935 case EOpIModAssign:
936 case EOpBitShiftLeftAssign:
937 case EOpBitShiftRightAssign:
938 case EOpBitwiseAndAssign:
939 case EOpBitwiseXorAssign:
940 case EOpBitwiseOrAssign:
John Bauman66b8ab22014-05-06 15:57:45 -0400941 if ((left->isMatrix() && right->isVector()) ||
942 (left->isVector() && right->isMatrix()))
943 return false;
Alexis Hetud061e422015-05-13 16:37:50 -0400944
945 // Are the sizes compatible?
946 if(left->getNominalSize() != right->getNominalSize() ||
947 left->getSecondarySize() != right->getSecondarySize())
948 {
949 // If the nominal sizes of operands do not match:
950 // One of them must be a scalar.
951 if(!left->isScalar() && !right->isScalar())
952 return false;
953
954 // In the case of compound assignment other than multiply-assign,
955 // the right side needs to be a scalar. Otherwise a vector/matrix
956 // would be assigned to a scalar. A scalar can't be shifted by a
957 // vector either.
958 if(!right->isScalar() && (modifiesState() || op == EOpBitShiftLeft || op == EOpBitShiftRight))
959 return false;
960 }
961
962 {
Alexis Hetu00106d42015-04-23 11:45:35 -0400963 const int secondarySize = std::max(
964 left->getSecondarySize(), right->getSecondarySize());
Alexis Hetud061e422015-05-13 16:37:50 -0400965 setType(TType(basicType, higherPrecision, EvqTemporary,
966 static_cast<unsigned char>(primarySize), static_cast<unsigned char>(secondarySize)));
967 if(left->isArray())
968 {
969 ASSERT(left->getArraySize() == right->getArraySize());
970 type.setArraySize(left->getArraySize());
971 }
972 }
John Bauman66b8ab22014-05-06 15:57:45 -0400973 break;
974
975 case EOpEqual:
976 case EOpNotEqual:
977 case EOpLessThan:
978 case EOpGreaterThan:
979 case EOpLessThanEqual:
980 case EOpGreaterThanEqual:
Alexis Hetu00106d42015-04-23 11:45:35 -0400981 if ((left->getNominalSize() != right->getNominalSize()) ||
982 (left->getSecondarySize() != right->getSecondarySize()))
John Bauman66b8ab22014-05-06 15:57:45 -0400983 return false;
984 setType(TType(EbtBool, EbpUndefined));
985 break;
986
Alexis Hetu3815b6c2015-05-27 11:21:37 -0400987 case EOpOuterProduct:
988 if(!left->isVector() || !right->isVector())
989 return false;
990 setType(TType(EbtFloat, right->getNominalSize(), left->getNominalSize()));
991 break;
992
993 case EOpTranspose:
994 if(!right->isMatrix())
995 return false;
996 setType(TType(EbtFloat, right->getSecondarySize(), right->getNominalSize()));
997 break;
998
999 case EOpDeterminant:
1000 if(!right->isMatrix())
1001 return false;
1002 setType(TType(EbtFloat));
1003 break;
1004
1005 case EOpInverse:
1006 if(!right->isMatrix() || right->getNominalSize() != right->getSecondarySize())
1007 return false;
1008 setType(right->getType());
1009 break;
1010
John Bauman66b8ab22014-05-06 15:57:45 -04001011 default:
1012 return false;
1013 }
1014
1015 return true;
1016}
1017
1018bool CompareStruct(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
1019{
Alexis Hetua8b364b2015-06-10 11:48:40 -04001020 const TFieldList& fields = leftNodeType.getStruct()->fields();
John Bauman66b8ab22014-05-06 15:57:45 -04001021
Alexis Hetua8b364b2015-06-10 11:48:40 -04001022 size_t structSize = fields.size();
John Bauman66b8ab22014-05-06 15:57:45 -04001023 int index = 0;
1024
1025 for (size_t j = 0; j < structSize; j++) {
Alexis Hetua8b364b2015-06-10 11:48:40 -04001026 int size = fields[j]->type()->getObjectSize();
John Bauman66b8ab22014-05-06 15:57:45 -04001027 for (int i = 0; i < size; i++) {
Alexis Hetua8b364b2015-06-10 11:48:40 -04001028 if (fields[j]->type()->getBasicType() == EbtStruct) {
1029 if (!CompareStructure(*(fields[j]->type()), &rightUnionArray[index], &leftUnionArray[index]))
John Bauman66b8ab22014-05-06 15:57:45 -04001030 return false;
1031 } else {
1032 if (leftUnionArray[index] != rightUnionArray[index])
1033 return false;
1034 index++;
1035 }
1036
1037 }
1038 }
1039 return true;
1040}
1041
1042bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
1043{
1044 if (leftNodeType.isArray()) {
1045 TType typeWithoutArrayness = leftNodeType;
1046 typeWithoutArrayness.clearArrayness();
1047
1048 int arraySize = leftNodeType.getArraySize();
1049
1050 for (int i = 0; i < arraySize; ++i) {
1051 int offset = typeWithoutArrayness.getObjectSize() * i;
1052 if (!CompareStruct(typeWithoutArrayness, &rightUnionArray[offset], &leftUnionArray[offset]))
1053 return false;
1054 }
1055 } else
1056 return CompareStruct(leftNodeType, rightUnionArray, leftUnionArray);
1057
1058 return true;
1059}
1060
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001061float determinant2(float m00, float m01, float m10, float m11)
1062{
1063 return m00 * m11 - m01 * m10;
1064}
1065
1066float determinant3(float m00, float m01, float m02,
1067 float m10, float m11, float m12,
1068 float m20, float m21, float m22)
1069{
1070 return m00 * determinant2(m11, m12, m21, m22) -
1071 m10 * determinant2(m01, m02, m21, m22) +
1072 m20 * determinant2(m01, m02, m11, m12);
1073}
1074
1075float determinant4(float m00, float m01, float m02, float m03,
1076 float m10, float m11, float m12, float m13,
1077 float m20, float m21, float m22, float m23,
1078 float m30, float m31, float m32, float m33)
1079{
1080 return m00 * determinant3(m11, m12, m13, m21, m22, m23, m31, m32, m33) -
1081 m10 * determinant3(m01, m02, m03, m21, m22, m23, m31, m32, m33) +
1082 m20 * determinant3(m01, m02, m03, m11, m12, m13, m31, m32, m33) -
1083 m30 * determinant3(m01, m02, m03, m11, m12, m13, m21, m22, m23);
1084}
1085
1086float ComputeDeterminant(int size, ConstantUnion* unionArray)
1087{
1088 switch(size)
1089 {
1090 case 2:
1091 return determinant2(unionArray[0].getFConst(),
1092 unionArray[1].getFConst(),
1093 unionArray[2].getFConst(),
1094 unionArray[3].getFConst());
1095 case 3:
1096 return determinant3(unionArray[0].getFConst(),
1097 unionArray[1].getFConst(),
1098 unionArray[2].getFConst(),
1099 unionArray[3].getFConst(),
1100 unionArray[4].getFConst(),
1101 unionArray[5].getFConst(),
1102 unionArray[6].getFConst(),
1103 unionArray[7].getFConst(),
1104 unionArray[8].getFConst());
1105 case 4:
1106 return determinant4(unionArray[0].getFConst(),
1107 unionArray[1].getFConst(),
1108 unionArray[2].getFConst(),
1109 unionArray[3].getFConst(),
1110 unionArray[4].getFConst(),
1111 unionArray[5].getFConst(),
1112 unionArray[6].getFConst(),
1113 unionArray[7].getFConst(),
1114 unionArray[8].getFConst(),
1115 unionArray[9].getFConst(),
1116 unionArray[10].getFConst(),
1117 unionArray[11].getFConst(),
1118 unionArray[12].getFConst(),
1119 unionArray[13].getFConst(),
1120 unionArray[14].getFConst(),
1121 unionArray[15].getFConst());
1122 default:
Nicolas Capens3713cd42015-06-22 10:41:54 -04001123 UNREACHABLE(size);
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001124 return 0.0f;
1125 }
1126}
1127
1128ConstantUnion* CreateInverse(TIntermConstantUnion* node, ConstantUnion* unionArray)
1129{
1130 ConstantUnion* tempConstArray = 0;
1131 int size = node->getNominalSize();
1132 float determinant = ComputeDeterminant(size, unionArray);
1133 if(determinant != 0.0f)
1134 {
1135 float invDet = 1.0f / determinant;
1136 tempConstArray = new ConstantUnion[size*size];
1137 switch(size)
1138 {
1139 case 2:
1140 {
1141 float m00 = unionArray[0].getFConst(); // Matrix is:
1142 float m01 = unionArray[1].getFConst(); // (m00, m01)
1143 float m10 = unionArray[2].getFConst(); // (m10, m11)
1144 float m11 = unionArray[3].getFConst();
1145 tempConstArray[0].setFConst( invDet * m11);
1146 tempConstArray[1].setFConst(-invDet * m01);
1147 tempConstArray[2].setFConst(-invDet * m10);
1148 tempConstArray[3].setFConst( invDet * m00);
1149 }
1150 break;
1151 case 3:
1152 {
1153 float m00 = unionArray[0].getFConst(); // Matrix is:
1154 float m01 = unionArray[1].getFConst(); // (m00, m01, m02)
1155 float m02 = unionArray[2].getFConst(); // (m10, m11, m12)
1156 float m10 = unionArray[3].getFConst(); // (m20, m21, m22)
1157 float m11 = unionArray[4].getFConst();
1158 float m12 = unionArray[5].getFConst();
1159 float m20 = unionArray[6].getFConst();
1160 float m21 = unionArray[7].getFConst();
1161 float m22 = unionArray[8].getFConst();
1162 tempConstArray[0].setFConst(invDet * determinant2(m11, m12, m21, m22)); // m00 = invDet * (m11 * m22 - m12 * m21)
1163 tempConstArray[1].setFConst(invDet * determinant2(m12, m10, m22, m20)); // m01 = -invDet * (m10 * m22 - m12 * m20)
1164 tempConstArray[2].setFConst(invDet * determinant2(m10, m11, m20, m21)); // m02 = invDet * (m10 * m21 - m11 * m20)
1165 tempConstArray[3].setFConst(invDet * determinant2(m21, m22, m01, m02)); // m10 = -invDet * (m01 * m22 - m02 * m21)
1166 tempConstArray[4].setFConst(invDet * determinant2(m00, m02, m20, m22)); // m11 = invDet * (m00 * m22 - m02 * m20)
1167 tempConstArray[5].setFConst(invDet * determinant2(m20, m21, m00, m01)); // m12 = -invDet * (m00 * m21 - m01 * m20)
1168 tempConstArray[6].setFConst(invDet * determinant2(m01, m02, m11, m12)); // m20 = invDet * (m01 * m12 - m02 * m11)
1169 tempConstArray[7].setFConst(invDet * determinant2(m10, m12, m00, m02)); // m21 = -invDet * (m00 * m12 - m02 * m10)
1170 tempConstArray[8].setFConst(invDet * determinant2(m00, m01, m10, m11)); // m22 = invDet * (m00 * m11 - m01 * m10)
1171 }
1172 break;
1173 case 4:
1174 {
1175 float m00 = unionArray[0].getFConst(); // Matrix is:
1176 float m01 = unionArray[1].getFConst(); // (m00, m01, m02, m03)
1177 float m02 = unionArray[2].getFConst(); // (m10, m11, m12, m13)
1178 float m03 = unionArray[3].getFConst(); // (m20, m21, m22, m23)
1179 float m10 = unionArray[4].getFConst(); // (m30, m31, m32, m33)
1180 float m11 = unionArray[5].getFConst();
1181 float m12 = unionArray[6].getFConst();
1182 float m13 = unionArray[7].getFConst();
1183 float m20 = unionArray[8].getFConst();
1184 float m21 = unionArray[9].getFConst();
1185 float m22 = unionArray[10].getFConst();
1186 float m23 = unionArray[11].getFConst();
1187 float m30 = unionArray[12].getFConst();
1188 float m31 = unionArray[13].getFConst();
1189 float m32 = unionArray[14].getFConst();
1190 float m33 = unionArray[15].getFConst();
1191 tempConstArray[ 0].setFConst( invDet * determinant3(m11, m12, m13, m21, m22, m23, m31, m32, m33)); // m00
1192 tempConstArray[ 1].setFConst(-invDet * determinant3(m10, m12, m13, m20, m22, m23, m30, m32, m33)); // m01
1193 tempConstArray[ 2].setFConst( invDet * determinant3(m10, m11, m13, m20, m21, m23, m30, m31, m33)); // m02
1194 tempConstArray[ 3].setFConst(-invDet * determinant3(m10, m11, m12, m20, m21, m22, m30, m31, m32)); // m03
1195 tempConstArray[ 4].setFConst( invDet * determinant3(m01, m02, m03, m21, m22, m23, m31, m32, m33)); // m10
1196 tempConstArray[ 5].setFConst(-invDet * determinant3(m00, m02, m03, m20, m22, m23, m30, m32, m33)); // m11
1197 tempConstArray[ 6].setFConst( invDet * determinant3(m00, m01, m03, m20, m21, m23, m30, m31, m33)); // m12
1198 tempConstArray[ 7].setFConst(-invDet * determinant3(m00, m01, m02, m20, m21, m22, m30, m31, m32)); // m13
1199 tempConstArray[ 8].setFConst( invDet * determinant3(m01, m02, m03, m11, m12, m13, m31, m32, m33)); // m20
1200 tempConstArray[ 9].setFConst(-invDet * determinant3(m00, m02, m03, m10, m12, m13, m30, m32, m33)); // m21
1201 tempConstArray[10].setFConst( invDet * determinant3(m00, m01, m03, m10, m11, m13, m30, m31, m33)); // m22
1202 tempConstArray[11].setFConst(-invDet * determinant3(m00, m01, m02, m10, m11, m12, m30, m31, m32)); // m23
1203 tempConstArray[12].setFConst( invDet * determinant3(m01, m02, m03, m11, m12, m13, m21, m22, m23)); // m30
1204 tempConstArray[13].setFConst(-invDet * determinant3(m00, m02, m03, m10, m12, m13, m20, m22, m23)); // m31
1205 tempConstArray[14].setFConst( invDet * determinant3(m00, m01, m03, m10, m11, m13, m20, m21, m23)); // m32
1206 tempConstArray[15].setFConst(-invDet * determinant3(m00, m01, m02, m10, m11, m12, m20, m21, m22)); // m33
1207 }
1208 break;
1209 default:
Nicolas Capens3713cd42015-06-22 10:41:54 -04001210 UNREACHABLE(size);
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001211 }
1212 }
1213 return tempConstArray;
1214}
1215
John Bauman66b8ab22014-05-06 15:57:45 -04001216//
1217// The fold functions see if an operation on a constant can be done in place,
1218// without generating run-time code.
1219//
1220// Returns the node to keep using, which may or may not be the node passed in.
1221//
1222
1223TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNode, TInfoSink& infoSink)
1224{
1225 ConstantUnion *unionArray = getUnionArrayPointer();
1226 int objectSize = getType().getObjectSize();
1227
1228 if (constantNode) { // binary operations
1229 TIntermConstantUnion *node = constantNode->getAsConstantUnion();
1230 ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
1231 TType returnType = getType();
1232
1233 // for a case like float f = 1.2 + vec4(2,3,4,5);
1234 if (constantNode->getType().getObjectSize() == 1 && objectSize > 1) {
1235 rightUnionArray = new ConstantUnion[objectSize];
1236 for (int i = 0; i < objectSize; ++i)
1237 rightUnionArray[i] = *node->getUnionArrayPointer();
1238 returnType = getType();
1239 } else if (constantNode->getType().getObjectSize() > 1 && objectSize == 1) {
1240 // for a case like float f = vec4(2,3,4,5) + 1.2;
1241 unionArray = new ConstantUnion[constantNode->getType().getObjectSize()];
1242 for (int i = 0; i < constantNode->getType().getObjectSize(); ++i)
1243 unionArray[i] = *getUnionArrayPointer();
1244 returnType = node->getType();
1245 objectSize = constantNode->getType().getObjectSize();
1246 }
1247
1248 ConstantUnion* tempConstArray = 0;
1249 TIntermConstantUnion *tempNode;
1250
1251 bool boolNodeFlag = false;
1252 switch(op) {
1253 case EOpAdd:
1254 tempConstArray = new ConstantUnion[objectSize];
1255 {// support MSVC++6.0
1256 for (int i = 0; i < objectSize; i++)
1257 tempConstArray[i] = unionArray[i] + rightUnionArray[i];
1258 }
1259 break;
1260 case EOpSub:
1261 tempConstArray = new ConstantUnion[objectSize];
1262 {// support MSVC++6.0
1263 for (int i = 0; i < objectSize; i++)
1264 tempConstArray[i] = unionArray[i] - rightUnionArray[i];
1265 }
1266 break;
1267
1268 case EOpMul:
1269 case EOpVectorTimesScalar:
1270 case EOpMatrixTimesScalar:
1271 tempConstArray = new ConstantUnion[objectSize];
1272 {// support MSVC++6.0
1273 for (int i = 0; i < objectSize; i++)
1274 tempConstArray[i] = unionArray[i] * rightUnionArray[i];
1275 }
1276 break;
1277 case EOpMatrixTimesMatrix:
1278 if (getType().getBasicType() != EbtFloat || node->getBasicType() != EbtFloat) {
1279 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix multiply", getLine());
1280 return 0;
1281 }
1282 {// support MSVC++6.0
Alexis Hetu00106d42015-04-23 11:45:35 -04001283 int leftNumCols = getNominalSize();
1284 int leftNumRows = getSecondarySize();
1285 int rightNumCols = node->getNominalSize();
1286 int rightNumRows = node->getSecondarySize();
1287 if(leftNumCols != rightNumRows) {
1288 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix multiply", getLine());
1289 return 0;
1290 }
1291 int tempNumCols = rightNumCols;
1292 int tempNumRows = leftNumRows;
1293 int tempNumAdds = leftNumCols;
1294 tempConstArray = new ConstantUnion[tempNumCols*tempNumRows];
1295 for (int row = 0; row < tempNumRows; row++) {
1296 for (int column = 0; column < tempNumCols; column++) {
1297 tempConstArray[tempNumRows * column + row].setFConst(0.0f);
1298 for (int i = 0; i < tempNumAdds; i++) {
1299 tempConstArray[tempNumRows * column + row].setFConst(tempConstArray[tempNumRows * column + row].getFConst() + unionArray[i * leftNumRows + row].getFConst() * (rightUnionArray[column * rightNumRows + i].getFConst()));
John Bauman66b8ab22014-05-06 15:57:45 -04001300 }
1301 }
1302 }
Alexis Hetu00106d42015-04-23 11:45:35 -04001303 // update return type for matrix product
1304 returnType.setNominalSize(static_cast<unsigned char>(tempNumCols));
1305 returnType.setSecondarySize(static_cast<unsigned char>(tempNumRows));
John Bauman66b8ab22014-05-06 15:57:45 -04001306 }
1307 break;
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001308
1309 case EOpOuterProduct:
1310 {
1311 int leftSize = getNominalSize();
1312 int rightSize = node->getNominalSize();
1313 tempConstArray = new ConstantUnion[leftSize*rightSize];
1314 for(int row = 0; row < leftSize; row++) {
1315 for(int column = 0; column < rightSize; column++) {
1316 tempConstArray[leftSize * column + row].setFConst(unionArray[row].getFConst() * rightUnionArray[column].getFConst());
1317 }
1318 }
1319 // update return type for outer product
1320 returnType.setNominalSize(static_cast<unsigned char>(rightSize));
1321 returnType.setSecondarySize(static_cast<unsigned char>(leftSize));
1322 }
1323 break;
1324
1325 case EOpTranspose:
1326 {
1327 int rightCol = node->getNominalSize();
1328 int rightRow = node->getSecondarySize();
1329 tempConstArray = new ConstantUnion[rightCol*rightRow];
1330 for(int row = 0; row < rightRow; row++) {
1331 for(int column = 0; column < rightCol; column++) {
1332 tempConstArray[rightRow * column + row].setFConst(rightUnionArray[rightCol * row + column].getFConst());
1333 }
1334 }
1335 // update return type for transpose
1336 returnType.setNominalSize(static_cast<unsigned char>(rightRow));
1337 returnType.setSecondarySize(static_cast<unsigned char>(rightCol));
1338 }
1339 break;
1340
1341 case EOpDeterminant:
1342 {
1343 ASSERT(node->getNominalSize() == node->getSecondarySize());
1344
1345 tempConstArray = new ConstantUnion[1];
1346 tempConstArray[0].setFConst(ComputeDeterminant(node->getNominalSize(), rightUnionArray));
1347 // update return type for determinant
1348 returnType.setNominalSize(1);
1349 returnType.setSecondarySize(1);
1350 }
1351 break;
1352
1353 case EOpInverse:
1354 {
1355 ASSERT(node->getNominalSize() == node->getSecondarySize());
1356
1357 tempConstArray = CreateInverse(node, rightUnionArray);
1358 if(!tempConstArray)
1359 {
1360 // Singular matrix, just copy
1361 tempConstArray = new ConstantUnion[objectSize];
1362 for(int i = 0; i < objectSize; i++)
1363 tempConstArray[i] = rightUnionArray[i];
1364 }
1365 }
1366 break;
1367
John Bauman66b8ab22014-05-06 15:57:45 -04001368 case EOpDiv:
Alexis Hetud061e422015-05-13 16:37:50 -04001369 case EOpIMod:
John Bauman66b8ab22014-05-06 15:57:45 -04001370 tempConstArray = new ConstantUnion[objectSize];
1371 {// support MSVC++6.0
1372 for (int i = 0; i < objectSize; i++) {
1373 switch (getType().getBasicType()) {
Alexis Hetud061e422015-05-13 16:37:50 -04001374 case EbtFloat:
1375 if (rightUnionArray[i] == 0.0f) {
1376 infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
1377 tempConstArray[i].setFConst(FLT_MAX);
1378 } else {
1379 ASSERT(op == EOpDiv);
1380 tempConstArray[i].setFConst(unionArray[i].getFConst() / rightUnionArray[i].getFConst());
1381 }
1382 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001383
Alexis Hetud061e422015-05-13 16:37:50 -04001384 case EbtInt:
1385 if (rightUnionArray[i] == 0) {
1386 infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
1387 tempConstArray[i].setIConst(INT_MAX);
1388 } else {
1389 if(op == EOpDiv) {
1390 tempConstArray[i].setIConst(unionArray[i].getIConst() / rightUnionArray[i].getIConst());
1391 } else {
1392 ASSERT(op == EOpIMod);
1393 tempConstArray[i].setIConst(unionArray[i].getIConst() % rightUnionArray[i].getIConst());
1394 }
1395 }
1396 break;
1397 case EbtUInt:
1398 if (rightUnionArray[i] == 0) {
1399 infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
1400 tempConstArray[i].setUConst(UINT_MAX);
1401 } else {
1402 if(op == EOpDiv) {
1403 tempConstArray[i].setUConst(unionArray[i].getUConst() / rightUnionArray[i].getUConst());
1404 } else {
1405 ASSERT(op == EOpIMod);
1406 tempConstArray[i].setUConst(unionArray[i].getUConst() % rightUnionArray[i].getUConst());
1407 }
1408 }
1409 break;
1410 default:
1411 infoSink.info.message(EPrefixInternalError, "Constant folding cannot be done for \"/\"", getLine());
1412 return 0;
John Bauman66b8ab22014-05-06 15:57:45 -04001413 }
1414 }
1415 }
1416 break;
1417
1418 case EOpMatrixTimesVector:
1419 if (node->getBasicType() != EbtFloat) {
1420 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix times vector", getLine());
1421 return 0;
1422 }
1423 tempConstArray = new ConstantUnion[getNominalSize()];
1424
1425 {// support MSVC++6.0
1426 for (int size = getNominalSize(), i = 0; i < size; i++) {
1427 tempConstArray[i].setFConst(0.0f);
1428 for (int j = 0; j < size; j++) {
1429 tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j*size + i].getFConst()) * rightUnionArray[j].getFConst()));
1430 }
1431 }
1432 }
1433
1434 tempNode = new TIntermConstantUnion(tempConstArray, node->getType());
1435 tempNode->setLine(getLine());
1436
1437 return tempNode;
1438
1439 case EOpVectorTimesMatrix:
1440 if (getType().getBasicType() != EbtFloat) {
1441 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for vector times matrix", getLine());
1442 return 0;
1443 }
1444
1445 tempConstArray = new ConstantUnion[getNominalSize()];
1446 {// support MSVC++6.0
1447 for (int size = getNominalSize(), i = 0; i < size; i++) {
1448 tempConstArray[i].setFConst(0.0f);
1449 for (int j = 0; j < size; j++) {
1450 tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j].getFConst()) * rightUnionArray[i*size + j].getFConst()));
1451 }
1452 }
1453 }
1454 break;
1455
1456 case EOpLogicalAnd: // this code is written for possible future use, will not get executed currently
1457 tempConstArray = new ConstantUnion[objectSize];
1458 {// support MSVC++6.0
1459 for (int i = 0; i < objectSize; i++)
1460 tempConstArray[i] = unionArray[i] && rightUnionArray[i];
1461 }
1462 break;
1463
1464 case EOpLogicalOr: // this code is written for possible future use, will not get executed currently
1465 tempConstArray = new ConstantUnion[objectSize];
1466 {// support MSVC++6.0
1467 for (int i = 0; i < objectSize; i++)
1468 tempConstArray[i] = unionArray[i] || rightUnionArray[i];
1469 }
1470 break;
1471
1472 case EOpLogicalXor:
1473 tempConstArray = new ConstantUnion[objectSize];
1474 {// support MSVC++6.0
1475 for (int i = 0; i < objectSize; i++)
1476 switch (getType().getBasicType()) {
Alexis Hetud061e422015-05-13 16:37:50 -04001477 case EbtBool: tempConstArray[i].setBConst((unionArray[i] == rightUnionArray[i]) ? false : true); break;
1478 default: assert(false && "Default missing");
John Bauman66b8ab22014-05-06 15:57:45 -04001479 }
1480 }
1481 break;
1482
Alexis Hetud061e422015-05-13 16:37:50 -04001483 case EOpBitwiseAnd:
1484 tempConstArray = new ConstantUnion[objectSize];
1485 for(int i = 0; i < objectSize; i++)
1486 tempConstArray[i] = unionArray[i] & rightUnionArray[i];
1487 break;
1488 case EOpBitwiseXor:
1489 tempConstArray = new ConstantUnion[objectSize];
1490 for(int i = 0; i < objectSize; i++)
1491 tempConstArray[i] = unionArray[i] ^ rightUnionArray[i];
1492 break;
1493 case EOpBitwiseOr:
1494 tempConstArray = new ConstantUnion[objectSize];
1495 for(int i = 0; i < objectSize; i++)
1496 tempConstArray[i] = unionArray[i] | rightUnionArray[i];
1497 break;
1498 case EOpBitShiftLeft:
1499 tempConstArray = new ConstantUnion[objectSize];
1500 for(int i = 0; i < objectSize; i++)
1501 tempConstArray[i] = unionArray[i] << rightUnionArray[i];
1502 break;
1503 case EOpBitShiftRight:
1504 tempConstArray = new ConstantUnion[objectSize];
1505 for(int i = 0; i < objectSize; i++)
1506 tempConstArray[i] = unionArray[i] >> rightUnionArray[i];
1507 break;
1508
John Bauman66b8ab22014-05-06 15:57:45 -04001509 case EOpLessThan:
1510 assert(objectSize == 1);
1511 tempConstArray = new ConstantUnion[1];
1512 tempConstArray->setBConst(*unionArray < *rightUnionArray);
Nicolas Capens31ad2aa2015-02-26 13:14:27 -05001513 returnType = TType(EbtBool, EbpUndefined, EvqConstExpr);
John Bauman66b8ab22014-05-06 15:57:45 -04001514 break;
1515 case EOpGreaterThan:
1516 assert(objectSize == 1);
1517 tempConstArray = new ConstantUnion[1];
1518 tempConstArray->setBConst(*unionArray > *rightUnionArray);
Nicolas Capens31ad2aa2015-02-26 13:14:27 -05001519 returnType = TType(EbtBool, EbpUndefined, EvqConstExpr);
John Bauman66b8ab22014-05-06 15:57:45 -04001520 break;
1521 case EOpLessThanEqual:
1522 {
1523 assert(objectSize == 1);
1524 ConstantUnion constant;
1525 constant.setBConst(*unionArray > *rightUnionArray);
1526 tempConstArray = new ConstantUnion[1];
1527 tempConstArray->setBConst(!constant.getBConst());
Nicolas Capens31ad2aa2015-02-26 13:14:27 -05001528 returnType = TType(EbtBool, EbpUndefined, EvqConstExpr);
John Bauman66b8ab22014-05-06 15:57:45 -04001529 break;
1530 }
1531 case EOpGreaterThanEqual:
1532 {
1533 assert(objectSize == 1);
1534 ConstantUnion constant;
1535 constant.setBConst(*unionArray < *rightUnionArray);
1536 tempConstArray = new ConstantUnion[1];
1537 tempConstArray->setBConst(!constant.getBConst());
Nicolas Capens31ad2aa2015-02-26 13:14:27 -05001538 returnType = TType(EbtBool, EbpUndefined, EvqConstExpr);
John Bauman66b8ab22014-05-06 15:57:45 -04001539 break;
1540 }
1541
1542 case EOpEqual:
1543 if (getType().getBasicType() == EbtStruct) {
1544 if (!CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray))
1545 boolNodeFlag = true;
1546 } else {
1547 for (int i = 0; i < objectSize; i++) {
1548 if (unionArray[i] != rightUnionArray[i]) {
1549 boolNodeFlag = true;
1550 break; // break out of for loop
1551 }
1552 }
1553 }
1554
1555 tempConstArray = new ConstantUnion[1];
1556 if (!boolNodeFlag) {
1557 tempConstArray->setBConst(true);
1558 }
1559 else {
1560 tempConstArray->setBConst(false);
1561 }
1562
Nicolas Capens31ad2aa2015-02-26 13:14:27 -05001563 tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConstExpr));
John Bauman66b8ab22014-05-06 15:57:45 -04001564 tempNode->setLine(getLine());
1565
1566 return tempNode;
1567
1568 case EOpNotEqual:
1569 if (getType().getBasicType() == EbtStruct) {
1570 if (CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray))
1571 boolNodeFlag = true;
1572 } else {
1573 for (int i = 0; i < objectSize; i++) {
1574 if (unionArray[i] == rightUnionArray[i]) {
1575 boolNodeFlag = true;
1576 break; // break out of for loop
1577 }
1578 }
1579 }
1580
1581 tempConstArray = new ConstantUnion[1];
1582 if (!boolNodeFlag) {
1583 tempConstArray->setBConst(true);
1584 }
1585 else {
1586 tempConstArray->setBConst(false);
1587 }
1588
Nicolas Capens31ad2aa2015-02-26 13:14:27 -05001589 tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConstExpr));
John Bauman66b8ab22014-05-06 15:57:45 -04001590 tempNode->setLine(getLine());
1591
1592 return tempNode;
1593
1594 default:
1595 infoSink.info.message(EPrefixInternalError, "Invalid operator for constant folding", getLine());
1596 return 0;
1597 }
1598 tempNode = new TIntermConstantUnion(tempConstArray, returnType);
1599 tempNode->setLine(getLine());
1600
1601 return tempNode;
1602 } else {
1603 //
1604 // Do unary operations
1605 //
1606 TIntermConstantUnion *newNode = 0;
1607 ConstantUnion* tempConstArray = new ConstantUnion[objectSize];
1608 for (int i = 0; i < objectSize; i++) {
1609 switch(op) {
1610 case EOpNegative:
1611 switch (getType().getBasicType()) {
1612 case EbtFloat: tempConstArray[i].setFConst(-unionArray[i].getFConst()); break;
1613 case EbtInt: tempConstArray[i].setIConst(-unionArray[i].getIConst()); break;
1614 default:
1615 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1616 return 0;
1617 }
1618 break;
1619 case EOpLogicalNot: // this code is written for possible future use, will not get executed currently
1620 switch (getType().getBasicType()) {
1621 case EbtBool: tempConstArray[i].setBConst(!unionArray[i].getBConst()); break;
1622 default:
1623 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1624 return 0;
1625 }
1626 break;
Alexis Hetud061e422015-05-13 16:37:50 -04001627 case EOpBitwiseNot:
1628 switch(getType().getBasicType()) {
1629 case EbtInt: tempConstArray[i].setIConst(~unionArray[i].getIConst()); break;
1630 case EbtUInt: tempConstArray[i].setUConst(~unionArray[i].getUConst()); break;
1631 default:
1632 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1633 return 0;
1634 }
1635 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001636 default:
1637 return 0;
1638 }
1639 }
1640 newNode = new TIntermConstantUnion(tempConstArray, getType());
1641 newNode->setLine(getLine());
1642 return newNode;
1643 }
1644}
1645
1646TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermConstantUnion* node)
1647{
John Bauman66b8ab22014-05-06 15:57:45 -04001648 int size = node->getType().getObjectSize();
1649
1650 ConstantUnion *leftUnionArray = new ConstantUnion[size];
1651
1652 for (int i=0; i < size; i++) {
1653
1654 switch (promoteTo) {
1655 case EbtFloat:
1656 switch (node->getType().getBasicType()) {
1657 case EbtInt:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001658 leftUnionArray[i].setFConst(static_cast<float>(node->getIConst(i)));
John Bauman66b8ab22014-05-06 15:57:45 -04001659 break;
Nicolas Capens3c20f802015-02-17 17:17:20 -05001660 case EbtUInt:
1661 leftUnionArray[i].setFConst(static_cast<float>(node->getUConst(i)));
1662 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001663 case EbtBool:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001664 leftUnionArray[i].setFConst(static_cast<float>(node->getBConst(i)));
John Bauman66b8ab22014-05-06 15:57:45 -04001665 break;
1666 case EbtFloat:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001667 leftUnionArray[i].setFConst(static_cast<float>(node->getFConst(i)));
John Bauman66b8ab22014-05-06 15:57:45 -04001668 break;
1669 default:
1670 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
1671 return 0;
1672 }
1673 break;
1674 case EbtInt:
1675 switch (node->getType().getBasicType()) {
1676 case EbtInt:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001677 leftUnionArray[i].setIConst(static_cast<int>(node->getIConst(i)));
John Bauman66b8ab22014-05-06 15:57:45 -04001678 break;
Nicolas Capens3c20f802015-02-17 17:17:20 -05001679 case EbtUInt:
1680 leftUnionArray[i].setIConst(static_cast<int>(node->getUConst(i)));
1681 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001682 case EbtBool:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001683 leftUnionArray[i].setIConst(static_cast<int>(node->getBConst(i)));
John Bauman66b8ab22014-05-06 15:57:45 -04001684 break;
1685 case EbtFloat:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001686 leftUnionArray[i].setIConst(static_cast<int>(node->getFConst(i)));
John Bauman66b8ab22014-05-06 15:57:45 -04001687 break;
1688 default:
1689 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
1690 return 0;
1691 }
1692 break;
Nicolas Capens3c20f802015-02-17 17:17:20 -05001693 case EbtUInt:
1694 switch (node->getType().getBasicType()) {
1695 case EbtInt:
1696 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getIConst(i)));
1697 break;
1698 case EbtUInt:
1699 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getUConst(i)));
1700 break;
1701 case EbtBool:
1702 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getBConst(i)));
1703 break;
1704 case EbtFloat:
1705 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getFConst(i)));
1706 break;
1707 default:
1708 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
1709 return 0;
1710 }
1711 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001712 case EbtBool:
1713 switch (node->getType().getBasicType()) {
1714 case EbtInt:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001715 leftUnionArray[i].setBConst(node->getIConst(i) != 0);
John Bauman66b8ab22014-05-06 15:57:45 -04001716 break;
Nicolas Capens3c20f802015-02-17 17:17:20 -05001717 case EbtUInt:
1718 leftUnionArray[i].setBConst(node->getUConst(i) != 0);
1719 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001720 case EbtBool:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001721 leftUnionArray[i].setBConst(node->getBConst(i));
John Bauman66b8ab22014-05-06 15:57:45 -04001722 break;
1723 case EbtFloat:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001724 leftUnionArray[i].setBConst(node->getFConst(i) != 0.0f);
John Bauman66b8ab22014-05-06 15:57:45 -04001725 break;
1726 default:
1727 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
1728 return 0;
1729 }
1730
1731 break;
1732 default:
1733 infoSink.info.message(EPrefixInternalError, "Incorrect data type found", node->getLine());
1734 return 0;
1735 }
1736
1737 }
1738
1739 const TType& t = node->getType();
1740
Alexis Hetub14178b2015-04-13 13:23:20 -04001741 return addConstantUnion(leftUnionArray, TType(promoteTo, t.getPrecision(), t.getQualifier(), t.getNominalSize(), t.getSecondarySize(), t.isArray()), node->getLine());
John Bauman66b8ab22014-05-06 15:57:45 -04001742}
1743