blob: 62658a4d557fc512cb7a612b896c7d6830f12bc0 [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:
51 UNREACHABLE();
52 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//
180TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, TSourceLoc line)
181{
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//
John Baumand4ae8632014-05-06 16:18:33 -0400193TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, 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);
250 if (line == 0)
251 line = right->getLine();
252 node->setLine(line);
253
254 node->setLeft(left);
255 node->setRight(right);
256 if (!node->promote(infoSink))
257 return 0;
258
259 //
260 // See if we can fold constants.
261 //
John Bauman66b8ab22014-05-06 15:57:45 -0400262 TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion();
263 TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion();
264 if (leftTempConstant && rightTempConstant) {
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400265 TIntermTyped *typedReturnNode = leftTempConstant->fold(node->getOp(), rightTempConstant, infoSink);
John Bauman66b8ab22014-05-06 15:57:45 -0400266
267 if (typedReturnNode)
268 return typedReturnNode;
269 }
270
271 return node;
272}
273
274//
275// Connect two nodes through an assignment.
276//
277// Returns the added node.
278//
279TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc line)
280{
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400281 if (left->getType().getStruct() || right->getType().getStruct())
282 {
283 if (left->getType() != right->getType())
284 {
285 return 0;
286 }
287 }
288
John Bauman66b8ab22014-05-06 15:57:45 -0400289 TIntermBinary* node = new TIntermBinary(op);
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400290 if(line == 0)
John Bauman66b8ab22014-05-06 15:57:45 -0400291 line = left->getLine();
292 node->setLine(line);
293
John Bauman66b8ab22014-05-06 15:57:45 -0400294 node->setLeft(left);
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400295 node->setRight(right);
John Bauman66b8ab22014-05-06 15:57:45 -0400296 if (! node->promote(infoSink))
297 return 0;
298
299 return node;
300}
301
302//
303// Connect two nodes through an index operator, where the left node is the base
304// of an array or struct, and the right node is a direct or indirect offset.
305//
306// Returns the added node.
307// The caller should set the type of the returned node.
308//
309TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc line)
310{
311 TIntermBinary* node = new TIntermBinary(op);
312 if (line == 0)
313 line = index->getLine();
314 node->setLine(line);
315 node->setLeft(base);
316 node->setRight(index);
317
318 // caller should set the type
319
320 return node;
321}
322
323//
324// Add one node as the parent of another that it operates on.
325//
326// Returns the added node.
327//
John Baumand4ae8632014-05-06 16:18:33 -0400328TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode, TSourceLoc line)
John Bauman66b8ab22014-05-06 15:57:45 -0400329{
330 TIntermUnary* node;
331 TIntermTyped* child = childNode->getAsTyped();
332
333 if (child == 0) {
334 infoSink.info.message(EPrefixInternalError, "Bad type in AddUnaryMath", line);
335 return 0;
336 }
337
338 switch (op) {
Alexis Hetud061e422015-05-13 16:37:50 -0400339 case EOpBitwiseNot:
Alexis Hetu9085c8d2015-06-01 13:48:07 -0400340 if (!IsInteger(child->getType().getBasicType()) || child->getType().isMatrix() || child->getType().isArray()) {
Alexis Hetud061e422015-05-13 16:37:50 -0400341 return 0;
342 }
343 break;
344
John Bauman66b8ab22014-05-06 15:57:45 -0400345 case EOpLogicalNot:
346 if (child->getType().getBasicType() != EbtBool || child->getType().isMatrix() || child->getType().isArray() || child->getType().isVector()) {
347 return 0;
348 }
349 break;
350
351 case EOpPostIncrement:
352 case EOpPreIncrement:
353 case EOpPostDecrement:
354 case EOpPreDecrement:
355 case EOpNegative:
356 if (child->getType().getBasicType() == EbtStruct || child->getType().isArray())
357 return 0;
358 default: break;
359 }
360
John Bauman66b8ab22014-05-06 15:57:45 -0400361 TIntermConstantUnion *childTempConstant = 0;
362 if (child->getAsConstantUnion())
363 childTempConstant = child->getAsConstantUnion();
364
365 //
366 // Make a new node for the operator.
367 //
368 node = new TIntermUnary(op);
369 if (line == 0)
370 line = child->getLine();
371 node->setLine(line);
372 node->setOperand(child);
373
374 if (! node->promote(infoSink))
375 return 0;
376
377 if (childTempConstant) {
378 TIntermTyped* newChild = childTempConstant->fold(op, 0, infoSink);
379
380 if (newChild)
381 return newChild;
382 }
383
384 return node;
385}
386
387//
388// This is the safe way to change the operator on an aggregate, as it
389// does lots of error checking and fixing. Especially for establishing
390// a function call's operation on it's set of parameters. Sequences
391// of instructions are also aggregates, but they just direnctly set
392// their operator to EOpSequence.
393//
394// Returns an aggregate node, which could be the one passed in if
395// it was already an aggregate but no operator was set.
396//
397TIntermAggregate* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator op, TSourceLoc line)
398{
399 TIntermAggregate* aggNode;
400
401 //
402 // Make sure we have an aggregate. If not turn it into one.
403 //
404 if (node) {
405 aggNode = node->getAsAggregate();
406 if (aggNode == 0 || aggNode->getOp() != EOpNull) {
407 //
408 // Make an aggregate containing this node.
409 //
410 aggNode = new TIntermAggregate();
411 aggNode->getSequence().push_back(node);
412 if (line == 0)
413 line = node->getLine();
414 }
415 } else
416 aggNode = new TIntermAggregate();
417
418 //
419 // Set the operator.
420 //
421 aggNode->setOp(op);
422 if (line != 0)
423 aggNode->setLine(line);
424
425 return aggNode;
426}
427
428//
John Bauman66b8ab22014-05-06 15:57:45 -0400429// Safe way to combine two nodes into an aggregate. Works with null pointers,
430// a node that's not a aggregate yet, etc.
431//
432// Returns the resulting aggregate, unless 0 was passed in for
433// both existing nodes.
434//
435TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* right, TSourceLoc line)
436{
437 if (left == 0 && right == 0)
438 return 0;
439
440 TIntermAggregate* aggNode = 0;
441 if (left)
442 aggNode = left->getAsAggregate();
443 if (!aggNode || aggNode->getOp() != EOpNull) {
444 aggNode = new TIntermAggregate;
445 if (left)
446 aggNode->getSequence().push_back(left);
447 }
448
449 if (right)
450 aggNode->getSequence().push_back(right);
451
452 if (line != 0)
453 aggNode->setLine(line);
454
455 return aggNode;
456}
457
458//
459// Turn an existing node into an aggregate.
460//
461// Returns an aggregate, unless 0 was passed in for the existing node.
462//
463TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, TSourceLoc line)
464{
465 if (node == 0)
466 return 0;
467
468 TIntermAggregate* aggNode = new TIntermAggregate;
469 aggNode->getSequence().push_back(node);
470
471 if (line != 0)
472 aggNode->setLine(line);
473 else
474 aggNode->setLine(node->getLine());
475
476 return aggNode;
477}
478
479//
480// For "if" test nodes. There are three children; a condition,
481// a true path, and a false path. The two paths are in the
482// nodePair.
483//
484// Returns the selection node created.
485//
486TIntermNode* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nodePair, TSourceLoc line)
487{
488 //
489 // For compile time constant selections, prune the code and
490 // test now.
491 //
492
493 if (cond->getAsTyped() && cond->getAsTyped()->getAsConstantUnion()) {
Nicolas Capens198529d2015-02-10 13:54:19 -0500494 if (cond->getAsConstantUnion()->getBConst(0) == true)
John Bauman66b8ab22014-05-06 15:57:45 -0400495 return nodePair.node1 ? setAggregateOperator(nodePair.node1, EOpSequence, nodePair.node1->getLine()) : NULL;
496 else
497 return nodePair.node2 ? setAggregateOperator(nodePair.node2, EOpSequence, nodePair.node2->getLine()) : NULL;
498 }
499
500 TIntermSelection* node = new TIntermSelection(cond, nodePair.node1, nodePair.node2);
501 node->setLine(line);
502
503 return node;
504}
505
506
507TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, TSourceLoc line)
508{
Nicolas Capens31ad2aa2015-02-26 13:14:27 -0500509 if (left->getType().getQualifier() == EvqConstExpr && right->getType().getQualifier() == EvqConstExpr) {
John Bauman66b8ab22014-05-06 15:57:45 -0400510 return right;
511 } else {
512 TIntermTyped *commaAggregate = growAggregate(left, right, line);
513 commaAggregate->getAsAggregate()->setOp(EOpComma);
514 commaAggregate->setType(right->getType());
515 commaAggregate->getTypePointer()->setQualifier(EvqTemporary);
516 return commaAggregate;
517 }
518}
519
520//
521// For "?:" test nodes. There are three children; a condition,
522// a true path, and a false path. The two paths are specified
523// as separate parameters.
524//
525// Returns the selection node created, or 0 if one could not be.
526//
527TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, TSourceLoc line)
528{
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400529 if (trueBlock->getType() != falseBlock->getType())
530 {
531 return 0;
John Bauman66b8ab22014-05-06 15:57:45 -0400532 }
533
534 //
535 // See if all the operands are constant, then fold it otherwise not.
536 //
537
538 if (cond->getAsConstantUnion() && trueBlock->getAsConstantUnion() && falseBlock->getAsConstantUnion()) {
Nicolas Capens198529d2015-02-10 13:54:19 -0500539 if (cond->getAsConstantUnion()->getBConst(0))
John Bauman66b8ab22014-05-06 15:57:45 -0400540 return trueBlock;
541 else
542 return falseBlock;
543 }
544
545 //
546 // Make a selection node.
547 //
548 TIntermSelection* node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType());
549 node->getTypePointer()->setQualifier(EvqTemporary);
550 node->setLine(line);
551
552 return node;
553}
554
Alexis Hetu76a343a2015-06-04 17:21:22 -0400555TIntermSwitch *TIntermediate::addSwitch(TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &line)
556{
557 TIntermSwitch *node = new TIntermSwitch(init, statementList);
558 node->setLine(line);
559
560 return node;
561}
562
563TIntermCase *TIntermediate::addCase(TIntermTyped *condition, const TSourceLoc &line)
564{
565 TIntermCase *node = new TIntermCase(condition);
566 node->setLine(line);
567
568 return node;
569}
570
John Bauman66b8ab22014-05-06 15:57:45 -0400571//
572// Constant terminal nodes. Has a union that contains bool, float or int constants
573//
574// Returns the constant union node created.
575//
576
577TIntermConstantUnion* TIntermediate::addConstantUnion(ConstantUnion* unionArrayPointer, const TType& t, TSourceLoc line)
578{
579 TIntermConstantUnion* node = new TIntermConstantUnion(unionArrayPointer, t);
580 node->setLine(line);
581
582 return node;
583}
584
585TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, TSourceLoc line)
586{
587
588 TIntermAggregate* node = new TIntermAggregate(EOpSequence);
589
590 node->setLine(line);
591 TIntermConstantUnion* constIntNode;
592 TIntermSequence &sequenceVector = node->getSequence();
593 ConstantUnion* unionArray;
594
595 for (int i = 0; i < fields.num; i++) {
596 unionArray = new ConstantUnion[1];
597 unionArray->setIConst(fields.offsets[i]);
Nicolas Capens31ad2aa2015-02-26 13:14:27 -0500598 constIntNode = addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConstExpr), line);
John Bauman66b8ab22014-05-06 15:57:45 -0400599 sequenceVector.push_back(constIntNode);
600 }
601
602 return node;
603}
604
605//
606// Create loop nodes.
607//
608TIntermNode* TIntermediate::addLoop(TLoopType type, TIntermNode* init, TIntermTyped* cond, TIntermTyped* expr, TIntermNode* body, TSourceLoc line)
609{
610 TIntermNode* node = new TIntermLoop(type, init, cond, expr, body);
611 node->setLine(line);
612
613 return node;
614}
615
616//
617// Add branches.
618//
619TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TSourceLoc line)
620{
621 return addBranch(branchOp, 0, line);
622}
623
624TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expression, TSourceLoc line)
625{
626 TIntermBranch* node = new TIntermBranch(branchOp, expression);
627 node->setLine(line);
628
629 return node;
630}
631
632//
633// This is to be executed once the final root is put on top by the parsing
634// process.
635//
636bool TIntermediate::postProcess(TIntermNode* root)
637{
638 if (root == 0)
639 return true;
640
641 //
642 // First, finish off the top level sequence, if any
643 //
644 TIntermAggregate* aggRoot = root->getAsAggregate();
645 if (aggRoot && aggRoot->getOp() == EOpNull)
646 aggRoot->setOp(EOpSequence);
647
648 return true;
649}
650
John Bauman66b8ab22014-05-06 15:57:45 -0400651////////////////////////////////////////////////////////////////
652//
653// Member functions of the nodes used for building the tree.
654//
655////////////////////////////////////////////////////////////////
656
657//
658// Say whether or not an operation node changes the value of a variable.
659//
660// Returns true if state is modified.
661//
662bool TIntermOperator::modifiesState() const
663{
664 switch (op) {
665 case EOpPostIncrement:
666 case EOpPostDecrement:
667 case EOpPreIncrement:
668 case EOpPreDecrement:
669 case EOpAssign:
670 case EOpAddAssign:
671 case EOpSubAssign:
672 case EOpMulAssign:
673 case EOpVectorTimesMatrixAssign:
674 case EOpVectorTimesScalarAssign:
675 case EOpMatrixTimesScalarAssign:
676 case EOpMatrixTimesMatrixAssign:
677 case EOpDivAssign:
Alexis Hetu17809052015-05-13 11:28:22 -0400678 case EOpIModAssign:
679 case EOpBitShiftLeftAssign:
680 case EOpBitShiftRightAssign:
681 case EOpBitwiseAndAssign:
682 case EOpBitwiseXorAssign:
683 case EOpBitwiseOrAssign:
John Bauman66b8ab22014-05-06 15:57:45 -0400684 return true;
685 default:
686 return false;
687 }
688}
689
690//
691// returns true if the operator is for one of the constructors
692//
693bool TIntermOperator::isConstructor() const
694{
695 switch (op) {
696 case EOpConstructVec2:
697 case EOpConstructVec3:
698 case EOpConstructVec4:
699 case EOpConstructMat2:
Alexis Hetu00106d42015-04-23 11:45:35 -0400700 case EOpConstructMat2x3:
701 case EOpConstructMat2x4:
702 case EOpConstructMat3x2:
John Bauman66b8ab22014-05-06 15:57:45 -0400703 case EOpConstructMat3:
Alexis Hetu00106d42015-04-23 11:45:35 -0400704 case EOpConstructMat3x4:
705 case EOpConstructMat4x2:
706 case EOpConstructMat4x3:
John Bauman66b8ab22014-05-06 15:57:45 -0400707 case EOpConstructMat4:
708 case EOpConstructFloat:
709 case EOpConstructIVec2:
710 case EOpConstructIVec3:
711 case EOpConstructIVec4:
712 case EOpConstructInt:
Nicolas Capense4b1b1d2015-02-17 17:26:01 -0500713 case EOpConstructUVec2:
714 case EOpConstructUVec3:
715 case EOpConstructUVec4:
Nicolas Capens3c20f802015-02-17 17:17:20 -0500716 case EOpConstructUInt:
John Bauman66b8ab22014-05-06 15:57:45 -0400717 case EOpConstructBVec2:
718 case EOpConstructBVec3:
719 case EOpConstructBVec4:
720 case EOpConstructBool:
721 case EOpConstructStruct:
722 return true;
723 default:
724 return false;
725 }
726}
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400727
John Bauman66b8ab22014-05-06 15:57:45 -0400728//
729// Make sure the type of a unary operator is appropriate for its
730// combination of operation and operand type.
731//
732// Returns false in nothing makes sense.
733//
734bool TIntermUnary::promote(TInfoSink&)
735{
736 switch (op) {
737 case EOpLogicalNot:
738 if (operand->getBasicType() != EbtBool)
739 return false;
740 break;
Alexis Hetud061e422015-05-13 16:37:50 -0400741 case EOpBitwiseNot:
Alexis Hetu9085c8d2015-06-01 13:48:07 -0400742 if (!IsInteger(operand->getBasicType()))
Alexis Hetud061e422015-05-13 16:37:50 -0400743 return false;
744 break;
John Bauman66b8ab22014-05-06 15:57:45 -0400745 case EOpNegative:
746 case EOpPostIncrement:
747 case EOpPostDecrement:
748 case EOpPreIncrement:
749 case EOpPreDecrement:
750 if (operand->getBasicType() == EbtBool)
751 return false;
752 break;
753
754 // operators for built-ins are already type checked against their prototype
755 case EOpAny:
756 case EOpAll:
757 case EOpVectorLogicalNot:
758 return true;
759
760 default:
761 if (operand->getBasicType() != EbtFloat)
762 return false;
763 }
764
765 setType(operand->getType());
766
767 // Unary operations results in temporary variables unless const.
Nicolas Capens31ad2aa2015-02-26 13:14:27 -0500768 if (operand->getQualifier() != EvqConstExpr) {
John Bauman66b8ab22014-05-06 15:57:45 -0400769 getTypePointer()->setQualifier(EvqTemporary);
770 }
771
772 return true;
773}
774
775//
776// Establishes the type of the resultant operation, as well as
777// makes the operator the correct one for the operands.
778//
779// Returns false if operator can't work on operands.
780//
781bool TIntermBinary::promote(TInfoSink& infoSink)
782{
783 // This function only handles scalars, vectors, and matrices.
784 if (left->isArray() || right->isArray()) {
785 infoSink.info.message(EPrefixInternalError, "Invalid operation for arrays", getLine());
786 return false;
787 }
788
789 // GLSL ES 2.0 does not support implicit type casting.
790 // So the basic type should always match.
791 if (left->getBasicType() != right->getBasicType())
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400792 {
John Bauman66b8ab22014-05-06 15:57:45 -0400793 return false;
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400794 }
John Bauman66b8ab22014-05-06 15:57:45 -0400795
796 //
797 // Base assumption: just make the type the same as the left
798 // operand. Then only deviations from this need be coded.
799 //
800 setType(left->getType());
801
802 // The result gets promoted to the highest precision.
803 TPrecision higherPrecision = GetHigherPrecision(left->getPrecision(), right->getPrecision());
804 getTypePointer()->setPrecision(higherPrecision);
805
806 // Binary operations results in temporary variables unless both
807 // operands are const.
Nicolas Capens31ad2aa2015-02-26 13:14:27 -0500808 if (left->getQualifier() != EvqConstExpr || right->getQualifier() != EvqConstExpr) {
John Bauman66b8ab22014-05-06 15:57:45 -0400809 getTypePointer()->setQualifier(EvqTemporary);
810 }
811
Alexis Hetud061e422015-05-13 16:37:50 -0400812 int primarySize = std::max(left->getNominalSize(), right->getNominalSize());
John Bauman66b8ab22014-05-06 15:57:45 -0400813
814 //
815 // All scalars. Code after this test assumes this case is removed!
816 //
Alexis Hetud061e422015-05-13 16:37:50 -0400817 if (primarySize == 1) {
John Bauman66b8ab22014-05-06 15:57:45 -0400818 switch (op) {
819 //
820 // Promote to conditional
821 //
822 case EOpEqual:
823 case EOpNotEqual:
824 case EOpLessThan:
825 case EOpGreaterThan:
826 case EOpLessThanEqual:
827 case EOpGreaterThanEqual:
828 setType(TType(EbtBool, EbpUndefined));
829 break;
830
831 //
832 // And and Or operate on conditionals
833 //
834 case EOpLogicalAnd:
835 case EOpLogicalOr:
Alexis Hetud061e422015-05-13 16:37:50 -0400836 case EOpLogicalXor:
John Bauman66b8ab22014-05-06 15:57:45 -0400837 // Both operands must be of type bool.
838 if (left->getBasicType() != EbtBool || right->getBasicType() != EbtBool)
839 return false;
840 setType(TType(EbtBool, EbpUndefined));
841 break;
842
843 default:
844 break;
845 }
846 return true;
847 }
848
849 // If we reach here, at least one of the operands is vector or matrix.
850 // The other operand could be a scalar, vector, or matrix.
John Bauman66b8ab22014-05-06 15:57:45 -0400851 // Can these two operands be combined?
852 //
853 TBasicType basicType = left->getBasicType();
854 switch (op) {
855 case EOpMul:
856 if (!left->isMatrix() && right->isMatrix()) {
857 if (left->isVector())
Alexis Hetu00106d42015-04-23 11:45:35 -0400858 {
John Bauman66b8ab22014-05-06 15:57:45 -0400859 op = EOpVectorTimesMatrix;
Alexis Hetu00106d42015-04-23 11:45:35 -0400860 setType(TType(basicType, higherPrecision, EvqTemporary,
861 static_cast<unsigned char>(right->getNominalSize()), 1));
862 }
John Bauman66b8ab22014-05-06 15:57:45 -0400863 else {
864 op = EOpMatrixTimesScalar;
Alexis Hetu00106d42015-04-23 11:45:35 -0400865 setType(TType(basicType, higherPrecision, EvqTemporary,
866 static_cast<unsigned char>(right->getNominalSize()), static_cast<unsigned char>(right->getSecondarySize())));
John Bauman66b8ab22014-05-06 15:57:45 -0400867 }
868 } else if (left->isMatrix() && !right->isMatrix()) {
869 if (right->isVector()) {
870 op = EOpMatrixTimesVector;
Alexis Hetu00106d42015-04-23 11:45:35 -0400871 setType(TType(basicType, higherPrecision, EvqTemporary,
872 static_cast<unsigned char>(left->getSecondarySize()), 1));
John Bauman66b8ab22014-05-06 15:57:45 -0400873 } else {
874 op = EOpMatrixTimesScalar;
875 }
876 } else if (left->isMatrix() && right->isMatrix()) {
877 op = EOpMatrixTimesMatrix;
Alexis Hetu00106d42015-04-23 11:45:35 -0400878 setType(TType(basicType, higherPrecision, EvqTemporary,
879 static_cast<unsigned char>(right->getNominalSize()), static_cast<unsigned char>(left->getSecondarySize())));
John Bauman66b8ab22014-05-06 15:57:45 -0400880 } else if (!left->isMatrix() && !right->isMatrix()) {
881 if (left->isVector() && right->isVector()) {
882 // leave as component product
883 } else if (left->isVector() || right->isVector()) {
884 op = EOpVectorTimesScalar;
Alexis Hetu00106d42015-04-23 11:45:35 -0400885 setType(TType(basicType, higherPrecision, EvqTemporary,
886 static_cast<unsigned char>(primarySize), 1));
John Bauman66b8ab22014-05-06 15:57:45 -0400887 }
888 } else {
889 infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
890 return false;
891 }
Alexis Hetu00106d42015-04-23 11:45:35 -0400892
893 if(!ValidateMultiplication(op, left->getType(), right->getType()))
894 {
895 return false;
896 }
John Bauman66b8ab22014-05-06 15:57:45 -0400897 break;
898 case EOpMulAssign:
899 if (!left->isMatrix() && right->isMatrix()) {
900 if (left->isVector())
901 op = EOpVectorTimesMatrixAssign;
902 else {
903 return false;
904 }
905 } else if (left->isMatrix() && !right->isMatrix()) {
906 if (right->isVector()) {
907 return false;
908 } else {
909 op = EOpMatrixTimesScalarAssign;
910 }
911 } else if (left->isMatrix() && right->isMatrix()) {
912 op = EOpMatrixTimesMatrixAssign;
Alexis Hetu00106d42015-04-23 11:45:35 -0400913 setType(TType(basicType, higherPrecision, EvqTemporary,
914 static_cast<unsigned char>(right->getNominalSize()), static_cast<unsigned char>(left->getSecondarySize())));
John Bauman66b8ab22014-05-06 15:57:45 -0400915 } else if (!left->isMatrix() && !right->isMatrix()) {
916 if (left->isVector() && right->isVector()) {
917 // leave as component product
918 } else if (left->isVector() || right->isVector()) {
919 if (! left->isVector())
920 return false;
921 op = EOpVectorTimesScalarAssign;
Alexis Hetu00106d42015-04-23 11:45:35 -0400922 setType(TType(basicType, higherPrecision, EvqTemporary,
923 static_cast<unsigned char>(left->getNominalSize()), 1));
John Bauman66b8ab22014-05-06 15:57:45 -0400924 }
925 } else {
926 infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
927 return false;
928 }
Alexis Hetu00106d42015-04-23 11:45:35 -0400929
930 if(!ValidateMultiplication(op, left->getType(), right->getType()))
931 {
932 return false;
933 }
John Bauman66b8ab22014-05-06 15:57:45 -0400934 break;
935
936 case EOpAssign:
937 case EOpInitialize:
Alexis Hetu00106d42015-04-23 11:45:35 -0400938 // No more additional checks are needed.
939 if ((left->getNominalSize() != right->getNominalSize()) ||
940 (left->getSecondarySize() != right->getSecondarySize()))
941 return false;
942 break;
John Bauman66b8ab22014-05-06 15:57:45 -0400943 case EOpAdd:
944 case EOpSub:
945 case EOpDiv:
Alexis Hetud061e422015-05-13 16:37:50 -0400946 case EOpIMod:
947 case EOpBitShiftLeft:
948 case EOpBitShiftRight:
949 case EOpBitwiseAnd:
950 case EOpBitwiseXor:
951 case EOpBitwiseOr:
John Bauman66b8ab22014-05-06 15:57:45 -0400952 case EOpAddAssign:
953 case EOpSubAssign:
954 case EOpDivAssign:
Alexis Hetu17809052015-05-13 11:28:22 -0400955 case EOpIModAssign:
956 case EOpBitShiftLeftAssign:
957 case EOpBitShiftRightAssign:
958 case EOpBitwiseAndAssign:
959 case EOpBitwiseXorAssign:
960 case EOpBitwiseOrAssign:
John Bauman66b8ab22014-05-06 15:57:45 -0400961 if ((left->isMatrix() && right->isVector()) ||
962 (left->isVector() && right->isMatrix()))
963 return false;
Alexis Hetud061e422015-05-13 16:37:50 -0400964
965 // Are the sizes compatible?
966 if(left->getNominalSize() != right->getNominalSize() ||
967 left->getSecondarySize() != right->getSecondarySize())
968 {
969 // If the nominal sizes of operands do not match:
970 // One of them must be a scalar.
971 if(!left->isScalar() && !right->isScalar())
972 return false;
973
974 // In the case of compound assignment other than multiply-assign,
975 // the right side needs to be a scalar. Otherwise a vector/matrix
976 // would be assigned to a scalar. A scalar can't be shifted by a
977 // vector either.
978 if(!right->isScalar() && (modifiesState() || op == EOpBitShiftLeft || op == EOpBitShiftRight))
979 return false;
980 }
981
982 {
Alexis Hetu00106d42015-04-23 11:45:35 -0400983 const int secondarySize = std::max(
984 left->getSecondarySize(), right->getSecondarySize());
Alexis Hetud061e422015-05-13 16:37:50 -0400985 setType(TType(basicType, higherPrecision, EvqTemporary,
986 static_cast<unsigned char>(primarySize), static_cast<unsigned char>(secondarySize)));
987 if(left->isArray())
988 {
989 ASSERT(left->getArraySize() == right->getArraySize());
990 type.setArraySize(left->getArraySize());
991 }
992 }
John Bauman66b8ab22014-05-06 15:57:45 -0400993 break;
994
995 case EOpEqual:
996 case EOpNotEqual:
997 case EOpLessThan:
998 case EOpGreaterThan:
999 case EOpLessThanEqual:
1000 case EOpGreaterThanEqual:
Alexis Hetu00106d42015-04-23 11:45:35 -04001001 if ((left->getNominalSize() != right->getNominalSize()) ||
1002 (left->getSecondarySize() != right->getSecondarySize()))
John Bauman66b8ab22014-05-06 15:57:45 -04001003 return false;
1004 setType(TType(EbtBool, EbpUndefined));
1005 break;
1006
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001007 case EOpOuterProduct:
1008 if(!left->isVector() || !right->isVector())
1009 return false;
1010 setType(TType(EbtFloat, right->getNominalSize(), left->getNominalSize()));
1011 break;
1012
1013 case EOpTranspose:
1014 if(!right->isMatrix())
1015 return false;
1016 setType(TType(EbtFloat, right->getSecondarySize(), right->getNominalSize()));
1017 break;
1018
1019 case EOpDeterminant:
1020 if(!right->isMatrix())
1021 return false;
1022 setType(TType(EbtFloat));
1023 break;
1024
1025 case EOpInverse:
1026 if(!right->isMatrix() || right->getNominalSize() != right->getSecondarySize())
1027 return false;
1028 setType(right->getType());
1029 break;
1030
John Bauman66b8ab22014-05-06 15:57:45 -04001031 default:
1032 return false;
1033 }
1034
1035 return true;
1036}
1037
1038bool CompareStruct(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
1039{
Alexis Hetua8b364b2015-06-10 11:48:40 -04001040 const TFieldList& fields = leftNodeType.getStruct()->fields();
John Bauman66b8ab22014-05-06 15:57:45 -04001041
Alexis Hetua8b364b2015-06-10 11:48:40 -04001042 size_t structSize = fields.size();
John Bauman66b8ab22014-05-06 15:57:45 -04001043 int index = 0;
1044
1045 for (size_t j = 0; j < structSize; j++) {
Alexis Hetua8b364b2015-06-10 11:48:40 -04001046 int size = fields[j]->type()->getObjectSize();
John Bauman66b8ab22014-05-06 15:57:45 -04001047 for (int i = 0; i < size; i++) {
Alexis Hetua8b364b2015-06-10 11:48:40 -04001048 if (fields[j]->type()->getBasicType() == EbtStruct) {
1049 if (!CompareStructure(*(fields[j]->type()), &rightUnionArray[index], &leftUnionArray[index]))
John Bauman66b8ab22014-05-06 15:57:45 -04001050 return false;
1051 } else {
1052 if (leftUnionArray[index] != rightUnionArray[index])
1053 return false;
1054 index++;
1055 }
1056
1057 }
1058 }
1059 return true;
1060}
1061
1062bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
1063{
1064 if (leftNodeType.isArray()) {
1065 TType typeWithoutArrayness = leftNodeType;
1066 typeWithoutArrayness.clearArrayness();
1067
1068 int arraySize = leftNodeType.getArraySize();
1069
1070 for (int i = 0; i < arraySize; ++i) {
1071 int offset = typeWithoutArrayness.getObjectSize() * i;
1072 if (!CompareStruct(typeWithoutArrayness, &rightUnionArray[offset], &leftUnionArray[offset]))
1073 return false;
1074 }
1075 } else
1076 return CompareStruct(leftNodeType, rightUnionArray, leftUnionArray);
1077
1078 return true;
1079}
1080
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001081float determinant2(float m00, float m01, float m10, float m11)
1082{
1083 return m00 * m11 - m01 * m10;
1084}
1085
1086float determinant3(float m00, float m01, float m02,
1087 float m10, float m11, float m12,
1088 float m20, float m21, float m22)
1089{
1090 return m00 * determinant2(m11, m12, m21, m22) -
1091 m10 * determinant2(m01, m02, m21, m22) +
1092 m20 * determinant2(m01, m02, m11, m12);
1093}
1094
1095float determinant4(float m00, float m01, float m02, float m03,
1096 float m10, float m11, float m12, float m13,
1097 float m20, float m21, float m22, float m23,
1098 float m30, float m31, float m32, float m33)
1099{
1100 return m00 * determinant3(m11, m12, m13, m21, m22, m23, m31, m32, m33) -
1101 m10 * determinant3(m01, m02, m03, m21, m22, m23, m31, m32, m33) +
1102 m20 * determinant3(m01, m02, m03, m11, m12, m13, m31, m32, m33) -
1103 m30 * determinant3(m01, m02, m03, m11, m12, m13, m21, m22, m23);
1104}
1105
1106float ComputeDeterminant(int size, ConstantUnion* unionArray)
1107{
1108 switch(size)
1109 {
1110 case 2:
1111 return determinant2(unionArray[0].getFConst(),
1112 unionArray[1].getFConst(),
1113 unionArray[2].getFConst(),
1114 unionArray[3].getFConst());
1115 case 3:
1116 return determinant3(unionArray[0].getFConst(),
1117 unionArray[1].getFConst(),
1118 unionArray[2].getFConst(),
1119 unionArray[3].getFConst(),
1120 unionArray[4].getFConst(),
1121 unionArray[5].getFConst(),
1122 unionArray[6].getFConst(),
1123 unionArray[7].getFConst(),
1124 unionArray[8].getFConst());
1125 case 4:
1126 return determinant4(unionArray[0].getFConst(),
1127 unionArray[1].getFConst(),
1128 unionArray[2].getFConst(),
1129 unionArray[3].getFConst(),
1130 unionArray[4].getFConst(),
1131 unionArray[5].getFConst(),
1132 unionArray[6].getFConst(),
1133 unionArray[7].getFConst(),
1134 unionArray[8].getFConst(),
1135 unionArray[9].getFConst(),
1136 unionArray[10].getFConst(),
1137 unionArray[11].getFConst(),
1138 unionArray[12].getFConst(),
1139 unionArray[13].getFConst(),
1140 unionArray[14].getFConst(),
1141 unionArray[15].getFConst());
1142 default:
1143 UNREACHABLE();
1144 return 0.0f;
1145 }
1146}
1147
1148ConstantUnion* CreateInverse(TIntermConstantUnion* node, ConstantUnion* unionArray)
1149{
1150 ConstantUnion* tempConstArray = 0;
1151 int size = node->getNominalSize();
1152 float determinant = ComputeDeterminant(size, unionArray);
1153 if(determinant != 0.0f)
1154 {
1155 float invDet = 1.0f / determinant;
1156 tempConstArray = new ConstantUnion[size*size];
1157 switch(size)
1158 {
1159 case 2:
1160 {
1161 float m00 = unionArray[0].getFConst(); // Matrix is:
1162 float m01 = unionArray[1].getFConst(); // (m00, m01)
1163 float m10 = unionArray[2].getFConst(); // (m10, m11)
1164 float m11 = unionArray[3].getFConst();
1165 tempConstArray[0].setFConst( invDet * m11);
1166 tempConstArray[1].setFConst(-invDet * m01);
1167 tempConstArray[2].setFConst(-invDet * m10);
1168 tempConstArray[3].setFConst( invDet * m00);
1169 }
1170 break;
1171 case 3:
1172 {
1173 float m00 = unionArray[0].getFConst(); // Matrix is:
1174 float m01 = unionArray[1].getFConst(); // (m00, m01, m02)
1175 float m02 = unionArray[2].getFConst(); // (m10, m11, m12)
1176 float m10 = unionArray[3].getFConst(); // (m20, m21, m22)
1177 float m11 = unionArray[4].getFConst();
1178 float m12 = unionArray[5].getFConst();
1179 float m20 = unionArray[6].getFConst();
1180 float m21 = unionArray[7].getFConst();
1181 float m22 = unionArray[8].getFConst();
1182 tempConstArray[0].setFConst(invDet * determinant2(m11, m12, m21, m22)); // m00 = invDet * (m11 * m22 - m12 * m21)
1183 tempConstArray[1].setFConst(invDet * determinant2(m12, m10, m22, m20)); // m01 = -invDet * (m10 * m22 - m12 * m20)
1184 tempConstArray[2].setFConst(invDet * determinant2(m10, m11, m20, m21)); // m02 = invDet * (m10 * m21 - m11 * m20)
1185 tempConstArray[3].setFConst(invDet * determinant2(m21, m22, m01, m02)); // m10 = -invDet * (m01 * m22 - m02 * m21)
1186 tempConstArray[4].setFConst(invDet * determinant2(m00, m02, m20, m22)); // m11 = invDet * (m00 * m22 - m02 * m20)
1187 tempConstArray[5].setFConst(invDet * determinant2(m20, m21, m00, m01)); // m12 = -invDet * (m00 * m21 - m01 * m20)
1188 tempConstArray[6].setFConst(invDet * determinant2(m01, m02, m11, m12)); // m20 = invDet * (m01 * m12 - m02 * m11)
1189 tempConstArray[7].setFConst(invDet * determinant2(m10, m12, m00, m02)); // m21 = -invDet * (m00 * m12 - m02 * m10)
1190 tempConstArray[8].setFConst(invDet * determinant2(m00, m01, m10, m11)); // m22 = invDet * (m00 * m11 - m01 * m10)
1191 }
1192 break;
1193 case 4:
1194 {
1195 float m00 = unionArray[0].getFConst(); // Matrix is:
1196 float m01 = unionArray[1].getFConst(); // (m00, m01, m02, m03)
1197 float m02 = unionArray[2].getFConst(); // (m10, m11, m12, m13)
1198 float m03 = unionArray[3].getFConst(); // (m20, m21, m22, m23)
1199 float m10 = unionArray[4].getFConst(); // (m30, m31, m32, m33)
1200 float m11 = unionArray[5].getFConst();
1201 float m12 = unionArray[6].getFConst();
1202 float m13 = unionArray[7].getFConst();
1203 float m20 = unionArray[8].getFConst();
1204 float m21 = unionArray[9].getFConst();
1205 float m22 = unionArray[10].getFConst();
1206 float m23 = unionArray[11].getFConst();
1207 float m30 = unionArray[12].getFConst();
1208 float m31 = unionArray[13].getFConst();
1209 float m32 = unionArray[14].getFConst();
1210 float m33 = unionArray[15].getFConst();
1211 tempConstArray[ 0].setFConst( invDet * determinant3(m11, m12, m13, m21, m22, m23, m31, m32, m33)); // m00
1212 tempConstArray[ 1].setFConst(-invDet * determinant3(m10, m12, m13, m20, m22, m23, m30, m32, m33)); // m01
1213 tempConstArray[ 2].setFConst( invDet * determinant3(m10, m11, m13, m20, m21, m23, m30, m31, m33)); // m02
1214 tempConstArray[ 3].setFConst(-invDet * determinant3(m10, m11, m12, m20, m21, m22, m30, m31, m32)); // m03
1215 tempConstArray[ 4].setFConst( invDet * determinant3(m01, m02, m03, m21, m22, m23, m31, m32, m33)); // m10
1216 tempConstArray[ 5].setFConst(-invDet * determinant3(m00, m02, m03, m20, m22, m23, m30, m32, m33)); // m11
1217 tempConstArray[ 6].setFConst( invDet * determinant3(m00, m01, m03, m20, m21, m23, m30, m31, m33)); // m12
1218 tempConstArray[ 7].setFConst(-invDet * determinant3(m00, m01, m02, m20, m21, m22, m30, m31, m32)); // m13
1219 tempConstArray[ 8].setFConst( invDet * determinant3(m01, m02, m03, m11, m12, m13, m31, m32, m33)); // m20
1220 tempConstArray[ 9].setFConst(-invDet * determinant3(m00, m02, m03, m10, m12, m13, m30, m32, m33)); // m21
1221 tempConstArray[10].setFConst( invDet * determinant3(m00, m01, m03, m10, m11, m13, m30, m31, m33)); // m22
1222 tempConstArray[11].setFConst(-invDet * determinant3(m00, m01, m02, m10, m11, m12, m30, m31, m32)); // m23
1223 tempConstArray[12].setFConst( invDet * determinant3(m01, m02, m03, m11, m12, m13, m21, m22, m23)); // m30
1224 tempConstArray[13].setFConst(-invDet * determinant3(m00, m02, m03, m10, m12, m13, m20, m22, m23)); // m31
1225 tempConstArray[14].setFConst( invDet * determinant3(m00, m01, m03, m10, m11, m13, m20, m21, m23)); // m32
1226 tempConstArray[15].setFConst(-invDet * determinant3(m00, m01, m02, m10, m11, m12, m20, m21, m22)); // m33
1227 }
1228 break;
1229 default:
1230 UNREACHABLE();
1231 }
1232 }
1233 return tempConstArray;
1234}
1235
John Bauman66b8ab22014-05-06 15:57:45 -04001236//
1237// The fold functions see if an operation on a constant can be done in place,
1238// without generating run-time code.
1239//
1240// Returns the node to keep using, which may or may not be the node passed in.
1241//
1242
1243TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNode, TInfoSink& infoSink)
1244{
1245 ConstantUnion *unionArray = getUnionArrayPointer();
1246 int objectSize = getType().getObjectSize();
1247
1248 if (constantNode) { // binary operations
1249 TIntermConstantUnion *node = constantNode->getAsConstantUnion();
1250 ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
1251 TType returnType = getType();
1252
1253 // for a case like float f = 1.2 + vec4(2,3,4,5);
1254 if (constantNode->getType().getObjectSize() == 1 && objectSize > 1) {
1255 rightUnionArray = new ConstantUnion[objectSize];
1256 for (int i = 0; i < objectSize; ++i)
1257 rightUnionArray[i] = *node->getUnionArrayPointer();
1258 returnType = getType();
1259 } else if (constantNode->getType().getObjectSize() > 1 && objectSize == 1) {
1260 // for a case like float f = vec4(2,3,4,5) + 1.2;
1261 unionArray = new ConstantUnion[constantNode->getType().getObjectSize()];
1262 for (int i = 0; i < constantNode->getType().getObjectSize(); ++i)
1263 unionArray[i] = *getUnionArrayPointer();
1264 returnType = node->getType();
1265 objectSize = constantNode->getType().getObjectSize();
1266 }
1267
1268 ConstantUnion* tempConstArray = 0;
1269 TIntermConstantUnion *tempNode;
1270
1271 bool boolNodeFlag = false;
1272 switch(op) {
1273 case EOpAdd:
1274 tempConstArray = new ConstantUnion[objectSize];
1275 {// support MSVC++6.0
1276 for (int i = 0; i < objectSize; i++)
1277 tempConstArray[i] = unionArray[i] + rightUnionArray[i];
1278 }
1279 break;
1280 case EOpSub:
1281 tempConstArray = new ConstantUnion[objectSize];
1282 {// support MSVC++6.0
1283 for (int i = 0; i < objectSize; i++)
1284 tempConstArray[i] = unionArray[i] - rightUnionArray[i];
1285 }
1286 break;
1287
1288 case EOpMul:
1289 case EOpVectorTimesScalar:
1290 case EOpMatrixTimesScalar:
1291 tempConstArray = new ConstantUnion[objectSize];
1292 {// support MSVC++6.0
1293 for (int i = 0; i < objectSize; i++)
1294 tempConstArray[i] = unionArray[i] * rightUnionArray[i];
1295 }
1296 break;
1297 case EOpMatrixTimesMatrix:
1298 if (getType().getBasicType() != EbtFloat || node->getBasicType() != EbtFloat) {
1299 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix multiply", getLine());
1300 return 0;
1301 }
1302 {// support MSVC++6.0
Alexis Hetu00106d42015-04-23 11:45:35 -04001303 int leftNumCols = getNominalSize();
1304 int leftNumRows = getSecondarySize();
1305 int rightNumCols = node->getNominalSize();
1306 int rightNumRows = node->getSecondarySize();
1307 if(leftNumCols != rightNumRows) {
1308 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix multiply", getLine());
1309 return 0;
1310 }
1311 int tempNumCols = rightNumCols;
1312 int tempNumRows = leftNumRows;
1313 int tempNumAdds = leftNumCols;
1314 tempConstArray = new ConstantUnion[tempNumCols*tempNumRows];
1315 for (int row = 0; row < tempNumRows; row++) {
1316 for (int column = 0; column < tempNumCols; column++) {
1317 tempConstArray[tempNumRows * column + row].setFConst(0.0f);
1318 for (int i = 0; i < tempNumAdds; i++) {
1319 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 -04001320 }
1321 }
1322 }
Alexis Hetu00106d42015-04-23 11:45:35 -04001323 // update return type for matrix product
1324 returnType.setNominalSize(static_cast<unsigned char>(tempNumCols));
1325 returnType.setSecondarySize(static_cast<unsigned char>(tempNumRows));
John Bauman66b8ab22014-05-06 15:57:45 -04001326 }
1327 break;
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001328
1329 case EOpOuterProduct:
1330 {
1331 int leftSize = getNominalSize();
1332 int rightSize = node->getNominalSize();
1333 tempConstArray = new ConstantUnion[leftSize*rightSize];
1334 for(int row = 0; row < leftSize; row++) {
1335 for(int column = 0; column < rightSize; column++) {
1336 tempConstArray[leftSize * column + row].setFConst(unionArray[row].getFConst() * rightUnionArray[column].getFConst());
1337 }
1338 }
1339 // update return type for outer product
1340 returnType.setNominalSize(static_cast<unsigned char>(rightSize));
1341 returnType.setSecondarySize(static_cast<unsigned char>(leftSize));
1342 }
1343 break;
1344
1345 case EOpTranspose:
1346 {
1347 int rightCol = node->getNominalSize();
1348 int rightRow = node->getSecondarySize();
1349 tempConstArray = new ConstantUnion[rightCol*rightRow];
1350 for(int row = 0; row < rightRow; row++) {
1351 for(int column = 0; column < rightCol; column++) {
1352 tempConstArray[rightRow * column + row].setFConst(rightUnionArray[rightCol * row + column].getFConst());
1353 }
1354 }
1355 // update return type for transpose
1356 returnType.setNominalSize(static_cast<unsigned char>(rightRow));
1357 returnType.setSecondarySize(static_cast<unsigned char>(rightCol));
1358 }
1359 break;
1360
1361 case EOpDeterminant:
1362 {
1363 ASSERT(node->getNominalSize() == node->getSecondarySize());
1364
1365 tempConstArray = new ConstantUnion[1];
1366 tempConstArray[0].setFConst(ComputeDeterminant(node->getNominalSize(), rightUnionArray));
1367 // update return type for determinant
1368 returnType.setNominalSize(1);
1369 returnType.setSecondarySize(1);
1370 }
1371 break;
1372
1373 case EOpInverse:
1374 {
1375 ASSERT(node->getNominalSize() == node->getSecondarySize());
1376
1377 tempConstArray = CreateInverse(node, rightUnionArray);
1378 if(!tempConstArray)
1379 {
1380 // Singular matrix, just copy
1381 tempConstArray = new ConstantUnion[objectSize];
1382 for(int i = 0; i < objectSize; i++)
1383 tempConstArray[i] = rightUnionArray[i];
1384 }
1385 }
1386 break;
1387
John Bauman66b8ab22014-05-06 15:57:45 -04001388 case EOpDiv:
Alexis Hetud061e422015-05-13 16:37:50 -04001389 case EOpIMod:
John Bauman66b8ab22014-05-06 15:57:45 -04001390 tempConstArray = new ConstantUnion[objectSize];
1391 {// support MSVC++6.0
1392 for (int i = 0; i < objectSize; i++) {
1393 switch (getType().getBasicType()) {
Alexis Hetud061e422015-05-13 16:37:50 -04001394 case EbtFloat:
1395 if (rightUnionArray[i] == 0.0f) {
1396 infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
1397 tempConstArray[i].setFConst(FLT_MAX);
1398 } else {
1399 ASSERT(op == EOpDiv);
1400 tempConstArray[i].setFConst(unionArray[i].getFConst() / rightUnionArray[i].getFConst());
1401 }
1402 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001403
Alexis Hetud061e422015-05-13 16:37:50 -04001404 case EbtInt:
1405 if (rightUnionArray[i] == 0) {
1406 infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
1407 tempConstArray[i].setIConst(INT_MAX);
1408 } else {
1409 if(op == EOpDiv) {
1410 tempConstArray[i].setIConst(unionArray[i].getIConst() / rightUnionArray[i].getIConst());
1411 } else {
1412 ASSERT(op == EOpIMod);
1413 tempConstArray[i].setIConst(unionArray[i].getIConst() % rightUnionArray[i].getIConst());
1414 }
1415 }
1416 break;
1417 case EbtUInt:
1418 if (rightUnionArray[i] == 0) {
1419 infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
1420 tempConstArray[i].setUConst(UINT_MAX);
1421 } else {
1422 if(op == EOpDiv) {
1423 tempConstArray[i].setUConst(unionArray[i].getUConst() / rightUnionArray[i].getUConst());
1424 } else {
1425 ASSERT(op == EOpIMod);
1426 tempConstArray[i].setUConst(unionArray[i].getUConst() % rightUnionArray[i].getUConst());
1427 }
1428 }
1429 break;
1430 default:
1431 infoSink.info.message(EPrefixInternalError, "Constant folding cannot be done for \"/\"", getLine());
1432 return 0;
John Bauman66b8ab22014-05-06 15:57:45 -04001433 }
1434 }
1435 }
1436 break;
1437
1438 case EOpMatrixTimesVector:
1439 if (node->getBasicType() != EbtFloat) {
1440 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix times vector", getLine());
1441 return 0;
1442 }
1443 tempConstArray = new ConstantUnion[getNominalSize()];
1444
1445 {// support MSVC++6.0
1446 for (int size = getNominalSize(), i = 0; i < size; i++) {
1447 tempConstArray[i].setFConst(0.0f);
1448 for (int j = 0; j < size; j++) {
1449 tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j*size + i].getFConst()) * rightUnionArray[j].getFConst()));
1450 }
1451 }
1452 }
1453
1454 tempNode = new TIntermConstantUnion(tempConstArray, node->getType());
1455 tempNode->setLine(getLine());
1456
1457 return tempNode;
1458
1459 case EOpVectorTimesMatrix:
1460 if (getType().getBasicType() != EbtFloat) {
1461 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for vector times matrix", getLine());
1462 return 0;
1463 }
1464
1465 tempConstArray = new ConstantUnion[getNominalSize()];
1466 {// support MSVC++6.0
1467 for (int size = getNominalSize(), i = 0; i < size; i++) {
1468 tempConstArray[i].setFConst(0.0f);
1469 for (int j = 0; j < size; j++) {
1470 tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j].getFConst()) * rightUnionArray[i*size + j].getFConst()));
1471 }
1472 }
1473 }
1474 break;
1475
1476 case EOpLogicalAnd: // this code is written for possible future use, will not get executed currently
1477 tempConstArray = new ConstantUnion[objectSize];
1478 {// support MSVC++6.0
1479 for (int i = 0; i < objectSize; i++)
1480 tempConstArray[i] = unionArray[i] && rightUnionArray[i];
1481 }
1482 break;
1483
1484 case EOpLogicalOr: // this code is written for possible future use, will not get executed currently
1485 tempConstArray = new ConstantUnion[objectSize];
1486 {// support MSVC++6.0
1487 for (int i = 0; i < objectSize; i++)
1488 tempConstArray[i] = unionArray[i] || rightUnionArray[i];
1489 }
1490 break;
1491
1492 case EOpLogicalXor:
1493 tempConstArray = new ConstantUnion[objectSize];
1494 {// support MSVC++6.0
1495 for (int i = 0; i < objectSize; i++)
1496 switch (getType().getBasicType()) {
Alexis Hetud061e422015-05-13 16:37:50 -04001497 case EbtBool: tempConstArray[i].setBConst((unionArray[i] == rightUnionArray[i]) ? false : true); break;
1498 default: assert(false && "Default missing");
John Bauman66b8ab22014-05-06 15:57:45 -04001499 }
1500 }
1501 break;
1502
Alexis Hetud061e422015-05-13 16:37:50 -04001503 case EOpBitwiseAnd:
1504 tempConstArray = new ConstantUnion[objectSize];
1505 for(int i = 0; i < objectSize; i++)
1506 tempConstArray[i] = unionArray[i] & rightUnionArray[i];
1507 break;
1508 case EOpBitwiseXor:
1509 tempConstArray = new ConstantUnion[objectSize];
1510 for(int i = 0; i < objectSize; i++)
1511 tempConstArray[i] = unionArray[i] ^ rightUnionArray[i];
1512 break;
1513 case EOpBitwiseOr:
1514 tempConstArray = new ConstantUnion[objectSize];
1515 for(int i = 0; i < objectSize; i++)
1516 tempConstArray[i] = unionArray[i] | rightUnionArray[i];
1517 break;
1518 case EOpBitShiftLeft:
1519 tempConstArray = new ConstantUnion[objectSize];
1520 for(int i = 0; i < objectSize; i++)
1521 tempConstArray[i] = unionArray[i] << rightUnionArray[i];
1522 break;
1523 case EOpBitShiftRight:
1524 tempConstArray = new ConstantUnion[objectSize];
1525 for(int i = 0; i < objectSize; i++)
1526 tempConstArray[i] = unionArray[i] >> rightUnionArray[i];
1527 break;
1528
John Bauman66b8ab22014-05-06 15:57:45 -04001529 case EOpLessThan:
1530 assert(objectSize == 1);
1531 tempConstArray = new ConstantUnion[1];
1532 tempConstArray->setBConst(*unionArray < *rightUnionArray);
Nicolas Capens31ad2aa2015-02-26 13:14:27 -05001533 returnType = TType(EbtBool, EbpUndefined, EvqConstExpr);
John Bauman66b8ab22014-05-06 15:57:45 -04001534 break;
1535 case EOpGreaterThan:
1536 assert(objectSize == 1);
1537 tempConstArray = new ConstantUnion[1];
1538 tempConstArray->setBConst(*unionArray > *rightUnionArray);
Nicolas Capens31ad2aa2015-02-26 13:14:27 -05001539 returnType = TType(EbtBool, EbpUndefined, EvqConstExpr);
John Bauman66b8ab22014-05-06 15:57:45 -04001540 break;
1541 case EOpLessThanEqual:
1542 {
1543 assert(objectSize == 1);
1544 ConstantUnion constant;
1545 constant.setBConst(*unionArray > *rightUnionArray);
1546 tempConstArray = new ConstantUnion[1];
1547 tempConstArray->setBConst(!constant.getBConst());
Nicolas Capens31ad2aa2015-02-26 13:14:27 -05001548 returnType = TType(EbtBool, EbpUndefined, EvqConstExpr);
John Bauman66b8ab22014-05-06 15:57:45 -04001549 break;
1550 }
1551 case EOpGreaterThanEqual:
1552 {
1553 assert(objectSize == 1);
1554 ConstantUnion constant;
1555 constant.setBConst(*unionArray < *rightUnionArray);
1556 tempConstArray = new ConstantUnion[1];
1557 tempConstArray->setBConst(!constant.getBConst());
Nicolas Capens31ad2aa2015-02-26 13:14:27 -05001558 returnType = TType(EbtBool, EbpUndefined, EvqConstExpr);
John Bauman66b8ab22014-05-06 15:57:45 -04001559 break;
1560 }
1561
1562 case EOpEqual:
1563 if (getType().getBasicType() == EbtStruct) {
1564 if (!CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray))
1565 boolNodeFlag = true;
1566 } else {
1567 for (int i = 0; i < objectSize; i++) {
1568 if (unionArray[i] != rightUnionArray[i]) {
1569 boolNodeFlag = true;
1570 break; // break out of for loop
1571 }
1572 }
1573 }
1574
1575 tempConstArray = new ConstantUnion[1];
1576 if (!boolNodeFlag) {
1577 tempConstArray->setBConst(true);
1578 }
1579 else {
1580 tempConstArray->setBConst(false);
1581 }
1582
Nicolas Capens31ad2aa2015-02-26 13:14:27 -05001583 tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConstExpr));
John Bauman66b8ab22014-05-06 15:57:45 -04001584 tempNode->setLine(getLine());
1585
1586 return tempNode;
1587
1588 case EOpNotEqual:
1589 if (getType().getBasicType() == EbtStruct) {
1590 if (CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray))
1591 boolNodeFlag = true;
1592 } else {
1593 for (int i = 0; i < objectSize; i++) {
1594 if (unionArray[i] == rightUnionArray[i]) {
1595 boolNodeFlag = true;
1596 break; // break out of for loop
1597 }
1598 }
1599 }
1600
1601 tempConstArray = new ConstantUnion[1];
1602 if (!boolNodeFlag) {
1603 tempConstArray->setBConst(true);
1604 }
1605 else {
1606 tempConstArray->setBConst(false);
1607 }
1608
Nicolas Capens31ad2aa2015-02-26 13:14:27 -05001609 tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConstExpr));
John Bauman66b8ab22014-05-06 15:57:45 -04001610 tempNode->setLine(getLine());
1611
1612 return tempNode;
1613
1614 default:
1615 infoSink.info.message(EPrefixInternalError, "Invalid operator for constant folding", getLine());
1616 return 0;
1617 }
1618 tempNode = new TIntermConstantUnion(tempConstArray, returnType);
1619 tempNode->setLine(getLine());
1620
1621 return tempNode;
1622 } else {
1623 //
1624 // Do unary operations
1625 //
1626 TIntermConstantUnion *newNode = 0;
1627 ConstantUnion* tempConstArray = new ConstantUnion[objectSize];
1628 for (int i = 0; i < objectSize; i++) {
1629 switch(op) {
1630 case EOpNegative:
1631 switch (getType().getBasicType()) {
1632 case EbtFloat: tempConstArray[i].setFConst(-unionArray[i].getFConst()); break;
1633 case EbtInt: tempConstArray[i].setIConst(-unionArray[i].getIConst()); break;
1634 default:
1635 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1636 return 0;
1637 }
1638 break;
1639 case EOpLogicalNot: // this code is written for possible future use, will not get executed currently
1640 switch (getType().getBasicType()) {
1641 case EbtBool: tempConstArray[i].setBConst(!unionArray[i].getBConst()); break;
1642 default:
1643 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1644 return 0;
1645 }
1646 break;
Alexis Hetud061e422015-05-13 16:37:50 -04001647 case EOpBitwiseNot:
1648 switch(getType().getBasicType()) {
1649 case EbtInt: tempConstArray[i].setIConst(~unionArray[i].getIConst()); break;
1650 case EbtUInt: tempConstArray[i].setUConst(~unionArray[i].getUConst()); break;
1651 default:
1652 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1653 return 0;
1654 }
1655 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001656 default:
1657 return 0;
1658 }
1659 }
1660 newNode = new TIntermConstantUnion(tempConstArray, getType());
1661 newNode->setLine(getLine());
1662 return newNode;
1663 }
1664}
1665
1666TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermConstantUnion* node)
1667{
John Bauman66b8ab22014-05-06 15:57:45 -04001668 int size = node->getType().getObjectSize();
1669
1670 ConstantUnion *leftUnionArray = new ConstantUnion[size];
1671
1672 for (int i=0; i < size; i++) {
1673
1674 switch (promoteTo) {
1675 case EbtFloat:
1676 switch (node->getType().getBasicType()) {
1677 case EbtInt:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001678 leftUnionArray[i].setFConst(static_cast<float>(node->getIConst(i)));
John Bauman66b8ab22014-05-06 15:57:45 -04001679 break;
Nicolas Capens3c20f802015-02-17 17:17:20 -05001680 case EbtUInt:
1681 leftUnionArray[i].setFConst(static_cast<float>(node->getUConst(i)));
1682 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001683 case EbtBool:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001684 leftUnionArray[i].setFConst(static_cast<float>(node->getBConst(i)));
John Bauman66b8ab22014-05-06 15:57:45 -04001685 break;
1686 case EbtFloat:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001687 leftUnionArray[i].setFConst(static_cast<float>(node->getFConst(i)));
John Bauman66b8ab22014-05-06 15:57:45 -04001688 break;
1689 default:
1690 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
1691 return 0;
1692 }
1693 break;
1694 case EbtInt:
1695 switch (node->getType().getBasicType()) {
1696 case EbtInt:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001697 leftUnionArray[i].setIConst(static_cast<int>(node->getIConst(i)));
John Bauman66b8ab22014-05-06 15:57:45 -04001698 break;
Nicolas Capens3c20f802015-02-17 17:17:20 -05001699 case EbtUInt:
1700 leftUnionArray[i].setIConst(static_cast<int>(node->getUConst(i)));
1701 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001702 case EbtBool:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001703 leftUnionArray[i].setIConst(static_cast<int>(node->getBConst(i)));
John Bauman66b8ab22014-05-06 15:57:45 -04001704 break;
1705 case EbtFloat:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001706 leftUnionArray[i].setIConst(static_cast<int>(node->getFConst(i)));
John Bauman66b8ab22014-05-06 15:57:45 -04001707 break;
1708 default:
1709 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
1710 return 0;
1711 }
1712 break;
Nicolas Capens3c20f802015-02-17 17:17:20 -05001713 case EbtUInt:
1714 switch (node->getType().getBasicType()) {
1715 case EbtInt:
1716 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getIConst(i)));
1717 break;
1718 case EbtUInt:
1719 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getUConst(i)));
1720 break;
1721 case EbtBool:
1722 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getBConst(i)));
1723 break;
1724 case EbtFloat:
1725 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getFConst(i)));
1726 break;
1727 default:
1728 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
1729 return 0;
1730 }
1731 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001732 case EbtBool:
1733 switch (node->getType().getBasicType()) {
1734 case EbtInt:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001735 leftUnionArray[i].setBConst(node->getIConst(i) != 0);
John Bauman66b8ab22014-05-06 15:57:45 -04001736 break;
Nicolas Capens3c20f802015-02-17 17:17:20 -05001737 case EbtUInt:
1738 leftUnionArray[i].setBConst(node->getUConst(i) != 0);
1739 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001740 case EbtBool:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001741 leftUnionArray[i].setBConst(node->getBConst(i));
John Bauman66b8ab22014-05-06 15:57:45 -04001742 break;
1743 case EbtFloat:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001744 leftUnionArray[i].setBConst(node->getFConst(i) != 0.0f);
John Bauman66b8ab22014-05-06 15:57:45 -04001745 break;
1746 default:
1747 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
1748 return 0;
1749 }
1750
1751 break;
1752 default:
1753 infoSink.info.message(EPrefixInternalError, "Incorrect data type found", node->getLine());
1754 return 0;
1755 }
1756
1757 }
1758
1759 const TType& t = node->getType();
1760
Alexis Hetub14178b2015-04-13 13:23:20 -04001761 return addConstantUnion(leftUnionArray, TType(promoteTo, t.getPrecision(), t.getQualifier(), t.getNominalSize(), t.getSecondarySize(), t.isArray()), node->getLine());
John Bauman66b8ab22014-05-06 15:57:45 -04001762}
1763