blob: 7f056fb0e184f54a1e357f29889e0a336efea864 [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
24const char* getOperatorString(TOperator op) {
25 switch (op) {
26 case EOpInitialize: return "=";
27 case EOpAssign: return "=";
28 case EOpAddAssign: return "+=";
29 case EOpSubAssign: return "-=";
30 case EOpDivAssign: return "/=";
Alexis Hetu17809052015-05-13 11:28:22 -040031 case EOpIModAssign: return "%=";
32 case EOpBitShiftLeftAssign: return "<<=";
33 case EOpBitShiftRightAssign: return ">>=";
34 case EOpBitwiseAndAssign: return "&=";
35 case EOpBitwiseXorAssign: return "^=";
36 case EOpBitwiseOrAssign: return "|=";
John Bauman66b8ab22014-05-06 15:57:45 -040037
38 // Fall-through.
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -040039 case EOpMulAssign:
John Bauman66b8ab22014-05-06 15:57:45 -040040 case EOpVectorTimesMatrixAssign:
41 case EOpVectorTimesScalarAssign:
42 case EOpMatrixTimesScalarAssign:
43 case EOpMatrixTimesMatrixAssign: return "*=";
44
45 // Fall-through.
46 case EOpIndexDirect:
47 case EOpIndexIndirect: return "[]";
48
49 case EOpIndexDirectStruct: return ".";
50 case EOpVectorSwizzle: return ".";
51 case EOpAdd: return "+";
52 case EOpSub: return "-";
53 case EOpMul: return "*";
54 case EOpDiv: return "/";
55 case EOpMod: UNIMPLEMENTED(); break;
56 case EOpEqual: return "==";
57 case EOpNotEqual: return "!=";
58 case EOpLessThan: return "<";
59 case EOpGreaterThan: return ">";
60 case EOpLessThanEqual: return "<=";
61 case EOpGreaterThanEqual: return ">=";
62
63 // Fall-through.
64 case EOpVectorTimesScalar:
65 case EOpVectorTimesMatrix:
66 case EOpMatrixTimesVector:
67 case EOpMatrixTimesScalar:
68 case EOpMatrixTimesMatrix: return "*";
69
70 case EOpLogicalOr: return "||";
71 case EOpLogicalXor: return "^^";
72 case EOpLogicalAnd: return "&&";
Alexis Hetu17809052015-05-13 11:28:22 -040073 case EOpIMod: return "%";
74 case EOpBitShiftLeft: return "<<";
75 case EOpBitShiftRight: return ">>";
76 case EOpBitwiseAnd: return "&";
77 case EOpBitwiseXor: return "^";
78 case EOpBitwiseOr: return "|";
John Bauman66b8ab22014-05-06 15:57:45 -040079 case EOpNegative: return "-";
80 case EOpVectorLogicalNot: return "not";
81 case EOpLogicalNot: return "!";
Alexis Hetu17809052015-05-13 11:28:22 -040082 case EOpBitwiseNot: return "~";
John Bauman66b8ab22014-05-06 15:57:45 -040083 case EOpPostIncrement: return "++";
84 case EOpPostDecrement: return "--";
85 case EOpPreIncrement: return "++";
86 case EOpPreDecrement: return "--";
87
John Bauman66b8ab22014-05-06 15:57:45 -040088 case EOpRadians: return "radians";
89 case EOpDegrees: return "degrees";
90 case EOpSin: return "sin";
91 case EOpCos: return "cos";
92 case EOpTan: return "tan";
93 case EOpAsin: return "asin";
94 case EOpAcos: return "acos";
95 case EOpAtan: return "atan";
Alexis Hetuaf1970c2015-04-17 14:26:07 -040096 case EOpSinh: return "sinh";
97 case EOpCosh: return "cosh";
98 case EOpTanh: return "tanh";
99 case EOpAsinh: return "asinh";
100 case EOpAcosh: return "acosh";
101 case EOpAtanh: return "atanh";
John Bauman66b8ab22014-05-06 15:57:45 -0400102 case EOpExp: return "exp";
103 case EOpLog: return "log";
104 case EOpExp2: return "exp2";
105 case EOpLog2: return "log2";
106 case EOpSqrt: return "sqrt";
107 case EOpInverseSqrt: return "inversesqrt";
108 case EOpAbs: return "abs";
109 case EOpSign: return "sign";
110 case EOpFloor: return "floor";
Alexis Hetuaf1970c2015-04-17 14:26:07 -0400111 case EOpTrunc: return "trunc";
112 case EOpRound: return "round";
113 case EOpRoundEven: return "roundEven";
John Bauman66b8ab22014-05-06 15:57:45 -0400114 case EOpCeil: return "ceil";
115 case EOpFract: return "fract";
116 case EOpLength: return "length";
117 case EOpNormalize: return "normalize";
118 case EOpDFdx: return "dFdx";
119 case EOpDFdy: return "dFdy";
120 case EOpFwidth: return "fwidth";
121 case EOpAny: return "any";
122 case EOpAll: return "all";
Alexis Hetuaf1970c2015-04-17 14:26:07 -0400123 case EOpIsNan: return "isnan";
124 case EOpIsInf: return "isinf";
John Bauman66b8ab22014-05-06 15:57:45 -0400125
126 default: break;
127 }
128 return "";
129}
130
131////////////////////////////////////////////////////////////////////////////
132//
133// First set of functions are to help build the intermediate representation.
134// These functions are not member functions of the nodes.
135// They are called from parser productions.
136//
137/////////////////////////////////////////////////////////////////////////////
138
139//
140// Add a terminal node for an identifier in an expression.
141//
142// Returns the added node.
143//
144TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, TSourceLoc line)
145{
146 TIntermSymbol* node = new TIntermSymbol(id, name, type);
147 node->setLine(line);
148
149 return node;
150}
151
152//
153// Connect two nodes with a new parent that does a binary operation on the nodes.
154//
155// Returns the added node.
156//
John Baumand4ae8632014-05-06 16:18:33 -0400157TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc line)
John Bauman66b8ab22014-05-06 15:57:45 -0400158{
159 switch (op) {
160 case EOpEqual:
161 case EOpNotEqual:
162 if (left->isArray())
163 return 0;
164 break;
165 case EOpLessThan:
166 case EOpGreaterThan:
167 case EOpLessThanEqual:
168 case EOpGreaterThanEqual:
169 if (left->isMatrix() || left->isArray() || left->isVector() || left->getBasicType() == EbtStruct) {
170 return 0;
171 }
172 break;
173 case EOpLogicalOr:
174 case EOpLogicalXor:
175 case EOpLogicalAnd:
176 if (left->getBasicType() != EbtBool || left->isMatrix() || left->isArray() || left->isVector()) {
177 return 0;
178 }
179 break;
180 case EOpAdd:
181 case EOpSub:
182 case EOpDiv:
183 case EOpMul:
184 if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool)
185 return 0;
186 default: break;
187 }
188
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400189 if (left->getBasicType() != right->getBasicType())
190 {
191 return 0;
John Bauman66b8ab22014-05-06 15:57:45 -0400192 }
193
194 //
195 // Need a new node holding things together then. Make
196 // one and promote it to the right type.
197 //
198 TIntermBinary* node = new TIntermBinary(op);
199 if (line == 0)
200 line = right->getLine();
201 node->setLine(line);
202
203 node->setLeft(left);
204 node->setRight(right);
205 if (!node->promote(infoSink))
206 return 0;
207
208 //
209 // See if we can fold constants.
210 //
John Bauman66b8ab22014-05-06 15:57:45 -0400211 TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion();
212 TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion();
213 if (leftTempConstant && rightTempConstant) {
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400214 TIntermTyped *typedReturnNode = leftTempConstant->fold(node->getOp(), rightTempConstant, infoSink);
John Bauman66b8ab22014-05-06 15:57:45 -0400215
216 if (typedReturnNode)
217 return typedReturnNode;
218 }
219
220 return node;
221}
222
223//
224// Connect two nodes through an assignment.
225//
226// Returns the added node.
227//
228TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc line)
229{
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400230 if (left->getType().getStruct() || right->getType().getStruct())
231 {
232 if (left->getType() != right->getType())
233 {
234 return 0;
235 }
236 }
237
John Bauman66b8ab22014-05-06 15:57:45 -0400238 TIntermBinary* node = new TIntermBinary(op);
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400239 if(line == 0)
John Bauman66b8ab22014-05-06 15:57:45 -0400240 line = left->getLine();
241 node->setLine(line);
242
John Bauman66b8ab22014-05-06 15:57:45 -0400243 node->setLeft(left);
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400244 node->setRight(right);
John Bauman66b8ab22014-05-06 15:57:45 -0400245 if (! node->promote(infoSink))
246 return 0;
247
248 return node;
249}
250
251//
252// Connect two nodes through an index operator, where the left node is the base
253// of an array or struct, and the right node is a direct or indirect offset.
254//
255// Returns the added node.
256// The caller should set the type of the returned node.
257//
258TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc line)
259{
260 TIntermBinary* node = new TIntermBinary(op);
261 if (line == 0)
262 line = index->getLine();
263 node->setLine(line);
264 node->setLeft(base);
265 node->setRight(index);
266
267 // caller should set the type
268
269 return node;
270}
271
272//
273// Add one node as the parent of another that it operates on.
274//
275// Returns the added node.
276//
John Baumand4ae8632014-05-06 16:18:33 -0400277TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode, TSourceLoc line)
John Bauman66b8ab22014-05-06 15:57:45 -0400278{
279 TIntermUnary* node;
280 TIntermTyped* child = childNode->getAsTyped();
281
282 if (child == 0) {
283 infoSink.info.message(EPrefixInternalError, "Bad type in AddUnaryMath", line);
284 return 0;
285 }
286
287 switch (op) {
288 case EOpLogicalNot:
289 if (child->getType().getBasicType() != EbtBool || child->getType().isMatrix() || child->getType().isArray() || child->getType().isVector()) {
290 return 0;
291 }
292 break;
293
294 case EOpPostIncrement:
295 case EOpPreIncrement:
296 case EOpPostDecrement:
297 case EOpPreDecrement:
298 case EOpNegative:
299 if (child->getType().getBasicType() == EbtStruct || child->getType().isArray())
300 return 0;
301 default: break;
302 }
303
John Bauman66b8ab22014-05-06 15:57:45 -0400304 TIntermConstantUnion *childTempConstant = 0;
305 if (child->getAsConstantUnion())
306 childTempConstant = child->getAsConstantUnion();
307
308 //
309 // Make a new node for the operator.
310 //
311 node = new TIntermUnary(op);
312 if (line == 0)
313 line = child->getLine();
314 node->setLine(line);
315 node->setOperand(child);
316
317 if (! node->promote(infoSink))
318 return 0;
319
320 if (childTempConstant) {
321 TIntermTyped* newChild = childTempConstant->fold(op, 0, infoSink);
322
323 if (newChild)
324 return newChild;
325 }
326
327 return node;
328}
329
330//
331// This is the safe way to change the operator on an aggregate, as it
332// does lots of error checking and fixing. Especially for establishing
333// a function call's operation on it's set of parameters. Sequences
334// of instructions are also aggregates, but they just direnctly set
335// their operator to EOpSequence.
336//
337// Returns an aggregate node, which could be the one passed in if
338// it was already an aggregate but no operator was set.
339//
340TIntermAggregate* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator op, TSourceLoc line)
341{
342 TIntermAggregate* aggNode;
343
344 //
345 // Make sure we have an aggregate. If not turn it into one.
346 //
347 if (node) {
348 aggNode = node->getAsAggregate();
349 if (aggNode == 0 || aggNode->getOp() != EOpNull) {
350 //
351 // Make an aggregate containing this node.
352 //
353 aggNode = new TIntermAggregate();
354 aggNode->getSequence().push_back(node);
355 if (line == 0)
356 line = node->getLine();
357 }
358 } else
359 aggNode = new TIntermAggregate();
360
361 //
362 // Set the operator.
363 //
364 aggNode->setOp(op);
365 if (line != 0)
366 aggNode->setLine(line);
367
368 return aggNode;
369}
370
371//
John Bauman66b8ab22014-05-06 15:57:45 -0400372// Safe way to combine two nodes into an aggregate. Works with null pointers,
373// a node that's not a aggregate yet, etc.
374//
375// Returns the resulting aggregate, unless 0 was passed in for
376// both existing nodes.
377//
378TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* right, TSourceLoc line)
379{
380 if (left == 0 && right == 0)
381 return 0;
382
383 TIntermAggregate* aggNode = 0;
384 if (left)
385 aggNode = left->getAsAggregate();
386 if (!aggNode || aggNode->getOp() != EOpNull) {
387 aggNode = new TIntermAggregate;
388 if (left)
389 aggNode->getSequence().push_back(left);
390 }
391
392 if (right)
393 aggNode->getSequence().push_back(right);
394
395 if (line != 0)
396 aggNode->setLine(line);
397
398 return aggNode;
399}
400
401//
402// Turn an existing node into an aggregate.
403//
404// Returns an aggregate, unless 0 was passed in for the existing node.
405//
406TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, TSourceLoc line)
407{
408 if (node == 0)
409 return 0;
410
411 TIntermAggregate* aggNode = new TIntermAggregate;
412 aggNode->getSequence().push_back(node);
413
414 if (line != 0)
415 aggNode->setLine(line);
416 else
417 aggNode->setLine(node->getLine());
418
419 return aggNode;
420}
421
422//
423// For "if" test nodes. There are three children; a condition,
424// a true path, and a false path. The two paths are in the
425// nodePair.
426//
427// Returns the selection node created.
428//
429TIntermNode* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nodePair, TSourceLoc line)
430{
431 //
432 // For compile time constant selections, prune the code and
433 // test now.
434 //
435
436 if (cond->getAsTyped() && cond->getAsTyped()->getAsConstantUnion()) {
Nicolas Capens198529d2015-02-10 13:54:19 -0500437 if (cond->getAsConstantUnion()->getBConst(0) == true)
John Bauman66b8ab22014-05-06 15:57:45 -0400438 return nodePair.node1 ? setAggregateOperator(nodePair.node1, EOpSequence, nodePair.node1->getLine()) : NULL;
439 else
440 return nodePair.node2 ? setAggregateOperator(nodePair.node2, EOpSequence, nodePair.node2->getLine()) : NULL;
441 }
442
443 TIntermSelection* node = new TIntermSelection(cond, nodePair.node1, nodePair.node2);
444 node->setLine(line);
445
446 return node;
447}
448
449
450TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, TSourceLoc line)
451{
Nicolas Capens31ad2aa2015-02-26 13:14:27 -0500452 if (left->getType().getQualifier() == EvqConstExpr && right->getType().getQualifier() == EvqConstExpr) {
John Bauman66b8ab22014-05-06 15:57:45 -0400453 return right;
454 } else {
455 TIntermTyped *commaAggregate = growAggregate(left, right, line);
456 commaAggregate->getAsAggregate()->setOp(EOpComma);
457 commaAggregate->setType(right->getType());
458 commaAggregate->getTypePointer()->setQualifier(EvqTemporary);
459 return commaAggregate;
460 }
461}
462
463//
464// For "?:" test nodes. There are three children; a condition,
465// a true path, and a false path. The two paths are specified
466// as separate parameters.
467//
468// Returns the selection node created, or 0 if one could not be.
469//
470TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, TSourceLoc line)
471{
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400472 if (trueBlock->getType() != falseBlock->getType())
473 {
474 return 0;
John Bauman66b8ab22014-05-06 15:57:45 -0400475 }
476
477 //
478 // See if all the operands are constant, then fold it otherwise not.
479 //
480
481 if (cond->getAsConstantUnion() && trueBlock->getAsConstantUnion() && falseBlock->getAsConstantUnion()) {
Nicolas Capens198529d2015-02-10 13:54:19 -0500482 if (cond->getAsConstantUnion()->getBConst(0))
John Bauman66b8ab22014-05-06 15:57:45 -0400483 return trueBlock;
484 else
485 return falseBlock;
486 }
487
488 //
489 // Make a selection node.
490 //
491 TIntermSelection* node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType());
492 node->getTypePointer()->setQualifier(EvqTemporary);
493 node->setLine(line);
494
495 return node;
496}
497
498//
499// Constant terminal nodes. Has a union that contains bool, float or int constants
500//
501// Returns the constant union node created.
502//
503
504TIntermConstantUnion* TIntermediate::addConstantUnion(ConstantUnion* unionArrayPointer, const TType& t, TSourceLoc line)
505{
506 TIntermConstantUnion* node = new TIntermConstantUnion(unionArrayPointer, t);
507 node->setLine(line);
508
509 return node;
510}
511
512TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, TSourceLoc line)
513{
514
515 TIntermAggregate* node = new TIntermAggregate(EOpSequence);
516
517 node->setLine(line);
518 TIntermConstantUnion* constIntNode;
519 TIntermSequence &sequenceVector = node->getSequence();
520 ConstantUnion* unionArray;
521
522 for (int i = 0; i < fields.num; i++) {
523 unionArray = new ConstantUnion[1];
524 unionArray->setIConst(fields.offsets[i]);
Nicolas Capens31ad2aa2015-02-26 13:14:27 -0500525 constIntNode = addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConstExpr), line);
John Bauman66b8ab22014-05-06 15:57:45 -0400526 sequenceVector.push_back(constIntNode);
527 }
528
529 return node;
530}
531
532//
533// Create loop nodes.
534//
535TIntermNode* TIntermediate::addLoop(TLoopType type, TIntermNode* init, TIntermTyped* cond, TIntermTyped* expr, TIntermNode* body, TSourceLoc line)
536{
537 TIntermNode* node = new TIntermLoop(type, init, cond, expr, body);
538 node->setLine(line);
539
540 return node;
541}
542
543//
544// Add branches.
545//
546TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TSourceLoc line)
547{
548 return addBranch(branchOp, 0, line);
549}
550
551TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expression, TSourceLoc line)
552{
553 TIntermBranch* node = new TIntermBranch(branchOp, expression);
554 node->setLine(line);
555
556 return node;
557}
558
559//
560// This is to be executed once the final root is put on top by the parsing
561// process.
562//
563bool TIntermediate::postProcess(TIntermNode* root)
564{
565 if (root == 0)
566 return true;
567
568 //
569 // First, finish off the top level sequence, if any
570 //
571 TIntermAggregate* aggRoot = root->getAsAggregate();
572 if (aggRoot && aggRoot->getOp() == EOpNull)
573 aggRoot->setOp(EOpSequence);
574
575 return true;
576}
577
John Bauman66b8ab22014-05-06 15:57:45 -0400578////////////////////////////////////////////////////////////////
579//
580// Member functions of the nodes used for building the tree.
581//
582////////////////////////////////////////////////////////////////
583
584//
585// Say whether or not an operation node changes the value of a variable.
586//
587// Returns true if state is modified.
588//
589bool TIntermOperator::modifiesState() const
590{
591 switch (op) {
592 case EOpPostIncrement:
593 case EOpPostDecrement:
594 case EOpPreIncrement:
595 case EOpPreDecrement:
596 case EOpAssign:
597 case EOpAddAssign:
598 case EOpSubAssign:
599 case EOpMulAssign:
600 case EOpVectorTimesMatrixAssign:
601 case EOpVectorTimesScalarAssign:
602 case EOpMatrixTimesScalarAssign:
603 case EOpMatrixTimesMatrixAssign:
604 case EOpDivAssign:
Alexis Hetu17809052015-05-13 11:28:22 -0400605 case EOpIModAssign:
606 case EOpBitShiftLeftAssign:
607 case EOpBitShiftRightAssign:
608 case EOpBitwiseAndAssign:
609 case EOpBitwiseXorAssign:
610 case EOpBitwiseOrAssign:
John Bauman66b8ab22014-05-06 15:57:45 -0400611 return true;
612 default:
613 return false;
614 }
615}
616
617//
618// returns true if the operator is for one of the constructors
619//
620bool TIntermOperator::isConstructor() const
621{
622 switch (op) {
623 case EOpConstructVec2:
624 case EOpConstructVec3:
625 case EOpConstructVec4:
626 case EOpConstructMat2:
627 case EOpConstructMat3:
628 case EOpConstructMat4:
629 case EOpConstructFloat:
630 case EOpConstructIVec2:
631 case EOpConstructIVec3:
632 case EOpConstructIVec4:
633 case EOpConstructInt:
Nicolas Capense4b1b1d2015-02-17 17:26:01 -0500634 case EOpConstructUVec2:
635 case EOpConstructUVec3:
636 case EOpConstructUVec4:
Nicolas Capens3c20f802015-02-17 17:17:20 -0500637 case EOpConstructUInt:
John Bauman66b8ab22014-05-06 15:57:45 -0400638 case EOpConstructBVec2:
639 case EOpConstructBVec3:
640 case EOpConstructBVec4:
641 case EOpConstructBool:
642 case EOpConstructStruct:
643 return true;
644 default:
645 return false;
646 }
647}
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400648
John Bauman66b8ab22014-05-06 15:57:45 -0400649//
650// Make sure the type of a unary operator is appropriate for its
651// combination of operation and operand type.
652//
653// Returns false in nothing makes sense.
654//
655bool TIntermUnary::promote(TInfoSink&)
656{
657 switch (op) {
658 case EOpLogicalNot:
659 if (operand->getBasicType() != EbtBool)
660 return false;
661 break;
662 case EOpNegative:
663 case EOpPostIncrement:
664 case EOpPostDecrement:
665 case EOpPreIncrement:
666 case EOpPreDecrement:
667 if (operand->getBasicType() == EbtBool)
668 return false;
669 break;
670
671 // operators for built-ins are already type checked against their prototype
672 case EOpAny:
673 case EOpAll:
674 case EOpVectorLogicalNot:
675 return true;
676
677 default:
678 if (operand->getBasicType() != EbtFloat)
679 return false;
680 }
681
682 setType(operand->getType());
683
684 // Unary operations results in temporary variables unless const.
Nicolas Capens31ad2aa2015-02-26 13:14:27 -0500685 if (operand->getQualifier() != EvqConstExpr) {
John Bauman66b8ab22014-05-06 15:57:45 -0400686 getTypePointer()->setQualifier(EvqTemporary);
687 }
688
689 return true;
690}
691
692//
693// Establishes the type of the resultant operation, as well as
694// makes the operator the correct one for the operands.
695//
696// Returns false if operator can't work on operands.
697//
698bool TIntermBinary::promote(TInfoSink& infoSink)
699{
700 // This function only handles scalars, vectors, and matrices.
701 if (left->isArray() || right->isArray()) {
702 infoSink.info.message(EPrefixInternalError, "Invalid operation for arrays", getLine());
703 return false;
704 }
705
706 // GLSL ES 2.0 does not support implicit type casting.
707 // So the basic type should always match.
708 if (left->getBasicType() != right->getBasicType())
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400709 {
John Bauman66b8ab22014-05-06 15:57:45 -0400710 return false;
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400711 }
John Bauman66b8ab22014-05-06 15:57:45 -0400712
713 //
714 // Base assumption: just make the type the same as the left
715 // operand. Then only deviations from this need be coded.
716 //
717 setType(left->getType());
718
719 // The result gets promoted to the highest precision.
720 TPrecision higherPrecision = GetHigherPrecision(left->getPrecision(), right->getPrecision());
721 getTypePointer()->setPrecision(higherPrecision);
722
723 // Binary operations results in temporary variables unless both
724 // operands are const.
Nicolas Capens31ad2aa2015-02-26 13:14:27 -0500725 if (left->getQualifier() != EvqConstExpr || right->getQualifier() != EvqConstExpr) {
John Bauman66b8ab22014-05-06 15:57:45 -0400726 getTypePointer()->setQualifier(EvqTemporary);
727 }
728
729 int size = std::max(left->getNominalSize(), right->getNominalSize());
Alexis Hetub14178b2015-04-13 13:23:20 -0400730 int matrixSize = std::max(left->getSecondarySize(), right->getSecondarySize()); // FIXME: This will have to change for NxM matrices
John Bauman66b8ab22014-05-06 15:57:45 -0400731
732 //
733 // All scalars. Code after this test assumes this case is removed!
734 //
735 if (size == 1) {
736 switch (op) {
737 //
738 // Promote to conditional
739 //
740 case EOpEqual:
741 case EOpNotEqual:
742 case EOpLessThan:
743 case EOpGreaterThan:
744 case EOpLessThanEqual:
745 case EOpGreaterThanEqual:
746 setType(TType(EbtBool, EbpUndefined));
747 break;
748
749 //
750 // And and Or operate on conditionals
751 //
752 case EOpLogicalAnd:
753 case EOpLogicalOr:
754 // Both operands must be of type bool.
755 if (left->getBasicType() != EbtBool || right->getBasicType() != EbtBool)
756 return false;
757 setType(TType(EbtBool, EbpUndefined));
758 break;
759
760 default:
761 break;
762 }
763 return true;
764 }
765
766 // If we reach here, at least one of the operands is vector or matrix.
767 // The other operand could be a scalar, vector, or matrix.
768 // Are the sizes compatible?
769 //
770 if (left->getNominalSize() != right->getNominalSize()) {
771 // If the nominal size of operands do not match:
772 // One of them must be scalar.
773 if (left->getNominalSize() != 1 && right->getNominalSize() != 1)
774 return false;
775 // Operator cannot be of type pure assignment.
776 if (op == EOpAssign || op == EOpInitialize)
777 return false;
778 }
779
Alexis Hetub14178b2015-04-13 13:23:20 -0400780 if (left->getSecondarySize() != right->getSecondarySize()) {
781 // Operator cannot be of type pure assignment.
782 if (op == EOpAssign || op == EOpInitialize)
783 return false;
784 }
785
John Bauman66b8ab22014-05-06 15:57:45 -0400786 //
787 // Can these two operands be combined?
788 //
789 TBasicType basicType = left->getBasicType();
790 switch (op) {
791 case EOpMul:
792 if (!left->isMatrix() && right->isMatrix()) {
793 if (left->isVector())
794 op = EOpVectorTimesMatrix;
795 else {
796 op = EOpMatrixTimesScalar;
Alexis Hetub14178b2015-04-13 13:23:20 -0400797 setType(TType(basicType, higherPrecision, EvqTemporary, size, matrixSize));
John Bauman66b8ab22014-05-06 15:57:45 -0400798 }
799 } else if (left->isMatrix() && !right->isMatrix()) {
800 if (right->isVector()) {
801 op = EOpMatrixTimesVector;
Alexis Hetub14178b2015-04-13 13:23:20 -0400802 setType(TType(basicType, higherPrecision, EvqTemporary, size, 1));
John Bauman66b8ab22014-05-06 15:57:45 -0400803 } else {
804 op = EOpMatrixTimesScalar;
805 }
806 } else if (left->isMatrix() && right->isMatrix()) {
807 op = EOpMatrixTimesMatrix;
808 } else if (!left->isMatrix() && !right->isMatrix()) {
809 if (left->isVector() && right->isVector()) {
810 // leave as component product
811 } else if (left->isVector() || right->isVector()) {
812 op = EOpVectorTimesScalar;
Alexis Hetub14178b2015-04-13 13:23:20 -0400813 setType(TType(basicType, higherPrecision, EvqTemporary, size, 1));
John Bauman66b8ab22014-05-06 15:57:45 -0400814 }
815 } else {
816 infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
817 return false;
818 }
819 break;
820 case EOpMulAssign:
821 if (!left->isMatrix() && right->isMatrix()) {
822 if (left->isVector())
823 op = EOpVectorTimesMatrixAssign;
824 else {
825 return false;
826 }
827 } else if (left->isMatrix() && !right->isMatrix()) {
828 if (right->isVector()) {
829 return false;
830 } else {
831 op = EOpMatrixTimesScalarAssign;
832 }
833 } else if (left->isMatrix() && right->isMatrix()) {
834 op = EOpMatrixTimesMatrixAssign;
835 } else if (!left->isMatrix() && !right->isMatrix()) {
836 if (left->isVector() && right->isVector()) {
837 // leave as component product
838 } else if (left->isVector() || right->isVector()) {
839 if (! left->isVector())
840 return false;
841 op = EOpVectorTimesScalarAssign;
Alexis Hetub14178b2015-04-13 13:23:20 -0400842 setType(TType(basicType, higherPrecision, EvqTemporary, size, 1));
John Bauman66b8ab22014-05-06 15:57:45 -0400843 }
844 } else {
845 infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
846 return false;
847 }
848 break;
849
850 case EOpAssign:
851 case EOpInitialize:
852 case EOpAdd:
853 case EOpSub:
854 case EOpDiv:
855 case EOpAddAssign:
856 case EOpSubAssign:
857 case EOpDivAssign:
Alexis Hetu17809052015-05-13 11:28:22 -0400858 case EOpIModAssign:
859 case EOpBitShiftLeftAssign:
860 case EOpBitShiftRightAssign:
861 case EOpBitwiseAndAssign:
862 case EOpBitwiseXorAssign:
863 case EOpBitwiseOrAssign:
John Bauman66b8ab22014-05-06 15:57:45 -0400864 if ((left->isMatrix() && right->isVector()) ||
865 (left->isVector() && right->isMatrix()))
866 return false;
Alexis Hetub14178b2015-04-13 13:23:20 -0400867 setType(TType(basicType, higherPrecision, EvqTemporary, size, matrixSize));
John Bauman66b8ab22014-05-06 15:57:45 -0400868 break;
869
870 case EOpEqual:
871 case EOpNotEqual:
872 case EOpLessThan:
873 case EOpGreaterThan:
874 case EOpLessThanEqual:
875 case EOpGreaterThanEqual:
876 if ((left->isMatrix() && right->isVector()) ||
877 (left->isVector() && right->isMatrix()))
878 return false;
879 setType(TType(EbtBool, EbpUndefined));
880 break;
881
882 default:
883 return false;
884 }
885
886 return true;
887}
888
889bool CompareStruct(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
890{
891 const TTypeList* fields = leftNodeType.getStruct();
892
893 size_t structSize = fields->size();
894 int index = 0;
895
896 for (size_t j = 0; j < structSize; j++) {
897 int size = (*fields)[j].type->getObjectSize();
898 for (int i = 0; i < size; i++) {
899 if ((*fields)[j].type->getBasicType() == EbtStruct) {
900 if (!CompareStructure(*(*fields)[j].type, &rightUnionArray[index], &leftUnionArray[index]))
901 return false;
902 } else {
903 if (leftUnionArray[index] != rightUnionArray[index])
904 return false;
905 index++;
906 }
907
908 }
909 }
910 return true;
911}
912
913bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
914{
915 if (leftNodeType.isArray()) {
916 TType typeWithoutArrayness = leftNodeType;
917 typeWithoutArrayness.clearArrayness();
918
919 int arraySize = leftNodeType.getArraySize();
920
921 for (int i = 0; i < arraySize; ++i) {
922 int offset = typeWithoutArrayness.getObjectSize() * i;
923 if (!CompareStruct(typeWithoutArrayness, &rightUnionArray[offset], &leftUnionArray[offset]))
924 return false;
925 }
926 } else
927 return CompareStruct(leftNodeType, rightUnionArray, leftUnionArray);
928
929 return true;
930}
931
932//
933// The fold functions see if an operation on a constant can be done in place,
934// without generating run-time code.
935//
936// Returns the node to keep using, which may or may not be the node passed in.
937//
938
939TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNode, TInfoSink& infoSink)
940{
941 ConstantUnion *unionArray = getUnionArrayPointer();
942 int objectSize = getType().getObjectSize();
943
944 if (constantNode) { // binary operations
945 TIntermConstantUnion *node = constantNode->getAsConstantUnion();
946 ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
947 TType returnType = getType();
948
949 // for a case like float f = 1.2 + vec4(2,3,4,5);
950 if (constantNode->getType().getObjectSize() == 1 && objectSize > 1) {
951 rightUnionArray = new ConstantUnion[objectSize];
952 for (int i = 0; i < objectSize; ++i)
953 rightUnionArray[i] = *node->getUnionArrayPointer();
954 returnType = getType();
955 } else if (constantNode->getType().getObjectSize() > 1 && objectSize == 1) {
956 // for a case like float f = vec4(2,3,4,5) + 1.2;
957 unionArray = new ConstantUnion[constantNode->getType().getObjectSize()];
958 for (int i = 0; i < constantNode->getType().getObjectSize(); ++i)
959 unionArray[i] = *getUnionArrayPointer();
960 returnType = node->getType();
961 objectSize = constantNode->getType().getObjectSize();
962 }
963
964 ConstantUnion* tempConstArray = 0;
965 TIntermConstantUnion *tempNode;
966
967 bool boolNodeFlag = false;
968 switch(op) {
969 case EOpAdd:
970 tempConstArray = new ConstantUnion[objectSize];
971 {// support MSVC++6.0
972 for (int i = 0; i < objectSize; i++)
973 tempConstArray[i] = unionArray[i] + rightUnionArray[i];
974 }
975 break;
976 case EOpSub:
977 tempConstArray = new ConstantUnion[objectSize];
978 {// support MSVC++6.0
979 for (int i = 0; i < objectSize; i++)
980 tempConstArray[i] = unionArray[i] - rightUnionArray[i];
981 }
982 break;
983
984 case EOpMul:
985 case EOpVectorTimesScalar:
986 case EOpMatrixTimesScalar:
987 tempConstArray = new ConstantUnion[objectSize];
988 {// support MSVC++6.0
989 for (int i = 0; i < objectSize; i++)
990 tempConstArray[i] = unionArray[i] * rightUnionArray[i];
991 }
992 break;
993 case EOpMatrixTimesMatrix:
994 if (getType().getBasicType() != EbtFloat || node->getBasicType() != EbtFloat) {
995 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix multiply", getLine());
996 return 0;
997 }
998 {// support MSVC++6.0
999 int size = getNominalSize();
1000 tempConstArray = new ConstantUnion[size*size];
1001 for (int row = 0; row < size; row++) {
1002 for (int column = 0; column < size; column++) {
1003 tempConstArray[size * column + row].setFConst(0.0f);
1004 for (int i = 0; i < size; i++) {
1005 tempConstArray[size * column + row].setFConst(tempConstArray[size * column + row].getFConst() + unionArray[i * size + row].getFConst() * (rightUnionArray[column * size + i].getFConst()));
1006 }
1007 }
1008 }
1009 }
1010 break;
1011 case EOpDiv:
1012 tempConstArray = new ConstantUnion[objectSize];
1013 {// support MSVC++6.0
1014 for (int i = 0; i < objectSize; i++) {
1015 switch (getType().getBasicType()) {
1016 case EbtFloat:
1017 if (rightUnionArray[i] == 0.0f) {
1018 infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
1019 tempConstArray[i].setFConst(FLT_MAX);
1020 } else
1021 tempConstArray[i].setFConst(unionArray[i].getFConst() / rightUnionArray[i].getFConst());
1022 break;
1023
1024 case EbtInt:
1025 if (rightUnionArray[i] == 0) {
1026 infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
1027 tempConstArray[i].setIConst(INT_MAX);
1028 } else
1029 tempConstArray[i].setIConst(unionArray[i].getIConst() / rightUnionArray[i].getIConst());
1030 break;
Nicolas Capens3c20f802015-02-17 17:17:20 -05001031 case EbtUInt:
1032 if (rightUnionArray[i] == 0) {
1033 infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
1034 tempConstArray[i].setUConst(UINT_MAX);
1035 } else
1036 tempConstArray[i].setUConst(unionArray[i].getUConst() / rightUnionArray[i].getUConst());
1037 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001038 default:
1039 infoSink.info.message(EPrefixInternalError, "Constant folding cannot be done for \"/\"", getLine());
1040 return 0;
1041 }
1042 }
1043 }
1044 break;
1045
1046 case EOpMatrixTimesVector:
1047 if (node->getBasicType() != EbtFloat) {
1048 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix times vector", getLine());
1049 return 0;
1050 }
1051 tempConstArray = new ConstantUnion[getNominalSize()];
1052
1053 {// support MSVC++6.0
1054 for (int size = getNominalSize(), i = 0; i < size; i++) {
1055 tempConstArray[i].setFConst(0.0f);
1056 for (int j = 0; j < size; j++) {
1057 tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j*size + i].getFConst()) * rightUnionArray[j].getFConst()));
1058 }
1059 }
1060 }
1061
1062 tempNode = new TIntermConstantUnion(tempConstArray, node->getType());
1063 tempNode->setLine(getLine());
1064
1065 return tempNode;
1066
1067 case EOpVectorTimesMatrix:
1068 if (getType().getBasicType() != EbtFloat) {
1069 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for vector times matrix", getLine());
1070 return 0;
1071 }
1072
1073 tempConstArray = new ConstantUnion[getNominalSize()];
1074 {// support MSVC++6.0
1075 for (int size = getNominalSize(), i = 0; i < size; i++) {
1076 tempConstArray[i].setFConst(0.0f);
1077 for (int j = 0; j < size; j++) {
1078 tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j].getFConst()) * rightUnionArray[i*size + j].getFConst()));
1079 }
1080 }
1081 }
1082 break;
1083
1084 case EOpLogicalAnd: // this code is written for possible future use, will not get executed currently
1085 tempConstArray = new ConstantUnion[objectSize];
1086 {// support MSVC++6.0
1087 for (int i = 0; i < objectSize; i++)
1088 tempConstArray[i] = unionArray[i] && rightUnionArray[i];
1089 }
1090 break;
1091
1092 case EOpLogicalOr: // this code is written for possible future use, will not get executed currently
1093 tempConstArray = new ConstantUnion[objectSize];
1094 {// support MSVC++6.0
1095 for (int i = 0; i < objectSize; i++)
1096 tempConstArray[i] = unionArray[i] || rightUnionArray[i];
1097 }
1098 break;
1099
1100 case EOpLogicalXor:
1101 tempConstArray = new ConstantUnion[objectSize];
1102 {// support MSVC++6.0
1103 for (int i = 0; i < objectSize; i++)
1104 switch (getType().getBasicType()) {
1105 case EbtBool: tempConstArray[i].setBConst((unionArray[i] == rightUnionArray[i]) ? false : true); break;
1106 default: assert(false && "Default missing");
1107 }
1108 }
1109 break;
1110
1111 case EOpLessThan:
1112 assert(objectSize == 1);
1113 tempConstArray = new ConstantUnion[1];
1114 tempConstArray->setBConst(*unionArray < *rightUnionArray);
Nicolas Capens31ad2aa2015-02-26 13:14:27 -05001115 returnType = TType(EbtBool, EbpUndefined, EvqConstExpr);
John Bauman66b8ab22014-05-06 15:57:45 -04001116 break;
1117 case EOpGreaterThan:
1118 assert(objectSize == 1);
1119 tempConstArray = new ConstantUnion[1];
1120 tempConstArray->setBConst(*unionArray > *rightUnionArray);
Nicolas Capens31ad2aa2015-02-26 13:14:27 -05001121 returnType = TType(EbtBool, EbpUndefined, EvqConstExpr);
John Bauman66b8ab22014-05-06 15:57:45 -04001122 break;
1123 case EOpLessThanEqual:
1124 {
1125 assert(objectSize == 1);
1126 ConstantUnion constant;
1127 constant.setBConst(*unionArray > *rightUnionArray);
1128 tempConstArray = new ConstantUnion[1];
1129 tempConstArray->setBConst(!constant.getBConst());
Nicolas Capens31ad2aa2015-02-26 13:14:27 -05001130 returnType = TType(EbtBool, EbpUndefined, EvqConstExpr);
John Bauman66b8ab22014-05-06 15:57:45 -04001131 break;
1132 }
1133 case EOpGreaterThanEqual:
1134 {
1135 assert(objectSize == 1);
1136 ConstantUnion constant;
1137 constant.setBConst(*unionArray < *rightUnionArray);
1138 tempConstArray = new ConstantUnion[1];
1139 tempConstArray->setBConst(!constant.getBConst());
Nicolas Capens31ad2aa2015-02-26 13:14:27 -05001140 returnType = TType(EbtBool, EbpUndefined, EvqConstExpr);
John Bauman66b8ab22014-05-06 15:57:45 -04001141 break;
1142 }
1143
1144 case EOpEqual:
1145 if (getType().getBasicType() == EbtStruct) {
1146 if (!CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray))
1147 boolNodeFlag = true;
1148 } else {
1149 for (int i = 0; i < objectSize; i++) {
1150 if (unionArray[i] != rightUnionArray[i]) {
1151 boolNodeFlag = true;
1152 break; // break out of for loop
1153 }
1154 }
1155 }
1156
1157 tempConstArray = new ConstantUnion[1];
1158 if (!boolNodeFlag) {
1159 tempConstArray->setBConst(true);
1160 }
1161 else {
1162 tempConstArray->setBConst(false);
1163 }
1164
Nicolas Capens31ad2aa2015-02-26 13:14:27 -05001165 tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConstExpr));
John Bauman66b8ab22014-05-06 15:57:45 -04001166 tempNode->setLine(getLine());
1167
1168 return tempNode;
1169
1170 case EOpNotEqual:
1171 if (getType().getBasicType() == EbtStruct) {
1172 if (CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray))
1173 boolNodeFlag = true;
1174 } else {
1175 for (int i = 0; i < objectSize; i++) {
1176 if (unionArray[i] == rightUnionArray[i]) {
1177 boolNodeFlag = true;
1178 break; // break out of for loop
1179 }
1180 }
1181 }
1182
1183 tempConstArray = new ConstantUnion[1];
1184 if (!boolNodeFlag) {
1185 tempConstArray->setBConst(true);
1186 }
1187 else {
1188 tempConstArray->setBConst(false);
1189 }
1190
Nicolas Capens31ad2aa2015-02-26 13:14:27 -05001191 tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConstExpr));
John Bauman66b8ab22014-05-06 15:57:45 -04001192 tempNode->setLine(getLine());
1193
1194 return tempNode;
1195
1196 default:
1197 infoSink.info.message(EPrefixInternalError, "Invalid operator for constant folding", getLine());
1198 return 0;
1199 }
1200 tempNode = new TIntermConstantUnion(tempConstArray, returnType);
1201 tempNode->setLine(getLine());
1202
1203 return tempNode;
1204 } else {
1205 //
1206 // Do unary operations
1207 //
1208 TIntermConstantUnion *newNode = 0;
1209 ConstantUnion* tempConstArray = new ConstantUnion[objectSize];
1210 for (int i = 0; i < objectSize; i++) {
1211 switch(op) {
1212 case EOpNegative:
1213 switch (getType().getBasicType()) {
1214 case EbtFloat: tempConstArray[i].setFConst(-unionArray[i].getFConst()); break;
1215 case EbtInt: tempConstArray[i].setIConst(-unionArray[i].getIConst()); break;
1216 default:
1217 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1218 return 0;
1219 }
1220 break;
1221 case EOpLogicalNot: // this code is written for possible future use, will not get executed currently
1222 switch (getType().getBasicType()) {
1223 case EbtBool: tempConstArray[i].setBConst(!unionArray[i].getBConst()); break;
1224 default:
1225 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1226 return 0;
1227 }
1228 break;
1229 default:
1230 return 0;
1231 }
1232 }
1233 newNode = new TIntermConstantUnion(tempConstArray, getType());
1234 newNode->setLine(getLine());
1235 return newNode;
1236 }
1237}
1238
1239TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermConstantUnion* node)
1240{
John Bauman66b8ab22014-05-06 15:57:45 -04001241 int size = node->getType().getObjectSize();
1242
1243 ConstantUnion *leftUnionArray = new ConstantUnion[size];
1244
1245 for (int i=0; i < size; i++) {
1246
1247 switch (promoteTo) {
1248 case EbtFloat:
1249 switch (node->getType().getBasicType()) {
1250 case EbtInt:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001251 leftUnionArray[i].setFConst(static_cast<float>(node->getIConst(i)));
John Bauman66b8ab22014-05-06 15:57:45 -04001252 break;
Nicolas Capens3c20f802015-02-17 17:17:20 -05001253 case EbtUInt:
1254 leftUnionArray[i].setFConst(static_cast<float>(node->getUConst(i)));
1255 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001256 case EbtBool:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001257 leftUnionArray[i].setFConst(static_cast<float>(node->getBConst(i)));
John Bauman66b8ab22014-05-06 15:57:45 -04001258 break;
1259 case EbtFloat:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001260 leftUnionArray[i].setFConst(static_cast<float>(node->getFConst(i)));
John Bauman66b8ab22014-05-06 15:57:45 -04001261 break;
1262 default:
1263 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
1264 return 0;
1265 }
1266 break;
1267 case EbtInt:
1268 switch (node->getType().getBasicType()) {
1269 case EbtInt:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001270 leftUnionArray[i].setIConst(static_cast<int>(node->getIConst(i)));
John Bauman66b8ab22014-05-06 15:57:45 -04001271 break;
Nicolas Capens3c20f802015-02-17 17:17:20 -05001272 case EbtUInt:
1273 leftUnionArray[i].setIConst(static_cast<int>(node->getUConst(i)));
1274 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001275 case EbtBool:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001276 leftUnionArray[i].setIConst(static_cast<int>(node->getBConst(i)));
John Bauman66b8ab22014-05-06 15:57:45 -04001277 break;
1278 case EbtFloat:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001279 leftUnionArray[i].setIConst(static_cast<int>(node->getFConst(i)));
John Bauman66b8ab22014-05-06 15:57:45 -04001280 break;
1281 default:
1282 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
1283 return 0;
1284 }
1285 break;
Nicolas Capens3c20f802015-02-17 17:17:20 -05001286 case EbtUInt:
1287 switch (node->getType().getBasicType()) {
1288 case EbtInt:
1289 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getIConst(i)));
1290 break;
1291 case EbtUInt:
1292 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getUConst(i)));
1293 break;
1294 case EbtBool:
1295 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getBConst(i)));
1296 break;
1297 case EbtFloat:
1298 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getFConst(i)));
1299 break;
1300 default:
1301 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
1302 return 0;
1303 }
1304 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001305 case EbtBool:
1306 switch (node->getType().getBasicType()) {
1307 case EbtInt:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001308 leftUnionArray[i].setBConst(node->getIConst(i) != 0);
John Bauman66b8ab22014-05-06 15:57:45 -04001309 break;
Nicolas Capens3c20f802015-02-17 17:17:20 -05001310 case EbtUInt:
1311 leftUnionArray[i].setBConst(node->getUConst(i) != 0);
1312 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001313 case EbtBool:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001314 leftUnionArray[i].setBConst(node->getBConst(i));
John Bauman66b8ab22014-05-06 15:57:45 -04001315 break;
1316 case EbtFloat:
Nicolas Capens55b22d62015-02-10 13:58:40 -05001317 leftUnionArray[i].setBConst(node->getFConst(i) != 0.0f);
John Bauman66b8ab22014-05-06 15:57:45 -04001318 break;
1319 default:
1320 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
1321 return 0;
1322 }
1323
1324 break;
1325 default:
1326 infoSink.info.message(EPrefixInternalError, "Incorrect data type found", node->getLine());
1327 return 0;
1328 }
1329
1330 }
1331
1332 const TType& t = node->getType();
1333
Alexis Hetub14178b2015-04-13 13:23:20 -04001334 return addConstantUnion(leftUnionArray, TType(promoteTo, t.getPrecision(), t.getQualifier(), t.getNominalSize(), t.getSecondarySize(), t.isArray()), node->getLine());
John Bauman66b8ab22014-05-06 15:57:45 -04001335}
1336