blob: 0579deb4860a8944d0ef3c5d8aa4ac6a408a7065 [file] [log] [blame]
John Bauman66b8ab22014-05-06 15:57:45 -04001//
John Baumand4ae8632014-05-06 16:18:33 -04002// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
John Bauman66b8ab22014-05-06 15:57:45 -04003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7//
8// Build the intermediate representation.
9//
10
11#include <float.h>
12#include <limits.h>
13#include <algorithm>
14
Nicolas Capenscc863da2015-01-21 15:50:55 -050015#include "localintermediate.h"
16#include "SymbolTable.h"
John Bauman66b8ab22014-05-06 15:57:45 -040017
18bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray);
19
20static TPrecision GetHigherPrecision( TPrecision left, TPrecision right ){
21 return left > right ? left : right;
22}
23
Alexis Hetu00106d42015-04-23 11:45:35 -040024static bool ValidateMultiplication(TOperator op, const TType &left, const TType &right)
25{
26 switch(op)
27 {
28 case EOpMul:
29 case EOpMulAssign:
30 return left.getNominalSize() == right.getNominalSize() &&
31 left.getSecondarySize() == right.getSecondarySize();
32 case EOpVectorTimesScalar:
33 case EOpVectorTimesScalarAssign:
34 return true;
35 case EOpVectorTimesMatrix:
36 return left.getNominalSize() == right.getSecondarySize();
37 case EOpVectorTimesMatrixAssign:
38 return left.getNominalSize() == right.getSecondarySize() &&
39 left.getNominalSize() == right.getNominalSize();
40 case EOpMatrixTimesVector:
41 return left.getNominalSize() == right.getNominalSize();
42 case EOpMatrixTimesScalar:
43 case EOpMatrixTimesScalarAssign:
44 return true;
45 case EOpMatrixTimesMatrix:
46 return left.getNominalSize() == right.getSecondarySize();
47 case EOpMatrixTimesMatrixAssign:
48 return left.getNominalSize() == right.getNominalSize() &&
49 left.getSecondarySize() == right.getSecondarySize();
50 default:
Nicolas Capens3713cd42015-06-22 10:41:54 -040051 UNREACHABLE(op);
Alexis Hetu00106d42015-04-23 11:45:35 -040052 return false;
53 }
54}
55
John Bauman66b8ab22014-05-06 15:57:45 -040056const char* getOperatorString(TOperator op) {
57 switch (op) {
58 case EOpInitialize: return "=";
59 case EOpAssign: return "=";
60 case EOpAddAssign: return "+=";
61 case EOpSubAssign: return "-=";
62 case EOpDivAssign: return "/=";
Alexis Hetu17809052015-05-13 11:28:22 -040063 case EOpIModAssign: return "%=";
64 case EOpBitShiftLeftAssign: return "<<=";
65 case EOpBitShiftRightAssign: return ">>=";
66 case EOpBitwiseAndAssign: return "&=";
67 case EOpBitwiseXorAssign: return "^=";
68 case EOpBitwiseOrAssign: return "|=";
John Bauman66b8ab22014-05-06 15:57:45 -040069
70 // Fall-through.
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -040071 case EOpMulAssign:
John Bauman66b8ab22014-05-06 15:57:45 -040072 case EOpVectorTimesMatrixAssign:
73 case EOpVectorTimesScalarAssign:
74 case EOpMatrixTimesScalarAssign:
75 case EOpMatrixTimesMatrixAssign: return "*=";
76
77 // Fall-through.
78 case EOpIndexDirect:
79 case EOpIndexIndirect: return "[]";
80
81 case EOpIndexDirectStruct: return ".";
82 case EOpVectorSwizzle: return ".";
83 case EOpAdd: return "+";
84 case EOpSub: return "-";
85 case EOpMul: return "*";
86 case EOpDiv: return "/";
87 case EOpMod: UNIMPLEMENTED(); break;
88 case EOpEqual: return "==";
89 case EOpNotEqual: return "!=";
90 case EOpLessThan: return "<";
91 case EOpGreaterThan: return ">";
92 case EOpLessThanEqual: return "<=";
93 case EOpGreaterThanEqual: return ">=";
94
95 // Fall-through.
96 case EOpVectorTimesScalar:
97 case EOpVectorTimesMatrix:
98 case EOpMatrixTimesVector:
99 case EOpMatrixTimesScalar:
100 case EOpMatrixTimesMatrix: return "*";
101
102 case EOpLogicalOr: return "||";
103 case EOpLogicalXor: return "^^";
104 case EOpLogicalAnd: return "&&";
Alexis Hetu17809052015-05-13 11:28:22 -0400105 case EOpIMod: return "%";
106 case EOpBitShiftLeft: return "<<";
107 case EOpBitShiftRight: return ">>";
108 case EOpBitwiseAnd: return "&";
109 case EOpBitwiseXor: return "^";
110 case EOpBitwiseOr: return "|";
John Bauman66b8ab22014-05-06 15:57:45 -0400111 case EOpNegative: return "-";
112 case EOpVectorLogicalNot: return "not";
113 case EOpLogicalNot: return "!";
Alexis Hetu17809052015-05-13 11:28:22 -0400114 case EOpBitwiseNot: return "~";
John Bauman66b8ab22014-05-06 15:57:45 -0400115 case EOpPostIncrement: return "++";
116 case EOpPostDecrement: return "--";
117 case EOpPreIncrement: return "++";
118 case EOpPreDecrement: return "--";
119
John Bauman66b8ab22014-05-06 15:57:45 -0400120 case EOpRadians: return "radians";
121 case EOpDegrees: return "degrees";
122 case EOpSin: return "sin";
123 case EOpCos: return "cos";
124 case EOpTan: return "tan";
125 case EOpAsin: return "asin";
126 case EOpAcos: return "acos";
127 case EOpAtan: return "atan";
Alexis Hetuaf1970c2015-04-17 14:26:07 -0400128 case EOpSinh: return "sinh";
129 case EOpCosh: return "cosh";
130 case EOpTanh: return "tanh";
131 case EOpAsinh: return "asinh";
132 case EOpAcosh: return "acosh";
133 case EOpAtanh: return "atanh";
John Bauman66b8ab22014-05-06 15:57:45 -0400134 case EOpExp: return "exp";
135 case EOpLog: return "log";
136 case EOpExp2: return "exp2";
137 case EOpLog2: return "log2";
138 case EOpSqrt: return "sqrt";
139 case EOpInverseSqrt: return "inversesqrt";
140 case EOpAbs: return "abs";
141 case EOpSign: return "sign";
142 case EOpFloor: return "floor";
Alexis Hetuaf1970c2015-04-17 14:26:07 -0400143 case EOpTrunc: return "trunc";
144 case EOpRound: return "round";
145 case EOpRoundEven: return "roundEven";
John Bauman66b8ab22014-05-06 15:57:45 -0400146 case EOpCeil: return "ceil";
147 case EOpFract: return "fract";
148 case EOpLength: return "length";
149 case EOpNormalize: return "normalize";
150 case EOpDFdx: return "dFdx";
151 case EOpDFdy: return "dFdy";
152 case EOpFwidth: return "fwidth";
153 case EOpAny: return "any";
154 case EOpAll: return "all";
Alexis Hetuaf1970c2015-04-17 14:26:07 -0400155 case EOpIsNan: return "isnan";
156 case EOpIsInf: return "isinf";
Alexis Hetu3815b6c2015-05-27 11:21:37 -0400157 case EOpOuterProduct: return "outerProduct";
158 case EOpTranspose: return "transpose";
159 case EOpDeterminant: return "determinant";
160 case EOpInverse: return "inverse";
John Bauman66b8ab22014-05-06 15:57:45 -0400161
162 default: break;
163 }
164 return "";
165}
166
167////////////////////////////////////////////////////////////////////////////
168//
169// First set of functions are to help build the intermediate representation.
170// These functions are not member functions of the nodes.
171// They are called from parser productions.
172//
173/////////////////////////////////////////////////////////////////////////////
174
175//
176// Add a terminal node for an identifier in an expression.
177//
178// Returns the added node.
179//
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{
Alexis Hetue5246692015-06-18 12:34:52 -0400783 ASSERT(left->isArray() == right->isArray());
John Bauman66b8ab22014-05-06 15:57:45 -0400784
785 // GLSL ES 2.0 does not support implicit type casting.
786 // So the basic type should always match.
787 if (left->getBasicType() != right->getBasicType())
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400788 {
John Bauman66b8ab22014-05-06 15:57:45 -0400789 return false;
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400790 }
John Bauman66b8ab22014-05-06 15:57:45 -0400791
792 //
793 // Base assumption: just make the type the same as the left
794 // operand. Then only deviations from this need be coded.
795 //
796 setType(left->getType());
797
798 // The result gets promoted to the highest precision.
799 TPrecision higherPrecision = GetHigherPrecision(left->getPrecision(), right->getPrecision());
800 getTypePointer()->setPrecision(higherPrecision);
801
802 // Binary operations results in temporary variables unless both
803 // operands are const.
Nicolas Capens31ad2aa2015-02-26 13:14:27 -0500804 if (left->getQualifier() != EvqConstExpr || right->getQualifier() != EvqConstExpr) {
John Bauman66b8ab22014-05-06 15:57:45 -0400805 getTypePointer()->setQualifier(EvqTemporary);
806 }
807
Alexis Hetud061e422015-05-13 16:37:50 -0400808 int primarySize = std::max(left->getNominalSize(), right->getNominalSize());
John Bauman66b8ab22014-05-06 15:57:45 -0400809
810 //
811 // All scalars. Code after this test assumes this case is removed!
812 //
Alexis Hetud061e422015-05-13 16:37:50 -0400813 if (primarySize == 1) {
John Bauman66b8ab22014-05-06 15:57:45 -0400814 switch (op) {
815 //
816 // Promote to conditional
817 //
818 case EOpEqual:
819 case EOpNotEqual:
820 case EOpLessThan:
821 case EOpGreaterThan:
822 case EOpLessThanEqual:
823 case EOpGreaterThanEqual:
824 setType(TType(EbtBool, EbpUndefined));
825 break;
826
827 //
828 // And and Or operate on conditionals
829 //
830 case EOpLogicalAnd:
831 case EOpLogicalOr:
Alexis Hetud061e422015-05-13 16:37:50 -0400832 case EOpLogicalXor:
John Bauman66b8ab22014-05-06 15:57:45 -0400833 // Both operands must be of type bool.
834 if (left->getBasicType() != EbtBool || right->getBasicType() != EbtBool)
835 return false;
836 setType(TType(EbtBool, EbpUndefined));
837 break;
838
839 default:
840 break;
841 }
842 return true;
843 }
844
845 // If we reach here, at least one of the operands is vector or matrix.
846 // The other operand could be a scalar, vector, or matrix.
John Bauman66b8ab22014-05-06 15:57:45 -0400847 // Can these two operands be combined?
848 //
849 TBasicType basicType = left->getBasicType();
850 switch (op) {
851 case EOpMul:
852 if (!left->isMatrix() && right->isMatrix()) {
853 if (left->isVector())
Alexis Hetu00106d42015-04-23 11:45:35 -0400854 {
John Bauman66b8ab22014-05-06 15:57:45 -0400855 op = EOpVectorTimesMatrix;
Alexis Hetu00106d42015-04-23 11:45:35 -0400856 setType(TType(basicType, higherPrecision, EvqTemporary,
857 static_cast<unsigned char>(right->getNominalSize()), 1));
858 }
John Bauman66b8ab22014-05-06 15:57:45 -0400859 else {
860 op = EOpMatrixTimesScalar;
Alexis Hetu00106d42015-04-23 11:45:35 -0400861 setType(TType(basicType, higherPrecision, EvqTemporary,
862 static_cast<unsigned char>(right->getNominalSize()), static_cast<unsigned char>(right->getSecondarySize())));
John Bauman66b8ab22014-05-06 15:57:45 -0400863 }
864 } else if (left->isMatrix() && !right->isMatrix()) {
865 if (right->isVector()) {
866 op = EOpMatrixTimesVector;
Alexis Hetu00106d42015-04-23 11:45:35 -0400867 setType(TType(basicType, higherPrecision, EvqTemporary,
868 static_cast<unsigned char>(left->getSecondarySize()), 1));
John Bauman66b8ab22014-05-06 15:57:45 -0400869 } else {
870 op = EOpMatrixTimesScalar;
871 }
872 } else if (left->isMatrix() && right->isMatrix()) {
873 op = EOpMatrixTimesMatrix;
Alexis Hetu00106d42015-04-23 11:45:35 -0400874 setType(TType(basicType, higherPrecision, EvqTemporary,
875 static_cast<unsigned char>(right->getNominalSize()), static_cast<unsigned char>(left->getSecondarySize())));
John Bauman66b8ab22014-05-06 15:57:45 -0400876 } else if (!left->isMatrix() && !right->isMatrix()) {
877 if (left->isVector() && right->isVector()) {
878 // leave as component product
879 } else if (left->isVector() || right->isVector()) {
880 op = EOpVectorTimesScalar;
Alexis Hetu00106d42015-04-23 11:45:35 -0400881 setType(TType(basicType, higherPrecision, EvqTemporary,
882 static_cast<unsigned char>(primarySize), 1));
John Bauman66b8ab22014-05-06 15:57:45 -0400883 }
884 } else {
885 infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
886 return false;
887 }
Alexis Hetu00106d42015-04-23 11:45:35 -0400888
889 if(!ValidateMultiplication(op, left->getType(), right->getType()))
890 {
891 return false;
892 }
John Bauman66b8ab22014-05-06 15:57:45 -0400893 break;
894 case EOpMulAssign:
895 if (!left->isMatrix() && right->isMatrix()) {
896 if (left->isVector())
897 op = EOpVectorTimesMatrixAssign;
898 else {
899 return false;
900 }
901 } else if (left->isMatrix() && !right->isMatrix()) {
902 if (right->isVector()) {
903 return false;
904 } else {
905 op = EOpMatrixTimesScalarAssign;
906 }
907 } else if (left->isMatrix() && right->isMatrix()) {
908 op = EOpMatrixTimesMatrixAssign;
Alexis Hetu00106d42015-04-23 11:45:35 -0400909 setType(TType(basicType, higherPrecision, EvqTemporary,
910 static_cast<unsigned char>(right->getNominalSize()), static_cast<unsigned char>(left->getSecondarySize())));
John Bauman66b8ab22014-05-06 15:57:45 -0400911 } else if (!left->isMatrix() && !right->isMatrix()) {
912 if (left->isVector() && right->isVector()) {
913 // leave as component product
914 } else if (left->isVector() || right->isVector()) {
915 if (! left->isVector())
916 return false;
917 op = EOpVectorTimesScalarAssign;
Alexis Hetu00106d42015-04-23 11:45:35 -0400918 setType(TType(basicType, higherPrecision, EvqTemporary,
919 static_cast<unsigned char>(left->getNominalSize()), 1));
John Bauman66b8ab22014-05-06 15:57:45 -0400920 }
921 } else {
922 infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
923 return false;
924 }
Alexis Hetu00106d42015-04-23 11:45:35 -0400925
926 if(!ValidateMultiplication(op, left->getType(), right->getType()))
927 {
928 return false;
929 }
John Bauman66b8ab22014-05-06 15:57:45 -0400930 break;
931
932 case EOpAssign:
933 case EOpInitialize:
Alexis Hetu00106d42015-04-23 11:45:35 -0400934 // No more additional checks are needed.
935 if ((left->getNominalSize() != right->getNominalSize()) ||
936 (left->getSecondarySize() != right->getSecondarySize()))
937 return false;
938 break;
John Bauman66b8ab22014-05-06 15:57:45 -0400939 case EOpAdd:
940 case EOpSub:
941 case EOpDiv:
Alexis Hetud061e422015-05-13 16:37:50 -0400942 case EOpIMod:
943 case EOpBitShiftLeft:
944 case EOpBitShiftRight:
945 case EOpBitwiseAnd:
946 case EOpBitwiseXor:
947 case EOpBitwiseOr:
John Bauman66b8ab22014-05-06 15:57:45 -0400948 case EOpAddAssign:
949 case EOpSubAssign:
950 case EOpDivAssign:
Alexis Hetu17809052015-05-13 11:28:22 -0400951 case EOpIModAssign:
952 case EOpBitShiftLeftAssign:
953 case EOpBitShiftRightAssign:
954 case EOpBitwiseAndAssign:
955 case EOpBitwiseXorAssign:
956 case EOpBitwiseOrAssign:
John Bauman66b8ab22014-05-06 15:57:45 -0400957 if ((left->isMatrix() && right->isVector()) ||
958 (left->isVector() && right->isMatrix()))
959 return false;
Alexis Hetud061e422015-05-13 16:37:50 -0400960
961 // Are the sizes compatible?
962 if(left->getNominalSize() != right->getNominalSize() ||
963 left->getSecondarySize() != right->getSecondarySize())
964 {
965 // If the nominal sizes of operands do not match:
966 // One of them must be a scalar.
967 if(!left->isScalar() && !right->isScalar())
968 return false;
969
970 // In the case of compound assignment other than multiply-assign,
971 // the right side needs to be a scalar. Otherwise a vector/matrix
972 // would be assigned to a scalar. A scalar can't be shifted by a
973 // vector either.
974 if(!right->isScalar() && (modifiesState() || op == EOpBitShiftLeft || op == EOpBitShiftRight))
975 return false;
976 }
977
978 {
Alexis Hetu00106d42015-04-23 11:45:35 -0400979 const int secondarySize = std::max(
980 left->getSecondarySize(), right->getSecondarySize());
Alexis Hetud061e422015-05-13 16:37:50 -0400981 setType(TType(basicType, higherPrecision, EvqTemporary,
982 static_cast<unsigned char>(primarySize), static_cast<unsigned char>(secondarySize)));
983 if(left->isArray())
984 {
985 ASSERT(left->getArraySize() == right->getArraySize());
986 type.setArraySize(left->getArraySize());
987 }
988 }
John Bauman66b8ab22014-05-06 15:57:45 -0400989 break;
990
991 case EOpEqual:
992 case EOpNotEqual:
993 case EOpLessThan:
994 case EOpGreaterThan:
995 case EOpLessThanEqual:
996 case EOpGreaterThanEqual:
Alexis Hetu00106d42015-04-23 11:45:35 -0400997 if ((left->getNominalSize() != right->getNominalSize()) ||
998 (left->getSecondarySize() != right->getSecondarySize()))
John Bauman66b8ab22014-05-06 15:57:45 -0400999 return false;
1000 setType(TType(EbtBool, EbpUndefined));
1001 break;
1002
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001003 case EOpOuterProduct:
1004 if(!left->isVector() || !right->isVector())
1005 return false;
1006 setType(TType(EbtFloat, right->getNominalSize(), left->getNominalSize()));
1007 break;
1008
1009 case EOpTranspose:
1010 if(!right->isMatrix())
1011 return false;
1012 setType(TType(EbtFloat, right->getSecondarySize(), right->getNominalSize()));
1013 break;
1014
1015 case EOpDeterminant:
1016 if(!right->isMatrix())
1017 return false;
1018 setType(TType(EbtFloat));
1019 break;
1020
1021 case EOpInverse:
1022 if(!right->isMatrix() || right->getNominalSize() != right->getSecondarySize())
1023 return false;
1024 setType(right->getType());
1025 break;
1026
John Bauman66b8ab22014-05-06 15:57:45 -04001027 default:
1028 return false;
1029 }
1030
1031 return true;
1032}
1033
1034bool CompareStruct(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
1035{
Alexis Hetua8b364b2015-06-10 11:48:40 -04001036 const TFieldList& fields = leftNodeType.getStruct()->fields();
John Bauman66b8ab22014-05-06 15:57:45 -04001037
Alexis Hetua8b364b2015-06-10 11:48:40 -04001038 size_t structSize = fields.size();
John Bauman66b8ab22014-05-06 15:57:45 -04001039 int index = 0;
1040
1041 for (size_t j = 0; j < structSize; j++) {
Alexis Hetua8b364b2015-06-10 11:48:40 -04001042 int size = fields[j]->type()->getObjectSize();
John Bauman66b8ab22014-05-06 15:57:45 -04001043 for (int i = 0; i < size; i++) {
Alexis Hetua8b364b2015-06-10 11:48:40 -04001044 if (fields[j]->type()->getBasicType() == EbtStruct) {
1045 if (!CompareStructure(*(fields[j]->type()), &rightUnionArray[index], &leftUnionArray[index]))
John Bauman66b8ab22014-05-06 15:57:45 -04001046 return false;
1047 } else {
1048 if (leftUnionArray[index] != rightUnionArray[index])
1049 return false;
1050 index++;
1051 }
1052
1053 }
1054 }
1055 return true;
1056}
1057
1058bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
1059{
1060 if (leftNodeType.isArray()) {
1061 TType typeWithoutArrayness = leftNodeType;
1062 typeWithoutArrayness.clearArrayness();
1063
1064 int arraySize = leftNodeType.getArraySize();
1065
1066 for (int i = 0; i < arraySize; ++i) {
1067 int offset = typeWithoutArrayness.getObjectSize() * i;
1068 if (!CompareStruct(typeWithoutArrayness, &rightUnionArray[offset], &leftUnionArray[offset]))
1069 return false;
1070 }
1071 } else
1072 return CompareStruct(leftNodeType, rightUnionArray, leftUnionArray);
1073
1074 return true;
1075}
1076
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001077float determinant2(float m00, float m01, float m10, float m11)
1078{
1079 return m00 * m11 - m01 * m10;
1080}
1081
1082float determinant3(float m00, float m01, float m02,
1083 float m10, float m11, float m12,
1084 float m20, float m21, float m22)
1085{
1086 return m00 * determinant2(m11, m12, m21, m22) -
1087 m10 * determinant2(m01, m02, m21, m22) +
1088 m20 * determinant2(m01, m02, m11, m12);
1089}
1090
1091float determinant4(float m00, float m01, float m02, float m03,
1092 float m10, float m11, float m12, float m13,
1093 float m20, float m21, float m22, float m23,
1094 float m30, float m31, float m32, float m33)
1095{
1096 return m00 * determinant3(m11, m12, m13, m21, m22, m23, m31, m32, m33) -
1097 m10 * determinant3(m01, m02, m03, m21, m22, m23, m31, m32, m33) +
1098 m20 * determinant3(m01, m02, m03, m11, m12, m13, m31, m32, m33) -
1099 m30 * determinant3(m01, m02, m03, m11, m12, m13, m21, m22, m23);
1100}
1101
1102float ComputeDeterminant(int size, ConstantUnion* unionArray)
1103{
1104 switch(size)
1105 {
1106 case 2:
1107 return determinant2(unionArray[0].getFConst(),
1108 unionArray[1].getFConst(),
1109 unionArray[2].getFConst(),
1110 unionArray[3].getFConst());
1111 case 3:
1112 return determinant3(unionArray[0].getFConst(),
1113 unionArray[1].getFConst(),
1114 unionArray[2].getFConst(),
1115 unionArray[3].getFConst(),
1116 unionArray[4].getFConst(),
1117 unionArray[5].getFConst(),
1118 unionArray[6].getFConst(),
1119 unionArray[7].getFConst(),
1120 unionArray[8].getFConst());
1121 case 4:
1122 return determinant4(unionArray[0].getFConst(),
1123 unionArray[1].getFConst(),
1124 unionArray[2].getFConst(),
1125 unionArray[3].getFConst(),
1126 unionArray[4].getFConst(),
1127 unionArray[5].getFConst(),
1128 unionArray[6].getFConst(),
1129 unionArray[7].getFConst(),
1130 unionArray[8].getFConst(),
1131 unionArray[9].getFConst(),
1132 unionArray[10].getFConst(),
1133 unionArray[11].getFConst(),
1134 unionArray[12].getFConst(),
1135 unionArray[13].getFConst(),
1136 unionArray[14].getFConst(),
1137 unionArray[15].getFConst());
1138 default:
Nicolas Capens3713cd42015-06-22 10:41:54 -04001139 UNREACHABLE(size);
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001140 return 0.0f;
1141 }
1142}
1143
1144ConstantUnion* CreateInverse(TIntermConstantUnion* node, ConstantUnion* unionArray)
1145{
1146 ConstantUnion* tempConstArray = 0;
1147 int size = node->getNominalSize();
1148 float determinant = ComputeDeterminant(size, unionArray);
1149 if(determinant != 0.0f)
1150 {
1151 float invDet = 1.0f / determinant;
1152 tempConstArray = new ConstantUnion[size*size];
1153 switch(size)
1154 {
1155 case 2:
1156 {
1157 float m00 = unionArray[0].getFConst(); // Matrix is:
1158 float m01 = unionArray[1].getFConst(); // (m00, m01)
1159 float m10 = unionArray[2].getFConst(); // (m10, m11)
1160 float m11 = unionArray[3].getFConst();
1161 tempConstArray[0].setFConst( invDet * m11);
1162 tempConstArray[1].setFConst(-invDet * m01);
1163 tempConstArray[2].setFConst(-invDet * m10);
1164 tempConstArray[3].setFConst( invDet * m00);
1165 }
1166 break;
1167 case 3:
1168 {
1169 float m00 = unionArray[0].getFConst(); // Matrix is:
1170 float m01 = unionArray[1].getFConst(); // (m00, m01, m02)
1171 float m02 = unionArray[2].getFConst(); // (m10, m11, m12)
1172 float m10 = unionArray[3].getFConst(); // (m20, m21, m22)
1173 float m11 = unionArray[4].getFConst();
1174 float m12 = unionArray[5].getFConst();
1175 float m20 = unionArray[6].getFConst();
1176 float m21 = unionArray[7].getFConst();
1177 float m22 = unionArray[8].getFConst();
1178 tempConstArray[0].setFConst(invDet * determinant2(m11, m12, m21, m22)); // m00 = invDet * (m11 * m22 - m12 * m21)
1179 tempConstArray[1].setFConst(invDet * determinant2(m12, m10, m22, m20)); // m01 = -invDet * (m10 * m22 - m12 * m20)
1180 tempConstArray[2].setFConst(invDet * determinant2(m10, m11, m20, m21)); // m02 = invDet * (m10 * m21 - m11 * m20)
1181 tempConstArray[3].setFConst(invDet * determinant2(m21, m22, m01, m02)); // m10 = -invDet * (m01 * m22 - m02 * m21)
1182 tempConstArray[4].setFConst(invDet * determinant2(m00, m02, m20, m22)); // m11 = invDet * (m00 * m22 - m02 * m20)
1183 tempConstArray[5].setFConst(invDet * determinant2(m20, m21, m00, m01)); // m12 = -invDet * (m00 * m21 - m01 * m20)
1184 tempConstArray[6].setFConst(invDet * determinant2(m01, m02, m11, m12)); // m20 = invDet * (m01 * m12 - m02 * m11)
1185 tempConstArray[7].setFConst(invDet * determinant2(m10, m12, m00, m02)); // m21 = -invDet * (m00 * m12 - m02 * m10)
1186 tempConstArray[8].setFConst(invDet * determinant2(m00, m01, m10, m11)); // m22 = invDet * (m00 * m11 - m01 * m10)
1187 }
1188 break;
1189 case 4:
1190 {
1191 float m00 = unionArray[0].getFConst(); // Matrix is:
1192 float m01 = unionArray[1].getFConst(); // (m00, m01, m02, m03)
1193 float m02 = unionArray[2].getFConst(); // (m10, m11, m12, m13)
1194 float m03 = unionArray[3].getFConst(); // (m20, m21, m22, m23)
1195 float m10 = unionArray[4].getFConst(); // (m30, m31, m32, m33)
1196 float m11 = unionArray[5].getFConst();
1197 float m12 = unionArray[6].getFConst();
1198 float m13 = unionArray[7].getFConst();
1199 float m20 = unionArray[8].getFConst();
1200 float m21 = unionArray[9].getFConst();
1201 float m22 = unionArray[10].getFConst();
1202 float m23 = unionArray[11].getFConst();
1203 float m30 = unionArray[12].getFConst();
1204 float m31 = unionArray[13].getFConst();
1205 float m32 = unionArray[14].getFConst();
1206 float m33 = unionArray[15].getFConst();
1207 tempConstArray[ 0].setFConst( invDet * determinant3(m11, m12, m13, m21, m22, m23, m31, m32, m33)); // m00
1208 tempConstArray[ 1].setFConst(-invDet * determinant3(m10, m12, m13, m20, m22, m23, m30, m32, m33)); // m01
1209 tempConstArray[ 2].setFConst( invDet * determinant3(m10, m11, m13, m20, m21, m23, m30, m31, m33)); // m02
1210 tempConstArray[ 3].setFConst(-invDet * determinant3(m10, m11, m12, m20, m21, m22, m30, m31, m32)); // m03
1211 tempConstArray[ 4].setFConst( invDet * determinant3(m01, m02, m03, m21, m22, m23, m31, m32, m33)); // m10
1212 tempConstArray[ 5].setFConst(-invDet * determinant3(m00, m02, m03, m20, m22, m23, m30, m32, m33)); // m11
1213 tempConstArray[ 6].setFConst( invDet * determinant3(m00, m01, m03, m20, m21, m23, m30, m31, m33)); // m12
1214 tempConstArray[ 7].setFConst(-invDet * determinant3(m00, m01, m02, m20, m21, m22, m30, m31, m32)); // m13
1215 tempConstArray[ 8].setFConst( invDet * determinant3(m01, m02, m03, m11, m12, m13, m31, m32, m33)); // m20
1216 tempConstArray[ 9].setFConst(-invDet * determinant3(m00, m02, m03, m10, m12, m13, m30, m32, m33)); // m21
1217 tempConstArray[10].setFConst( invDet * determinant3(m00, m01, m03, m10, m11, m13, m30, m31, m33)); // m22
1218 tempConstArray[11].setFConst(-invDet * determinant3(m00, m01, m02, m10, m11, m12, m30, m31, m32)); // m23
1219 tempConstArray[12].setFConst( invDet * determinant3(m01, m02, m03, m11, m12, m13, m21, m22, m23)); // m30
1220 tempConstArray[13].setFConst(-invDet * determinant3(m00, m02, m03, m10, m12, m13, m20, m22, m23)); // m31
1221 tempConstArray[14].setFConst( invDet * determinant3(m00, m01, m03, m10, m11, m13, m20, m21, m23)); // m32
1222 tempConstArray[15].setFConst(-invDet * determinant3(m00, m01, m02, m10, m11, m12, m20, m21, m22)); // m33
1223 }
1224 break;
1225 default:
Nicolas Capens3713cd42015-06-22 10:41:54 -04001226 UNREACHABLE(size);
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001227 }
1228 }
1229 return tempConstArray;
1230}
1231
John Bauman66b8ab22014-05-06 15:57:45 -04001232//
1233// The fold functions see if an operation on a constant can be done in place,
1234// without generating run-time code.
1235//
1236// Returns the node to keep using, which may or may not be the node passed in.
1237//
1238
1239TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNode, TInfoSink& infoSink)
1240{
1241 ConstantUnion *unionArray = getUnionArrayPointer();
1242 int objectSize = getType().getObjectSize();
1243
1244 if (constantNode) { // binary operations
1245 TIntermConstantUnion *node = constantNode->getAsConstantUnion();
1246 ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
1247 TType returnType = getType();
1248
1249 // for a case like float f = 1.2 + vec4(2,3,4,5);
1250 if (constantNode->getType().getObjectSize() == 1 && objectSize > 1) {
1251 rightUnionArray = new ConstantUnion[objectSize];
1252 for (int i = 0; i < objectSize; ++i)
1253 rightUnionArray[i] = *node->getUnionArrayPointer();
1254 returnType = getType();
1255 } else if (constantNode->getType().getObjectSize() > 1 && objectSize == 1) {
1256 // for a case like float f = vec4(2,3,4,5) + 1.2;
1257 unionArray = new ConstantUnion[constantNode->getType().getObjectSize()];
1258 for (int i = 0; i < constantNode->getType().getObjectSize(); ++i)
1259 unionArray[i] = *getUnionArrayPointer();
1260 returnType = node->getType();
1261 objectSize = constantNode->getType().getObjectSize();
1262 }
1263
1264 ConstantUnion* tempConstArray = 0;
1265 TIntermConstantUnion *tempNode;
1266
1267 bool boolNodeFlag = false;
1268 switch(op) {
1269 case EOpAdd:
1270 tempConstArray = new ConstantUnion[objectSize];
1271 {// support MSVC++6.0
1272 for (int i = 0; i < objectSize; i++)
1273 tempConstArray[i] = unionArray[i] + rightUnionArray[i];
1274 }
1275 break;
1276 case EOpSub:
1277 tempConstArray = new ConstantUnion[objectSize];
1278 {// support MSVC++6.0
1279 for (int i = 0; i < objectSize; i++)
1280 tempConstArray[i] = unionArray[i] - rightUnionArray[i];
1281 }
1282 break;
1283
1284 case EOpMul:
1285 case EOpVectorTimesScalar:
1286 case EOpMatrixTimesScalar:
1287 tempConstArray = new ConstantUnion[objectSize];
1288 {// support MSVC++6.0
1289 for (int i = 0; i < objectSize; i++)
1290 tempConstArray[i] = unionArray[i] * rightUnionArray[i];
1291 }
1292 break;
1293 case EOpMatrixTimesMatrix:
1294 if (getType().getBasicType() != EbtFloat || node->getBasicType() != EbtFloat) {
1295 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix multiply", getLine());
1296 return 0;
1297 }
1298 {// support MSVC++6.0
Alexis Hetu00106d42015-04-23 11:45:35 -04001299 int leftNumCols = getNominalSize();
1300 int leftNumRows = getSecondarySize();
1301 int rightNumCols = node->getNominalSize();
1302 int rightNumRows = node->getSecondarySize();
1303 if(leftNumCols != rightNumRows) {
1304 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix multiply", getLine());
1305 return 0;
1306 }
1307 int tempNumCols = rightNumCols;
1308 int tempNumRows = leftNumRows;
1309 int tempNumAdds = leftNumCols;
1310 tempConstArray = new ConstantUnion[tempNumCols*tempNumRows];
1311 for (int row = 0; row < tempNumRows; row++) {
1312 for (int column = 0; column < tempNumCols; column++) {
1313 tempConstArray[tempNumRows * column + row].setFConst(0.0f);
1314 for (int i = 0; i < tempNumAdds; i++) {
1315 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 -04001316 }
1317 }
1318 }
Alexis Hetu00106d42015-04-23 11:45:35 -04001319 // update return type for matrix product
1320 returnType.setNominalSize(static_cast<unsigned char>(tempNumCols));
1321 returnType.setSecondarySize(static_cast<unsigned char>(tempNumRows));
John Bauman66b8ab22014-05-06 15:57:45 -04001322 }
1323 break;
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001324
1325 case EOpOuterProduct:
1326 {
1327 int leftSize = getNominalSize();
1328 int rightSize = node->getNominalSize();
1329 tempConstArray = new ConstantUnion[leftSize*rightSize];
1330 for(int row = 0; row < leftSize; row++) {
1331 for(int column = 0; column < rightSize; column++) {
1332 tempConstArray[leftSize * column + row].setFConst(unionArray[row].getFConst() * rightUnionArray[column].getFConst());
1333 }
1334 }
1335 // update return type for outer product
1336 returnType.setNominalSize(static_cast<unsigned char>(rightSize));
1337 returnType.setSecondarySize(static_cast<unsigned char>(leftSize));
1338 }
1339 break;
1340
1341 case EOpTranspose:
1342 {
1343 int rightCol = node->getNominalSize();
1344 int rightRow = node->getSecondarySize();
1345 tempConstArray = new ConstantUnion[rightCol*rightRow];
1346 for(int row = 0; row < rightRow; row++) {
1347 for(int column = 0; column < rightCol; column++) {
1348 tempConstArray[rightRow * column + row].setFConst(rightUnionArray[rightCol * row + column].getFConst());
1349 }
1350 }
1351 // update return type for transpose
1352 returnType.setNominalSize(static_cast<unsigned char>(rightRow));
1353 returnType.setSecondarySize(static_cast<unsigned char>(rightCol));
1354 }
1355 break;
1356
1357 case EOpDeterminant:
1358 {
1359 ASSERT(node->getNominalSize() == node->getSecondarySize());
1360
1361 tempConstArray = new ConstantUnion[1];
1362 tempConstArray[0].setFConst(ComputeDeterminant(node->getNominalSize(), rightUnionArray));
1363 // update return type for determinant
1364 returnType.setNominalSize(1);
1365 returnType.setSecondarySize(1);
1366 }
1367 break;
1368
1369 case EOpInverse:
1370 {
1371 ASSERT(node->getNominalSize() == node->getSecondarySize());
1372
1373 tempConstArray = CreateInverse(node, rightUnionArray);
1374 if(!tempConstArray)
1375 {
1376 // Singular matrix, just copy
1377 tempConstArray = new ConstantUnion[objectSize];
1378 for(int i = 0; i < objectSize; i++)
1379 tempConstArray[i] = rightUnionArray[i];
1380 }
1381 }
1382 break;
1383
John Bauman66b8ab22014-05-06 15:57:45 -04001384 case EOpDiv:
Alexis Hetud061e422015-05-13 16:37:50 -04001385 case EOpIMod:
John Bauman66b8ab22014-05-06 15:57:45 -04001386 tempConstArray = new ConstantUnion[objectSize];
1387 {// support MSVC++6.0
1388 for (int i = 0; i < objectSize; i++) {
1389 switch (getType().getBasicType()) {
Alexis Hetud061e422015-05-13 16:37:50 -04001390 case EbtFloat:
1391 if (rightUnionArray[i] == 0.0f) {
1392 infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
1393 tempConstArray[i].setFConst(FLT_MAX);
1394 } else {
1395 ASSERT(op == EOpDiv);
1396 tempConstArray[i].setFConst(unionArray[i].getFConst() / rightUnionArray[i].getFConst());
1397 }
1398 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001399
Alexis Hetud061e422015-05-13 16:37:50 -04001400 case EbtInt:
1401 if (rightUnionArray[i] == 0) {
1402 infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
1403 tempConstArray[i].setIConst(INT_MAX);
1404 } else {
1405 if(op == EOpDiv) {
1406 tempConstArray[i].setIConst(unionArray[i].getIConst() / rightUnionArray[i].getIConst());
1407 } else {
1408 ASSERT(op == EOpIMod);
1409 tempConstArray[i].setIConst(unionArray[i].getIConst() % rightUnionArray[i].getIConst());
1410 }
1411 }
1412 break;
1413 case EbtUInt:
1414 if (rightUnionArray[i] == 0) {
1415 infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
1416 tempConstArray[i].setUConst(UINT_MAX);
1417 } else {
1418 if(op == EOpDiv) {
1419 tempConstArray[i].setUConst(unionArray[i].getUConst() / rightUnionArray[i].getUConst());
1420 } else {
1421 ASSERT(op == EOpIMod);
1422 tempConstArray[i].setUConst(unionArray[i].getUConst() % rightUnionArray[i].getUConst());
1423 }
1424 }
1425 break;
1426 default:
1427 infoSink.info.message(EPrefixInternalError, "Constant folding cannot be done for \"/\"", getLine());
1428 return 0;
John Bauman66b8ab22014-05-06 15:57:45 -04001429 }
1430 }
1431 }
1432 break;
1433
1434 case EOpMatrixTimesVector:
1435 if (node->getBasicType() != EbtFloat) {
1436 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix times vector", getLine());
1437 return 0;
1438 }
1439 tempConstArray = new ConstantUnion[getNominalSize()];
1440
1441 {// support MSVC++6.0
1442 for (int size = getNominalSize(), i = 0; i < size; i++) {
1443 tempConstArray[i].setFConst(0.0f);
1444 for (int j = 0; j < size; j++) {
1445 tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j*size + i].getFConst()) * rightUnionArray[j].getFConst()));
1446 }
1447 }
1448 }
1449
1450 tempNode = new TIntermConstantUnion(tempConstArray, node->getType());
1451 tempNode->setLine(getLine());
1452
1453 return tempNode;
1454
1455 case EOpVectorTimesMatrix:
1456 if (getType().getBasicType() != EbtFloat) {
1457 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for vector times matrix", getLine());
1458 return 0;
1459 }
1460
1461 tempConstArray = new ConstantUnion[getNominalSize()];
1462 {// support MSVC++6.0
1463 for (int size = getNominalSize(), i = 0; i < size; i++) {
1464 tempConstArray[i].setFConst(0.0f);
1465 for (int j = 0; j < size; j++) {
1466 tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j].getFConst()) * rightUnionArray[i*size + j].getFConst()));
1467 }
1468 }
1469 }
1470 break;
1471
1472 case EOpLogicalAnd: // this code is written for possible future use, will not get executed currently
1473 tempConstArray = new ConstantUnion[objectSize];
1474 {// support MSVC++6.0
1475 for (int i = 0; i < objectSize; i++)
1476 tempConstArray[i] = unionArray[i] && rightUnionArray[i];
1477 }
1478 break;
1479
1480 case EOpLogicalOr: // this code is written for possible future use, will not get executed currently
1481 tempConstArray = new ConstantUnion[objectSize];
1482 {// support MSVC++6.0
1483 for (int i = 0; i < objectSize; i++)
1484 tempConstArray[i] = unionArray[i] || rightUnionArray[i];
1485 }
1486 break;
1487
1488 case EOpLogicalXor:
1489 tempConstArray = new ConstantUnion[objectSize];
1490 {// support MSVC++6.0
1491 for (int i = 0; i < objectSize; i++)
1492 switch (getType().getBasicType()) {
Alexis Hetud061e422015-05-13 16:37:50 -04001493 case EbtBool: tempConstArray[i].setBConst((unionArray[i] == rightUnionArray[i]) ? false : true); break;
1494 default: assert(false && "Default missing");
John Bauman66b8ab22014-05-06 15:57:45 -04001495 }
1496 }
1497 break;
1498
Alexis Hetud061e422015-05-13 16:37:50 -04001499 case EOpBitwiseAnd:
1500 tempConstArray = new ConstantUnion[objectSize];
1501 for(int i = 0; i < objectSize; i++)
1502 tempConstArray[i] = unionArray[i] & rightUnionArray[i];
1503 break;
1504 case EOpBitwiseXor:
1505 tempConstArray = new ConstantUnion[objectSize];
1506 for(int i = 0; i < objectSize; i++)
1507 tempConstArray[i] = unionArray[i] ^ rightUnionArray[i];
1508 break;
1509 case EOpBitwiseOr:
1510 tempConstArray = new ConstantUnion[objectSize];
1511 for(int i = 0; i < objectSize; i++)
1512 tempConstArray[i] = unionArray[i] | rightUnionArray[i];
1513 break;
1514 case EOpBitShiftLeft:
1515 tempConstArray = new ConstantUnion[objectSize];
1516 for(int i = 0; i < objectSize; i++)
1517 tempConstArray[i] = unionArray[i] << rightUnionArray[i];
1518 break;
1519 case EOpBitShiftRight:
1520 tempConstArray = new ConstantUnion[objectSize];
1521 for(int i = 0; i < objectSize; i++)
1522 tempConstArray[i] = unionArray[i] >> rightUnionArray[i];
1523 break;
1524
John Bauman66b8ab22014-05-06 15:57:45 -04001525 case EOpLessThan:
1526 assert(objectSize == 1);
1527 tempConstArray = new ConstantUnion[1];
1528 tempConstArray->setBConst(*unionArray < *rightUnionArray);
Nicolas Capens31ad2aa2015-02-26 13:14:27 -05001529 returnType = TType(EbtBool, EbpUndefined, EvqConstExpr);
John Bauman66b8ab22014-05-06 15:57:45 -04001530 break;
1531 case EOpGreaterThan:
1532 assert(objectSize == 1);
1533 tempConstArray = new ConstantUnion[1];
1534 tempConstArray->setBConst(*unionArray > *rightUnionArray);
Nicolas Capens31ad2aa2015-02-26 13:14:27 -05001535 returnType = TType(EbtBool, EbpUndefined, EvqConstExpr);
John Bauman66b8ab22014-05-06 15:57:45 -04001536 break;
1537 case EOpLessThanEqual:
1538 {
1539 assert(objectSize == 1);
1540 ConstantUnion constant;
1541 constant.setBConst(*unionArray > *rightUnionArray);
1542 tempConstArray = new ConstantUnion[1];
1543 tempConstArray->setBConst(!constant.getBConst());
Nicolas Capens31ad2aa2015-02-26 13:14:27 -05001544 returnType = TType(EbtBool, EbpUndefined, EvqConstExpr);
John Bauman66b8ab22014-05-06 15:57:45 -04001545 break;
1546 }
1547 case EOpGreaterThanEqual:
1548 {
1549 assert(objectSize == 1);
1550 ConstantUnion constant;
1551 constant.setBConst(*unionArray < *rightUnionArray);
1552 tempConstArray = new ConstantUnion[1];
1553 tempConstArray->setBConst(!constant.getBConst());
Nicolas Capens31ad2aa2015-02-26 13:14:27 -05001554 returnType = TType(EbtBool, EbpUndefined, EvqConstExpr);
John Bauman66b8ab22014-05-06 15:57:45 -04001555 break;
1556 }
1557
1558 case EOpEqual:
1559 if (getType().getBasicType() == EbtStruct) {
1560 if (!CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray))
1561 boolNodeFlag = true;
1562 } else {
1563 for (int i = 0; i < objectSize; i++) {
1564 if (unionArray[i] != rightUnionArray[i]) {
1565 boolNodeFlag = true;
1566 break; // break out of for loop
1567 }
1568 }
1569 }
1570
1571 tempConstArray = new ConstantUnion[1];
1572 if (!boolNodeFlag) {
1573 tempConstArray->setBConst(true);
1574 }
1575 else {
1576 tempConstArray->setBConst(false);
1577 }
1578
Nicolas Capens31ad2aa2015-02-26 13:14:27 -05001579 tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConstExpr));
John Bauman66b8ab22014-05-06 15:57:45 -04001580 tempNode->setLine(getLine());
1581
1582 return tempNode;
1583
1584 case EOpNotEqual:
1585 if (getType().getBasicType() == EbtStruct) {
1586 if (CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray))
1587 boolNodeFlag = true;
1588 } else {
1589 for (int i = 0; i < objectSize; i++) {
1590 if (unionArray[i] == rightUnionArray[i]) {
1591 boolNodeFlag = true;
1592 break; // break out of for loop
1593 }
1594 }
1595 }
1596
1597 tempConstArray = new ConstantUnion[1];
1598 if (!boolNodeFlag) {
1599 tempConstArray->setBConst(true);
1600 }
1601 else {
1602 tempConstArray->setBConst(false);
1603 }
1604
Nicolas Capens31ad2aa2015-02-26 13:14:27 -05001605 tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConstExpr));
John Bauman66b8ab22014-05-06 15:57:45 -04001606 tempNode->setLine(getLine());
1607
1608 return tempNode;
1609
1610 default:
1611 infoSink.info.message(EPrefixInternalError, "Invalid operator for constant folding", getLine());
1612 return 0;
1613 }
1614 tempNode = new TIntermConstantUnion(tempConstArray, returnType);
1615 tempNode->setLine(getLine());
1616
1617 return tempNode;
1618 } else {
1619 //
1620 // Do unary operations
1621 //
1622 TIntermConstantUnion *newNode = 0;
1623 ConstantUnion* tempConstArray = new ConstantUnion[objectSize];
1624 for (int i = 0; i < objectSize; i++) {
1625 switch(op) {
1626 case EOpNegative:
1627 switch (getType().getBasicType()) {
1628 case EbtFloat: tempConstArray[i].setFConst(-unionArray[i].getFConst()); break;
1629 case EbtInt: tempConstArray[i].setIConst(-unionArray[i].getIConst()); break;
1630 default:
1631 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1632 return 0;
1633 }
1634 break;
1635 case EOpLogicalNot: // this code is written for possible future use, will not get executed currently
1636 switch (getType().getBasicType()) {
1637 case EbtBool: tempConstArray[i].setBConst(!unionArray[i].getBConst()); break;
1638 default:
1639 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1640 return 0;
1641 }
1642 break;
Alexis Hetud061e422015-05-13 16:37:50 -04001643 case EOpBitwiseNot:
1644 switch(getType().getBasicType()) {
1645 case EbtInt: tempConstArray[i].setIConst(~unionArray[i].getIConst()); break;
1646 case EbtUInt: tempConstArray[i].setUConst(~unionArray[i].getUConst()); break;
1647 default:
1648 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1649 return 0;
1650 }
1651 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001652 default:
1653 return 0;
1654 }
1655 }
1656 newNode = new TIntermConstantUnion(tempConstArray, getType());
1657 newNode->setLine(getLine());
1658 return newNode;
1659 }
1660}
1661
1662TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermConstantUnion* node)
1663{
John Bauman66b8ab22014-05-06 15:57:45 -04001664 int size = node->getType().getObjectSize();
1665
1666 ConstantUnion *leftUnionArray = new ConstantUnion[size];
1667
1668 for (int i=0; i < size; i++) {
1669
1670 switch (promoteTo) {
1671 case EbtFloat:
1672 switch (node->getType().getBasicType()) {
1673 case EbtInt:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001674 leftUnionArray[i].setFConst(static_cast<float>(node->getIConst(i)));
John Bauman66b8ab22014-05-06 15:57:45 -04001675 break;
Nicolas Capens3c20f802015-02-17 17:17:20 -05001676 case EbtUInt:
1677 leftUnionArray[i].setFConst(static_cast<float>(node->getUConst(i)));
1678 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001679 case EbtBool:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001680 leftUnionArray[i].setFConst(static_cast<float>(node->getBConst(i)));
John Bauman66b8ab22014-05-06 15:57:45 -04001681 break;
1682 case EbtFloat:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001683 leftUnionArray[i].setFConst(static_cast<float>(node->getFConst(i)));
John Bauman66b8ab22014-05-06 15:57:45 -04001684 break;
1685 default:
1686 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
1687 return 0;
1688 }
1689 break;
1690 case EbtInt:
1691 switch (node->getType().getBasicType()) {
1692 case EbtInt:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001693 leftUnionArray[i].setIConst(static_cast<int>(node->getIConst(i)));
John Bauman66b8ab22014-05-06 15:57:45 -04001694 break;
Nicolas Capens3c20f802015-02-17 17:17:20 -05001695 case EbtUInt:
1696 leftUnionArray[i].setIConst(static_cast<int>(node->getUConst(i)));
1697 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001698 case EbtBool:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001699 leftUnionArray[i].setIConst(static_cast<int>(node->getBConst(i)));
John Bauman66b8ab22014-05-06 15:57:45 -04001700 break;
1701 case EbtFloat:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001702 leftUnionArray[i].setIConst(static_cast<int>(node->getFConst(i)));
John Bauman66b8ab22014-05-06 15:57:45 -04001703 break;
1704 default:
1705 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
1706 return 0;
1707 }
1708 break;
Nicolas Capens3c20f802015-02-17 17:17:20 -05001709 case EbtUInt:
1710 switch (node->getType().getBasicType()) {
1711 case EbtInt:
1712 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getIConst(i)));
1713 break;
1714 case EbtUInt:
1715 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getUConst(i)));
1716 break;
1717 case EbtBool:
1718 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getBConst(i)));
1719 break;
1720 case EbtFloat:
1721 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getFConst(i)));
1722 break;
1723 default:
1724 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
1725 return 0;
1726 }
1727 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001728 case EbtBool:
1729 switch (node->getType().getBasicType()) {
1730 case EbtInt:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001731 leftUnionArray[i].setBConst(node->getIConst(i) != 0);
John Bauman66b8ab22014-05-06 15:57:45 -04001732 break;
Nicolas Capens3c20f802015-02-17 17:17:20 -05001733 case EbtUInt:
1734 leftUnionArray[i].setBConst(node->getUConst(i) != 0);
1735 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001736 case EbtBool:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001737 leftUnionArray[i].setBConst(node->getBConst(i));
John Bauman66b8ab22014-05-06 15:57:45 -04001738 break;
1739 case EbtFloat:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001740 leftUnionArray[i].setBConst(node->getFConst(i) != 0.0f);
John Bauman66b8ab22014-05-06 15:57:45 -04001741 break;
1742 default:
1743 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
1744 return 0;
1745 }
1746
1747 break;
1748 default:
1749 infoSink.info.message(EPrefixInternalError, "Incorrect data type found", node->getLine());
1750 return 0;
1751 }
1752
1753 }
1754
1755 const TType& t = node->getType();
1756
Alexis Hetub14178b2015-04-13 13:23:20 -04001757 return addConstantUnion(leftUnionArray, TType(promoteTo, t.getPrecision(), t.getQualifier(), t.getNominalSize(), t.getSecondarySize(), t.isArray()), node->getLine());
John Bauman66b8ab22014-05-06 15:57:45 -04001758}
1759