blob: ca0f702b2eef6d646bfd684fd15c5a91e09f74ac [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
555//
556// Constant terminal nodes. Has a union that contains bool, float or int constants
557//
558// Returns the constant union node created.
559//
560
561TIntermConstantUnion* TIntermediate::addConstantUnion(ConstantUnion* unionArrayPointer, const TType& t, TSourceLoc line)
562{
563 TIntermConstantUnion* node = new TIntermConstantUnion(unionArrayPointer, t);
564 node->setLine(line);
565
566 return node;
567}
568
569TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, TSourceLoc line)
570{
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//
592TIntermNode* TIntermediate::addLoop(TLoopType type, TIntermNode* init, TIntermTyped* cond, TIntermTyped* expr, TIntermNode* body, TSourceLoc line)
593{
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//
603TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TSourceLoc line)
604{
605 return addBranch(branchOp, 0, line);
606}
607
608TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expression, TSourceLoc line)
609{
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{
767 // This function only handles scalars, vectors, and matrices.
768 if (left->isArray() || right->isArray()) {
769 infoSink.info.message(EPrefixInternalError, "Invalid operation for arrays", getLine());
770 return false;
771 }
772
773 // GLSL ES 2.0 does not support implicit type casting.
774 // So the basic type should always match.
775 if (left->getBasicType() != right->getBasicType())
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400776 {
John Bauman66b8ab22014-05-06 15:57:45 -0400777 return false;
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400778 }
John Bauman66b8ab22014-05-06 15:57:45 -0400779
780 //
781 // Base assumption: just make the type the same as the left
782 // operand. Then only deviations from this need be coded.
783 //
784 setType(left->getType());
785
786 // The result gets promoted to the highest precision.
787 TPrecision higherPrecision = GetHigherPrecision(left->getPrecision(), right->getPrecision());
788 getTypePointer()->setPrecision(higherPrecision);
789
790 // Binary operations results in temporary variables unless both
791 // operands are const.
Nicolas Capens31ad2aa2015-02-26 13:14:27 -0500792 if (left->getQualifier() != EvqConstExpr || right->getQualifier() != EvqConstExpr) {
John Bauman66b8ab22014-05-06 15:57:45 -0400793 getTypePointer()->setQualifier(EvqTemporary);
794 }
795
Alexis Hetud061e422015-05-13 16:37:50 -0400796 int primarySize = std::max(left->getNominalSize(), right->getNominalSize());
John Bauman66b8ab22014-05-06 15:57:45 -0400797
798 //
799 // All scalars. Code after this test assumes this case is removed!
800 //
Alexis Hetud061e422015-05-13 16:37:50 -0400801 if (primarySize == 1) {
John Bauman66b8ab22014-05-06 15:57:45 -0400802 switch (op) {
803 //
804 // Promote to conditional
805 //
806 case EOpEqual:
807 case EOpNotEqual:
808 case EOpLessThan:
809 case EOpGreaterThan:
810 case EOpLessThanEqual:
811 case EOpGreaterThanEqual:
812 setType(TType(EbtBool, EbpUndefined));
813 break;
814
815 //
816 // And and Or operate on conditionals
817 //
818 case EOpLogicalAnd:
819 case EOpLogicalOr:
Alexis Hetud061e422015-05-13 16:37:50 -0400820 case EOpLogicalXor:
John Bauman66b8ab22014-05-06 15:57:45 -0400821 // Both operands must be of type bool.
822 if (left->getBasicType() != EbtBool || right->getBasicType() != EbtBool)
823 return false;
824 setType(TType(EbtBool, EbpUndefined));
825 break;
826
827 default:
828 break;
829 }
830 return true;
831 }
832
833 // If we reach here, at least one of the operands is vector or matrix.
834 // The other operand could be a scalar, vector, or matrix.
John Bauman66b8ab22014-05-06 15:57:45 -0400835 // Can these two operands be combined?
836 //
837 TBasicType basicType = left->getBasicType();
838 switch (op) {
839 case EOpMul:
840 if (!left->isMatrix() && right->isMatrix()) {
841 if (left->isVector())
Alexis Hetu00106d42015-04-23 11:45:35 -0400842 {
John Bauman66b8ab22014-05-06 15:57:45 -0400843 op = EOpVectorTimesMatrix;
Alexis Hetu00106d42015-04-23 11:45:35 -0400844 setType(TType(basicType, higherPrecision, EvqTemporary,
845 static_cast<unsigned char>(right->getNominalSize()), 1));
846 }
John Bauman66b8ab22014-05-06 15:57:45 -0400847 else {
848 op = EOpMatrixTimesScalar;
Alexis Hetu00106d42015-04-23 11:45:35 -0400849 setType(TType(basicType, higherPrecision, EvqTemporary,
850 static_cast<unsigned char>(right->getNominalSize()), static_cast<unsigned char>(right->getSecondarySize())));
John Bauman66b8ab22014-05-06 15:57:45 -0400851 }
852 } else if (left->isMatrix() && !right->isMatrix()) {
853 if (right->isVector()) {
854 op = EOpMatrixTimesVector;
Alexis Hetu00106d42015-04-23 11:45:35 -0400855 setType(TType(basicType, higherPrecision, EvqTemporary,
856 static_cast<unsigned char>(left->getSecondarySize()), 1));
John Bauman66b8ab22014-05-06 15:57:45 -0400857 } else {
858 op = EOpMatrixTimesScalar;
859 }
860 } else if (left->isMatrix() && right->isMatrix()) {
861 op = EOpMatrixTimesMatrix;
Alexis Hetu00106d42015-04-23 11:45:35 -0400862 setType(TType(basicType, higherPrecision, EvqTemporary,
863 static_cast<unsigned char>(right->getNominalSize()), static_cast<unsigned char>(left->getSecondarySize())));
John Bauman66b8ab22014-05-06 15:57:45 -0400864 } else if (!left->isMatrix() && !right->isMatrix()) {
865 if (left->isVector() && right->isVector()) {
866 // leave as component product
867 } else if (left->isVector() || right->isVector()) {
868 op = EOpVectorTimesScalar;
Alexis Hetu00106d42015-04-23 11:45:35 -0400869 setType(TType(basicType, higherPrecision, EvqTemporary,
870 static_cast<unsigned char>(primarySize), 1));
John Bauman66b8ab22014-05-06 15:57:45 -0400871 }
872 } else {
873 infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
874 return false;
875 }
Alexis Hetu00106d42015-04-23 11:45:35 -0400876
877 if(!ValidateMultiplication(op, left->getType(), right->getType()))
878 {
879 return false;
880 }
John Bauman66b8ab22014-05-06 15:57:45 -0400881 break;
882 case EOpMulAssign:
883 if (!left->isMatrix() && right->isMatrix()) {
884 if (left->isVector())
885 op = EOpVectorTimesMatrixAssign;
886 else {
887 return false;
888 }
889 } else if (left->isMatrix() && !right->isMatrix()) {
890 if (right->isVector()) {
891 return false;
892 } else {
893 op = EOpMatrixTimesScalarAssign;
894 }
895 } else if (left->isMatrix() && right->isMatrix()) {
896 op = EOpMatrixTimesMatrixAssign;
Alexis Hetu00106d42015-04-23 11:45:35 -0400897 setType(TType(basicType, higherPrecision, EvqTemporary,
898 static_cast<unsigned char>(right->getNominalSize()), static_cast<unsigned char>(left->getSecondarySize())));
John Bauman66b8ab22014-05-06 15:57:45 -0400899 } else if (!left->isMatrix() && !right->isMatrix()) {
900 if (left->isVector() && right->isVector()) {
901 // leave as component product
902 } else if (left->isVector() || right->isVector()) {
903 if (! left->isVector())
904 return false;
905 op = EOpVectorTimesScalarAssign;
Alexis Hetu00106d42015-04-23 11:45:35 -0400906 setType(TType(basicType, higherPrecision, EvqTemporary,
907 static_cast<unsigned char>(left->getNominalSize()), 1));
John Bauman66b8ab22014-05-06 15:57:45 -0400908 }
909 } else {
910 infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
911 return false;
912 }
Alexis Hetu00106d42015-04-23 11:45:35 -0400913
914 if(!ValidateMultiplication(op, left->getType(), right->getType()))
915 {
916 return false;
917 }
John Bauman66b8ab22014-05-06 15:57:45 -0400918 break;
919
920 case EOpAssign:
921 case EOpInitialize:
Alexis Hetu00106d42015-04-23 11:45:35 -0400922 // No more additional checks are needed.
923 if ((left->getNominalSize() != right->getNominalSize()) ||
924 (left->getSecondarySize() != right->getSecondarySize()))
925 return false;
926 break;
John Bauman66b8ab22014-05-06 15:57:45 -0400927 case EOpAdd:
928 case EOpSub:
929 case EOpDiv:
Alexis Hetud061e422015-05-13 16:37:50 -0400930 case EOpIMod:
931 case EOpBitShiftLeft:
932 case EOpBitShiftRight:
933 case EOpBitwiseAnd:
934 case EOpBitwiseXor:
935 case EOpBitwiseOr:
John Bauman66b8ab22014-05-06 15:57:45 -0400936 case EOpAddAssign:
937 case EOpSubAssign:
938 case EOpDivAssign:
Alexis Hetu17809052015-05-13 11:28:22 -0400939 case EOpIModAssign:
940 case EOpBitShiftLeftAssign:
941 case EOpBitShiftRightAssign:
942 case EOpBitwiseAndAssign:
943 case EOpBitwiseXorAssign:
944 case EOpBitwiseOrAssign:
John Bauman66b8ab22014-05-06 15:57:45 -0400945 if ((left->isMatrix() && right->isVector()) ||
946 (left->isVector() && right->isMatrix()))
947 return false;
Alexis Hetud061e422015-05-13 16:37:50 -0400948
949 // Are the sizes compatible?
950 if(left->getNominalSize() != right->getNominalSize() ||
951 left->getSecondarySize() != right->getSecondarySize())
952 {
953 // If the nominal sizes of operands do not match:
954 // One of them must be a scalar.
955 if(!left->isScalar() && !right->isScalar())
956 return false;
957
958 // In the case of compound assignment other than multiply-assign,
959 // the right side needs to be a scalar. Otherwise a vector/matrix
960 // would be assigned to a scalar. A scalar can't be shifted by a
961 // vector either.
962 if(!right->isScalar() && (modifiesState() || op == EOpBitShiftLeft || op == EOpBitShiftRight))
963 return false;
964 }
965
966 {
Alexis Hetu00106d42015-04-23 11:45:35 -0400967 const int secondarySize = std::max(
968 left->getSecondarySize(), right->getSecondarySize());
Alexis Hetud061e422015-05-13 16:37:50 -0400969 setType(TType(basicType, higherPrecision, EvqTemporary,
970 static_cast<unsigned char>(primarySize), static_cast<unsigned char>(secondarySize)));
971 if(left->isArray())
972 {
973 ASSERT(left->getArraySize() == right->getArraySize());
974 type.setArraySize(left->getArraySize());
975 }
976 }
John Bauman66b8ab22014-05-06 15:57:45 -0400977 break;
978
979 case EOpEqual:
980 case EOpNotEqual:
981 case EOpLessThan:
982 case EOpGreaterThan:
983 case EOpLessThanEqual:
984 case EOpGreaterThanEqual:
Alexis Hetu00106d42015-04-23 11:45:35 -0400985 if ((left->getNominalSize() != right->getNominalSize()) ||
986 (left->getSecondarySize() != right->getSecondarySize()))
John Bauman66b8ab22014-05-06 15:57:45 -0400987 return false;
988 setType(TType(EbtBool, EbpUndefined));
989 break;
990
Alexis Hetu3815b6c2015-05-27 11:21:37 -0400991 case EOpOuterProduct:
992 if(!left->isVector() || !right->isVector())
993 return false;
994 setType(TType(EbtFloat, right->getNominalSize(), left->getNominalSize()));
995 break;
996
997 case EOpTranspose:
998 if(!right->isMatrix())
999 return false;
1000 setType(TType(EbtFloat, right->getSecondarySize(), right->getNominalSize()));
1001 break;
1002
1003 case EOpDeterminant:
1004 if(!right->isMatrix())
1005 return false;
1006 setType(TType(EbtFloat));
1007 break;
1008
1009 case EOpInverse:
1010 if(!right->isMatrix() || right->getNominalSize() != right->getSecondarySize())
1011 return false;
1012 setType(right->getType());
1013 break;
1014
John Bauman66b8ab22014-05-06 15:57:45 -04001015 default:
1016 return false;
1017 }
1018
1019 return true;
1020}
1021
1022bool CompareStruct(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
1023{
Alexis Hetua8b364b2015-06-10 11:48:40 -04001024 const TFieldList& fields = leftNodeType.getStruct()->fields();
John Bauman66b8ab22014-05-06 15:57:45 -04001025
Alexis Hetua8b364b2015-06-10 11:48:40 -04001026 size_t structSize = fields.size();
John Bauman66b8ab22014-05-06 15:57:45 -04001027 int index = 0;
1028
1029 for (size_t j = 0; j < structSize; j++) {
Alexis Hetua8b364b2015-06-10 11:48:40 -04001030 int size = fields[j]->type()->getObjectSize();
John Bauman66b8ab22014-05-06 15:57:45 -04001031 for (int i = 0; i < size; i++) {
Alexis Hetua8b364b2015-06-10 11:48:40 -04001032 if (fields[j]->type()->getBasicType() == EbtStruct) {
1033 if (!CompareStructure(*(fields[j]->type()), &rightUnionArray[index], &leftUnionArray[index]))
John Bauman66b8ab22014-05-06 15:57:45 -04001034 return false;
1035 } else {
1036 if (leftUnionArray[index] != rightUnionArray[index])
1037 return false;
1038 index++;
1039 }
1040
1041 }
1042 }
1043 return true;
1044}
1045
1046bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
1047{
1048 if (leftNodeType.isArray()) {
1049 TType typeWithoutArrayness = leftNodeType;
1050 typeWithoutArrayness.clearArrayness();
1051
1052 int arraySize = leftNodeType.getArraySize();
1053
1054 for (int i = 0; i < arraySize; ++i) {
1055 int offset = typeWithoutArrayness.getObjectSize() * i;
1056 if (!CompareStruct(typeWithoutArrayness, &rightUnionArray[offset], &leftUnionArray[offset]))
1057 return false;
1058 }
1059 } else
1060 return CompareStruct(leftNodeType, rightUnionArray, leftUnionArray);
1061
1062 return true;
1063}
1064
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001065float determinant2(float m00, float m01, float m10, float m11)
1066{
1067 return m00 * m11 - m01 * m10;
1068}
1069
1070float determinant3(float m00, float m01, float m02,
1071 float m10, float m11, float m12,
1072 float m20, float m21, float m22)
1073{
1074 return m00 * determinant2(m11, m12, m21, m22) -
1075 m10 * determinant2(m01, m02, m21, m22) +
1076 m20 * determinant2(m01, m02, m11, m12);
1077}
1078
1079float determinant4(float m00, float m01, float m02, float m03,
1080 float m10, float m11, float m12, float m13,
1081 float m20, float m21, float m22, float m23,
1082 float m30, float m31, float m32, float m33)
1083{
1084 return m00 * determinant3(m11, m12, m13, m21, m22, m23, m31, m32, m33) -
1085 m10 * determinant3(m01, m02, m03, m21, m22, m23, m31, m32, m33) +
1086 m20 * determinant3(m01, m02, m03, m11, m12, m13, m31, m32, m33) -
1087 m30 * determinant3(m01, m02, m03, m11, m12, m13, m21, m22, m23);
1088}
1089
1090float ComputeDeterminant(int size, ConstantUnion* unionArray)
1091{
1092 switch(size)
1093 {
1094 case 2:
1095 return determinant2(unionArray[0].getFConst(),
1096 unionArray[1].getFConst(),
1097 unionArray[2].getFConst(),
1098 unionArray[3].getFConst());
1099 case 3:
1100 return determinant3(unionArray[0].getFConst(),
1101 unionArray[1].getFConst(),
1102 unionArray[2].getFConst(),
1103 unionArray[3].getFConst(),
1104 unionArray[4].getFConst(),
1105 unionArray[5].getFConst(),
1106 unionArray[6].getFConst(),
1107 unionArray[7].getFConst(),
1108 unionArray[8].getFConst());
1109 case 4:
1110 return determinant4(unionArray[0].getFConst(),
1111 unionArray[1].getFConst(),
1112 unionArray[2].getFConst(),
1113 unionArray[3].getFConst(),
1114 unionArray[4].getFConst(),
1115 unionArray[5].getFConst(),
1116 unionArray[6].getFConst(),
1117 unionArray[7].getFConst(),
1118 unionArray[8].getFConst(),
1119 unionArray[9].getFConst(),
1120 unionArray[10].getFConst(),
1121 unionArray[11].getFConst(),
1122 unionArray[12].getFConst(),
1123 unionArray[13].getFConst(),
1124 unionArray[14].getFConst(),
1125 unionArray[15].getFConst());
1126 default:
1127 UNREACHABLE();
1128 return 0.0f;
1129 }
1130}
1131
1132ConstantUnion* CreateInverse(TIntermConstantUnion* node, ConstantUnion* unionArray)
1133{
1134 ConstantUnion* tempConstArray = 0;
1135 int size = node->getNominalSize();
1136 float determinant = ComputeDeterminant(size, unionArray);
1137 if(determinant != 0.0f)
1138 {
1139 float invDet = 1.0f / determinant;
1140 tempConstArray = new ConstantUnion[size*size];
1141 switch(size)
1142 {
1143 case 2:
1144 {
1145 float m00 = unionArray[0].getFConst(); // Matrix is:
1146 float m01 = unionArray[1].getFConst(); // (m00, m01)
1147 float m10 = unionArray[2].getFConst(); // (m10, m11)
1148 float m11 = unionArray[3].getFConst();
1149 tempConstArray[0].setFConst( invDet * m11);
1150 tempConstArray[1].setFConst(-invDet * m01);
1151 tempConstArray[2].setFConst(-invDet * m10);
1152 tempConstArray[3].setFConst( invDet * m00);
1153 }
1154 break;
1155 case 3:
1156 {
1157 float m00 = unionArray[0].getFConst(); // Matrix is:
1158 float m01 = unionArray[1].getFConst(); // (m00, m01, m02)
1159 float m02 = unionArray[2].getFConst(); // (m10, m11, m12)
1160 float m10 = unionArray[3].getFConst(); // (m20, m21, m22)
1161 float m11 = unionArray[4].getFConst();
1162 float m12 = unionArray[5].getFConst();
1163 float m20 = unionArray[6].getFConst();
1164 float m21 = unionArray[7].getFConst();
1165 float m22 = unionArray[8].getFConst();
1166 tempConstArray[0].setFConst(invDet * determinant2(m11, m12, m21, m22)); // m00 = invDet * (m11 * m22 - m12 * m21)
1167 tempConstArray[1].setFConst(invDet * determinant2(m12, m10, m22, m20)); // m01 = -invDet * (m10 * m22 - m12 * m20)
1168 tempConstArray[2].setFConst(invDet * determinant2(m10, m11, m20, m21)); // m02 = invDet * (m10 * m21 - m11 * m20)
1169 tempConstArray[3].setFConst(invDet * determinant2(m21, m22, m01, m02)); // m10 = -invDet * (m01 * m22 - m02 * m21)
1170 tempConstArray[4].setFConst(invDet * determinant2(m00, m02, m20, m22)); // m11 = invDet * (m00 * m22 - m02 * m20)
1171 tempConstArray[5].setFConst(invDet * determinant2(m20, m21, m00, m01)); // m12 = -invDet * (m00 * m21 - m01 * m20)
1172 tempConstArray[6].setFConst(invDet * determinant2(m01, m02, m11, m12)); // m20 = invDet * (m01 * m12 - m02 * m11)
1173 tempConstArray[7].setFConst(invDet * determinant2(m10, m12, m00, m02)); // m21 = -invDet * (m00 * m12 - m02 * m10)
1174 tempConstArray[8].setFConst(invDet * determinant2(m00, m01, m10, m11)); // m22 = invDet * (m00 * m11 - m01 * m10)
1175 }
1176 break;
1177 case 4:
1178 {
1179 float m00 = unionArray[0].getFConst(); // Matrix is:
1180 float m01 = unionArray[1].getFConst(); // (m00, m01, m02, m03)
1181 float m02 = unionArray[2].getFConst(); // (m10, m11, m12, m13)
1182 float m03 = unionArray[3].getFConst(); // (m20, m21, m22, m23)
1183 float m10 = unionArray[4].getFConst(); // (m30, m31, m32, m33)
1184 float m11 = unionArray[5].getFConst();
1185 float m12 = unionArray[6].getFConst();
1186 float m13 = unionArray[7].getFConst();
1187 float m20 = unionArray[8].getFConst();
1188 float m21 = unionArray[9].getFConst();
1189 float m22 = unionArray[10].getFConst();
1190 float m23 = unionArray[11].getFConst();
1191 float m30 = unionArray[12].getFConst();
1192 float m31 = unionArray[13].getFConst();
1193 float m32 = unionArray[14].getFConst();
1194 float m33 = unionArray[15].getFConst();
1195 tempConstArray[ 0].setFConst( invDet * determinant3(m11, m12, m13, m21, m22, m23, m31, m32, m33)); // m00
1196 tempConstArray[ 1].setFConst(-invDet * determinant3(m10, m12, m13, m20, m22, m23, m30, m32, m33)); // m01
1197 tempConstArray[ 2].setFConst( invDet * determinant3(m10, m11, m13, m20, m21, m23, m30, m31, m33)); // m02
1198 tempConstArray[ 3].setFConst(-invDet * determinant3(m10, m11, m12, m20, m21, m22, m30, m31, m32)); // m03
1199 tempConstArray[ 4].setFConst( invDet * determinant3(m01, m02, m03, m21, m22, m23, m31, m32, m33)); // m10
1200 tempConstArray[ 5].setFConst(-invDet * determinant3(m00, m02, m03, m20, m22, m23, m30, m32, m33)); // m11
1201 tempConstArray[ 6].setFConst( invDet * determinant3(m00, m01, m03, m20, m21, m23, m30, m31, m33)); // m12
1202 tempConstArray[ 7].setFConst(-invDet * determinant3(m00, m01, m02, m20, m21, m22, m30, m31, m32)); // m13
1203 tempConstArray[ 8].setFConst( invDet * determinant3(m01, m02, m03, m11, m12, m13, m31, m32, m33)); // m20
1204 tempConstArray[ 9].setFConst(-invDet * determinant3(m00, m02, m03, m10, m12, m13, m30, m32, m33)); // m21
1205 tempConstArray[10].setFConst( invDet * determinant3(m00, m01, m03, m10, m11, m13, m30, m31, m33)); // m22
1206 tempConstArray[11].setFConst(-invDet * determinant3(m00, m01, m02, m10, m11, m12, m30, m31, m32)); // m23
1207 tempConstArray[12].setFConst( invDet * determinant3(m01, m02, m03, m11, m12, m13, m21, m22, m23)); // m30
1208 tempConstArray[13].setFConst(-invDet * determinant3(m00, m02, m03, m10, m12, m13, m20, m22, m23)); // m31
1209 tempConstArray[14].setFConst( invDet * determinant3(m00, m01, m03, m10, m11, m13, m20, m21, m23)); // m32
1210 tempConstArray[15].setFConst(-invDet * determinant3(m00, m01, m02, m10, m11, m12, m20, m21, m22)); // m33
1211 }
1212 break;
1213 default:
1214 UNREACHABLE();
1215 }
1216 }
1217 return tempConstArray;
1218}
1219
John Bauman66b8ab22014-05-06 15:57:45 -04001220//
1221// The fold functions see if an operation on a constant can be done in place,
1222// without generating run-time code.
1223//
1224// Returns the node to keep using, which may or may not be the node passed in.
1225//
1226
1227TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNode, TInfoSink& infoSink)
1228{
1229 ConstantUnion *unionArray = getUnionArrayPointer();
1230 int objectSize = getType().getObjectSize();
1231
1232 if (constantNode) { // binary operations
1233 TIntermConstantUnion *node = constantNode->getAsConstantUnion();
1234 ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
1235 TType returnType = getType();
1236
1237 // for a case like float f = 1.2 + vec4(2,3,4,5);
1238 if (constantNode->getType().getObjectSize() == 1 && objectSize > 1) {
1239 rightUnionArray = new ConstantUnion[objectSize];
1240 for (int i = 0; i < objectSize; ++i)
1241 rightUnionArray[i] = *node->getUnionArrayPointer();
1242 returnType = getType();
1243 } else if (constantNode->getType().getObjectSize() > 1 && objectSize == 1) {
1244 // for a case like float f = vec4(2,3,4,5) + 1.2;
1245 unionArray = new ConstantUnion[constantNode->getType().getObjectSize()];
1246 for (int i = 0; i < constantNode->getType().getObjectSize(); ++i)
1247 unionArray[i] = *getUnionArrayPointer();
1248 returnType = node->getType();
1249 objectSize = constantNode->getType().getObjectSize();
1250 }
1251
1252 ConstantUnion* tempConstArray = 0;
1253 TIntermConstantUnion *tempNode;
1254
1255 bool boolNodeFlag = false;
1256 switch(op) {
1257 case EOpAdd:
1258 tempConstArray = new ConstantUnion[objectSize];
1259 {// support MSVC++6.0
1260 for (int i = 0; i < objectSize; i++)
1261 tempConstArray[i] = unionArray[i] + rightUnionArray[i];
1262 }
1263 break;
1264 case EOpSub:
1265 tempConstArray = new ConstantUnion[objectSize];
1266 {// support MSVC++6.0
1267 for (int i = 0; i < objectSize; i++)
1268 tempConstArray[i] = unionArray[i] - rightUnionArray[i];
1269 }
1270 break;
1271
1272 case EOpMul:
1273 case EOpVectorTimesScalar:
1274 case EOpMatrixTimesScalar:
1275 tempConstArray = new ConstantUnion[objectSize];
1276 {// support MSVC++6.0
1277 for (int i = 0; i < objectSize; i++)
1278 tempConstArray[i] = unionArray[i] * rightUnionArray[i];
1279 }
1280 break;
1281 case EOpMatrixTimesMatrix:
1282 if (getType().getBasicType() != EbtFloat || node->getBasicType() != EbtFloat) {
1283 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix multiply", getLine());
1284 return 0;
1285 }
1286 {// support MSVC++6.0
Alexis Hetu00106d42015-04-23 11:45:35 -04001287 int leftNumCols = getNominalSize();
1288 int leftNumRows = getSecondarySize();
1289 int rightNumCols = node->getNominalSize();
1290 int rightNumRows = node->getSecondarySize();
1291 if(leftNumCols != rightNumRows) {
1292 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix multiply", getLine());
1293 return 0;
1294 }
1295 int tempNumCols = rightNumCols;
1296 int tempNumRows = leftNumRows;
1297 int tempNumAdds = leftNumCols;
1298 tempConstArray = new ConstantUnion[tempNumCols*tempNumRows];
1299 for (int row = 0; row < tempNumRows; row++) {
1300 for (int column = 0; column < tempNumCols; column++) {
1301 tempConstArray[tempNumRows * column + row].setFConst(0.0f);
1302 for (int i = 0; i < tempNumAdds; i++) {
1303 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 -04001304 }
1305 }
1306 }
Alexis Hetu00106d42015-04-23 11:45:35 -04001307 // update return type for matrix product
1308 returnType.setNominalSize(static_cast<unsigned char>(tempNumCols));
1309 returnType.setSecondarySize(static_cast<unsigned char>(tempNumRows));
John Bauman66b8ab22014-05-06 15:57:45 -04001310 }
1311 break;
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001312
1313 case EOpOuterProduct:
1314 {
1315 int leftSize = getNominalSize();
1316 int rightSize = node->getNominalSize();
1317 tempConstArray = new ConstantUnion[leftSize*rightSize];
1318 for(int row = 0; row < leftSize; row++) {
1319 for(int column = 0; column < rightSize; column++) {
1320 tempConstArray[leftSize * column + row].setFConst(unionArray[row].getFConst() * rightUnionArray[column].getFConst());
1321 }
1322 }
1323 // update return type for outer product
1324 returnType.setNominalSize(static_cast<unsigned char>(rightSize));
1325 returnType.setSecondarySize(static_cast<unsigned char>(leftSize));
1326 }
1327 break;
1328
1329 case EOpTranspose:
1330 {
1331 int rightCol = node->getNominalSize();
1332 int rightRow = node->getSecondarySize();
1333 tempConstArray = new ConstantUnion[rightCol*rightRow];
1334 for(int row = 0; row < rightRow; row++) {
1335 for(int column = 0; column < rightCol; column++) {
1336 tempConstArray[rightRow * column + row].setFConst(rightUnionArray[rightCol * row + column].getFConst());
1337 }
1338 }
1339 // update return type for transpose
1340 returnType.setNominalSize(static_cast<unsigned char>(rightRow));
1341 returnType.setSecondarySize(static_cast<unsigned char>(rightCol));
1342 }
1343 break;
1344
1345 case EOpDeterminant:
1346 {
1347 ASSERT(node->getNominalSize() == node->getSecondarySize());
1348
1349 tempConstArray = new ConstantUnion[1];
1350 tempConstArray[0].setFConst(ComputeDeterminant(node->getNominalSize(), rightUnionArray));
1351 // update return type for determinant
1352 returnType.setNominalSize(1);
1353 returnType.setSecondarySize(1);
1354 }
1355 break;
1356
1357 case EOpInverse:
1358 {
1359 ASSERT(node->getNominalSize() == node->getSecondarySize());
1360
1361 tempConstArray = CreateInverse(node, rightUnionArray);
1362 if(!tempConstArray)
1363 {
1364 // Singular matrix, just copy
1365 tempConstArray = new ConstantUnion[objectSize];
1366 for(int i = 0; i < objectSize; i++)
1367 tempConstArray[i] = rightUnionArray[i];
1368 }
1369 }
1370 break;
1371
John Bauman66b8ab22014-05-06 15:57:45 -04001372 case EOpDiv:
Alexis Hetud061e422015-05-13 16:37:50 -04001373 case EOpIMod:
John Bauman66b8ab22014-05-06 15:57:45 -04001374 tempConstArray = new ConstantUnion[objectSize];
1375 {// support MSVC++6.0
1376 for (int i = 0; i < objectSize; i++) {
1377 switch (getType().getBasicType()) {
Alexis Hetud061e422015-05-13 16:37:50 -04001378 case EbtFloat:
1379 if (rightUnionArray[i] == 0.0f) {
1380 infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
1381 tempConstArray[i].setFConst(FLT_MAX);
1382 } else {
1383 ASSERT(op == EOpDiv);
1384 tempConstArray[i].setFConst(unionArray[i].getFConst() / rightUnionArray[i].getFConst());
1385 }
1386 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001387
Alexis Hetud061e422015-05-13 16:37:50 -04001388 case EbtInt:
1389 if (rightUnionArray[i] == 0) {
1390 infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
1391 tempConstArray[i].setIConst(INT_MAX);
1392 } else {
1393 if(op == EOpDiv) {
1394 tempConstArray[i].setIConst(unionArray[i].getIConst() / rightUnionArray[i].getIConst());
1395 } else {
1396 ASSERT(op == EOpIMod);
1397 tempConstArray[i].setIConst(unionArray[i].getIConst() % rightUnionArray[i].getIConst());
1398 }
1399 }
1400 break;
1401 case EbtUInt:
1402 if (rightUnionArray[i] == 0) {
1403 infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
1404 tempConstArray[i].setUConst(UINT_MAX);
1405 } else {
1406 if(op == EOpDiv) {
1407 tempConstArray[i].setUConst(unionArray[i].getUConst() / rightUnionArray[i].getUConst());
1408 } else {
1409 ASSERT(op == EOpIMod);
1410 tempConstArray[i].setUConst(unionArray[i].getUConst() % rightUnionArray[i].getUConst());
1411 }
1412 }
1413 break;
1414 default:
1415 infoSink.info.message(EPrefixInternalError, "Constant folding cannot be done for \"/\"", getLine());
1416 return 0;
John Bauman66b8ab22014-05-06 15:57:45 -04001417 }
1418 }
1419 }
1420 break;
1421
1422 case EOpMatrixTimesVector:
1423 if (node->getBasicType() != EbtFloat) {
1424 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix times vector", getLine());
1425 return 0;
1426 }
1427 tempConstArray = new ConstantUnion[getNominalSize()];
1428
1429 {// support MSVC++6.0
1430 for (int size = getNominalSize(), i = 0; i < size; i++) {
1431 tempConstArray[i].setFConst(0.0f);
1432 for (int j = 0; j < size; j++) {
1433 tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j*size + i].getFConst()) * rightUnionArray[j].getFConst()));
1434 }
1435 }
1436 }
1437
1438 tempNode = new TIntermConstantUnion(tempConstArray, node->getType());
1439 tempNode->setLine(getLine());
1440
1441 return tempNode;
1442
1443 case EOpVectorTimesMatrix:
1444 if (getType().getBasicType() != EbtFloat) {
1445 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for vector times matrix", getLine());
1446 return 0;
1447 }
1448
1449 tempConstArray = new ConstantUnion[getNominalSize()];
1450 {// support MSVC++6.0
1451 for (int size = getNominalSize(), i = 0; i < size; i++) {
1452 tempConstArray[i].setFConst(0.0f);
1453 for (int j = 0; j < size; j++) {
1454 tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j].getFConst()) * rightUnionArray[i*size + j].getFConst()));
1455 }
1456 }
1457 }
1458 break;
1459
1460 case EOpLogicalAnd: // this code is written for possible future use, will not get executed currently
1461 tempConstArray = new ConstantUnion[objectSize];
1462 {// support MSVC++6.0
1463 for (int i = 0; i < objectSize; i++)
1464 tempConstArray[i] = unionArray[i] && rightUnionArray[i];
1465 }
1466 break;
1467
1468 case EOpLogicalOr: // this code is written for possible future use, will not get executed currently
1469 tempConstArray = new ConstantUnion[objectSize];
1470 {// support MSVC++6.0
1471 for (int i = 0; i < objectSize; i++)
1472 tempConstArray[i] = unionArray[i] || rightUnionArray[i];
1473 }
1474 break;
1475
1476 case EOpLogicalXor:
1477 tempConstArray = new ConstantUnion[objectSize];
1478 {// support MSVC++6.0
1479 for (int i = 0; i < objectSize; i++)
1480 switch (getType().getBasicType()) {
Alexis Hetud061e422015-05-13 16:37:50 -04001481 case EbtBool: tempConstArray[i].setBConst((unionArray[i] == rightUnionArray[i]) ? false : true); break;
1482 default: assert(false && "Default missing");
John Bauman66b8ab22014-05-06 15:57:45 -04001483 }
1484 }
1485 break;
1486
Alexis Hetud061e422015-05-13 16:37:50 -04001487 case EOpBitwiseAnd:
1488 tempConstArray = new ConstantUnion[objectSize];
1489 for(int i = 0; i < objectSize; i++)
1490 tempConstArray[i] = unionArray[i] & rightUnionArray[i];
1491 break;
1492 case EOpBitwiseXor:
1493 tempConstArray = new ConstantUnion[objectSize];
1494 for(int i = 0; i < objectSize; i++)
1495 tempConstArray[i] = unionArray[i] ^ rightUnionArray[i];
1496 break;
1497 case EOpBitwiseOr:
1498 tempConstArray = new ConstantUnion[objectSize];
1499 for(int i = 0; i < objectSize; i++)
1500 tempConstArray[i] = unionArray[i] | rightUnionArray[i];
1501 break;
1502 case EOpBitShiftLeft:
1503 tempConstArray = new ConstantUnion[objectSize];
1504 for(int i = 0; i < objectSize; i++)
1505 tempConstArray[i] = unionArray[i] << rightUnionArray[i];
1506 break;
1507 case EOpBitShiftRight:
1508 tempConstArray = new ConstantUnion[objectSize];
1509 for(int i = 0; i < objectSize; i++)
1510 tempConstArray[i] = unionArray[i] >> rightUnionArray[i];
1511 break;
1512
John Bauman66b8ab22014-05-06 15:57:45 -04001513 case EOpLessThan:
1514 assert(objectSize == 1);
1515 tempConstArray = new ConstantUnion[1];
1516 tempConstArray->setBConst(*unionArray < *rightUnionArray);
Nicolas Capens31ad2aa2015-02-26 13:14:27 -05001517 returnType = TType(EbtBool, EbpUndefined, EvqConstExpr);
John Bauman66b8ab22014-05-06 15:57:45 -04001518 break;
1519 case EOpGreaterThan:
1520 assert(objectSize == 1);
1521 tempConstArray = new ConstantUnion[1];
1522 tempConstArray->setBConst(*unionArray > *rightUnionArray);
Nicolas Capens31ad2aa2015-02-26 13:14:27 -05001523 returnType = TType(EbtBool, EbpUndefined, EvqConstExpr);
John Bauman66b8ab22014-05-06 15:57:45 -04001524 break;
1525 case EOpLessThanEqual:
1526 {
1527 assert(objectSize == 1);
1528 ConstantUnion constant;
1529 constant.setBConst(*unionArray > *rightUnionArray);
1530 tempConstArray = new ConstantUnion[1];
1531 tempConstArray->setBConst(!constant.getBConst());
Nicolas Capens31ad2aa2015-02-26 13:14:27 -05001532 returnType = TType(EbtBool, EbpUndefined, EvqConstExpr);
John Bauman66b8ab22014-05-06 15:57:45 -04001533 break;
1534 }
1535 case EOpGreaterThanEqual:
1536 {
1537 assert(objectSize == 1);
1538 ConstantUnion constant;
1539 constant.setBConst(*unionArray < *rightUnionArray);
1540 tempConstArray = new ConstantUnion[1];
1541 tempConstArray->setBConst(!constant.getBConst());
Nicolas Capens31ad2aa2015-02-26 13:14:27 -05001542 returnType = TType(EbtBool, EbpUndefined, EvqConstExpr);
John Bauman66b8ab22014-05-06 15:57:45 -04001543 break;
1544 }
1545
1546 case EOpEqual:
1547 if (getType().getBasicType() == EbtStruct) {
1548 if (!CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray))
1549 boolNodeFlag = true;
1550 } else {
1551 for (int i = 0; i < objectSize; i++) {
1552 if (unionArray[i] != rightUnionArray[i]) {
1553 boolNodeFlag = true;
1554 break; // break out of for loop
1555 }
1556 }
1557 }
1558
1559 tempConstArray = new ConstantUnion[1];
1560 if (!boolNodeFlag) {
1561 tempConstArray->setBConst(true);
1562 }
1563 else {
1564 tempConstArray->setBConst(false);
1565 }
1566
Nicolas Capens31ad2aa2015-02-26 13:14:27 -05001567 tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConstExpr));
John Bauman66b8ab22014-05-06 15:57:45 -04001568 tempNode->setLine(getLine());
1569
1570 return tempNode;
1571
1572 case EOpNotEqual:
1573 if (getType().getBasicType() == EbtStruct) {
1574 if (CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray))
1575 boolNodeFlag = true;
1576 } else {
1577 for (int i = 0; i < objectSize; i++) {
1578 if (unionArray[i] == rightUnionArray[i]) {
1579 boolNodeFlag = true;
1580 break; // break out of for loop
1581 }
1582 }
1583 }
1584
1585 tempConstArray = new ConstantUnion[1];
1586 if (!boolNodeFlag) {
1587 tempConstArray->setBConst(true);
1588 }
1589 else {
1590 tempConstArray->setBConst(false);
1591 }
1592
Nicolas Capens31ad2aa2015-02-26 13:14:27 -05001593 tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConstExpr));
John Bauman66b8ab22014-05-06 15:57:45 -04001594 tempNode->setLine(getLine());
1595
1596 return tempNode;
1597
1598 default:
1599 infoSink.info.message(EPrefixInternalError, "Invalid operator for constant folding", getLine());
1600 return 0;
1601 }
1602 tempNode = new TIntermConstantUnion(tempConstArray, returnType);
1603 tempNode->setLine(getLine());
1604
1605 return tempNode;
1606 } else {
1607 //
1608 // Do unary operations
1609 //
1610 TIntermConstantUnion *newNode = 0;
1611 ConstantUnion* tempConstArray = new ConstantUnion[objectSize];
1612 for (int i = 0; i < objectSize; i++) {
1613 switch(op) {
1614 case EOpNegative:
1615 switch (getType().getBasicType()) {
1616 case EbtFloat: tempConstArray[i].setFConst(-unionArray[i].getFConst()); break;
1617 case EbtInt: tempConstArray[i].setIConst(-unionArray[i].getIConst()); break;
1618 default:
1619 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1620 return 0;
1621 }
1622 break;
1623 case EOpLogicalNot: // this code is written for possible future use, will not get executed currently
1624 switch (getType().getBasicType()) {
1625 case EbtBool: tempConstArray[i].setBConst(!unionArray[i].getBConst()); break;
1626 default:
1627 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1628 return 0;
1629 }
1630 break;
Alexis Hetud061e422015-05-13 16:37:50 -04001631 case EOpBitwiseNot:
1632 switch(getType().getBasicType()) {
1633 case EbtInt: tempConstArray[i].setIConst(~unionArray[i].getIConst()); break;
1634 case EbtUInt: tempConstArray[i].setUConst(~unionArray[i].getUConst()); break;
1635 default:
1636 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1637 return 0;
1638 }
1639 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001640 default:
1641 return 0;
1642 }
1643 }
1644 newNode = new TIntermConstantUnion(tempConstArray, getType());
1645 newNode->setLine(getLine());
1646 return newNode;
1647 }
1648}
1649
1650TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermConstantUnion* node)
1651{
John Bauman66b8ab22014-05-06 15:57:45 -04001652 int size = node->getType().getObjectSize();
1653
1654 ConstantUnion *leftUnionArray = new ConstantUnion[size];
1655
1656 for (int i=0; i < size; i++) {
1657
1658 switch (promoteTo) {
1659 case EbtFloat:
1660 switch (node->getType().getBasicType()) {
1661 case EbtInt:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001662 leftUnionArray[i].setFConst(static_cast<float>(node->getIConst(i)));
John Bauman66b8ab22014-05-06 15:57:45 -04001663 break;
Nicolas Capens3c20f802015-02-17 17:17:20 -05001664 case EbtUInt:
1665 leftUnionArray[i].setFConst(static_cast<float>(node->getUConst(i)));
1666 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001667 case EbtBool:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001668 leftUnionArray[i].setFConst(static_cast<float>(node->getBConst(i)));
John Bauman66b8ab22014-05-06 15:57:45 -04001669 break;
1670 case EbtFloat:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001671 leftUnionArray[i].setFConst(static_cast<float>(node->getFConst(i)));
John Bauman66b8ab22014-05-06 15:57:45 -04001672 break;
1673 default:
1674 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
1675 return 0;
1676 }
1677 break;
1678 case EbtInt:
1679 switch (node->getType().getBasicType()) {
1680 case EbtInt:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001681 leftUnionArray[i].setIConst(static_cast<int>(node->getIConst(i)));
John Bauman66b8ab22014-05-06 15:57:45 -04001682 break;
Nicolas Capens3c20f802015-02-17 17:17:20 -05001683 case EbtUInt:
1684 leftUnionArray[i].setIConst(static_cast<int>(node->getUConst(i)));
1685 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001686 case EbtBool:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001687 leftUnionArray[i].setIConst(static_cast<int>(node->getBConst(i)));
John Bauman66b8ab22014-05-06 15:57:45 -04001688 break;
1689 case EbtFloat:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001690 leftUnionArray[i].setIConst(static_cast<int>(node->getFConst(i)));
John Bauman66b8ab22014-05-06 15:57:45 -04001691 break;
1692 default:
1693 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
1694 return 0;
1695 }
1696 break;
Nicolas Capens3c20f802015-02-17 17:17:20 -05001697 case EbtUInt:
1698 switch (node->getType().getBasicType()) {
1699 case EbtInt:
1700 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getIConst(i)));
1701 break;
1702 case EbtUInt:
1703 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getUConst(i)));
1704 break;
1705 case EbtBool:
1706 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getBConst(i)));
1707 break;
1708 case EbtFloat:
1709 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getFConst(i)));
1710 break;
1711 default:
1712 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
1713 return 0;
1714 }
1715 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001716 case EbtBool:
1717 switch (node->getType().getBasicType()) {
1718 case EbtInt:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001719 leftUnionArray[i].setBConst(node->getIConst(i) != 0);
John Bauman66b8ab22014-05-06 15:57:45 -04001720 break;
Nicolas Capens3c20f802015-02-17 17:17:20 -05001721 case EbtUInt:
1722 leftUnionArray[i].setBConst(node->getUConst(i) != 0);
1723 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001724 case EbtBool:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001725 leftUnionArray[i].setBConst(node->getBConst(i));
John Bauman66b8ab22014-05-06 15:57:45 -04001726 break;
1727 case EbtFloat:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001728 leftUnionArray[i].setBConst(node->getFConst(i) != 0.0f);
John Bauman66b8ab22014-05-06 15:57:45 -04001729 break;
1730 default:
1731 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
1732 return 0;
1733 }
1734
1735 break;
1736 default:
1737 infoSink.info.message(EPrefixInternalError, "Incorrect data type found", node->getLine());
1738 return 0;
1739 }
1740
1741 }
1742
1743 const TType& t = node->getType();
1744
Alexis Hetub14178b2015-04-13 13:23:20 -04001745 return addConstantUnion(leftUnionArray, TType(promoteTo, t.getPrecision(), t.getQualifier(), t.getNominalSize(), t.getSecondarySize(), t.isArray()), node->getLine());
John Bauman66b8ab22014-05-06 15:57:45 -04001746}
1747