blob: a6b1b826b367cda1b26b7c96910f23a55b1d61f2 [file] [log] [blame]
Nicolas Capens0bac2852016-05-07 06:09:58 -04001// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
John Bauman66b8ab22014-05-06 15:57:45 -04002//
Nicolas Capens0bac2852016-05-07 06:09:58 -04003// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
John Bauman66b8ab22014-05-06 15:57:45 -04006//
Nicolas Capens0bac2852016-05-07 06:09:58 -04007// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
John Bauman66b8ab22014-05-06 15:57:45 -040014
15//
16// Build the intermediate representation.
17//
18
19#include <float.h>
20#include <limits.h>
21#include <algorithm>
22
Nicolas Capenscc863da2015-01-21 15:50:55 -050023#include "localintermediate.h"
24#include "SymbolTable.h"
Alexis Hetu2ce222c2016-05-02 11:20:52 -040025#include "Common/Math.hpp"
John Bauman66b8ab22014-05-06 15:57:45 -040026
27bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray);
28
29static TPrecision GetHigherPrecision( TPrecision left, TPrecision right ){
Nicolas Capens0bac2852016-05-07 06:09:58 -040030 return left > right ? left : right;
John Bauman66b8ab22014-05-06 15:57:45 -040031}
32
Alexis Hetu00106d42015-04-23 11:45:35 -040033static bool ValidateMultiplication(TOperator op, const TType &left, const TType &right)
34{
35 switch(op)
36 {
37 case EOpMul:
38 case EOpMulAssign:
39 return left.getNominalSize() == right.getNominalSize() &&
40 left.getSecondarySize() == right.getSecondarySize();
41 case EOpVectorTimesScalar:
42 case EOpVectorTimesScalarAssign:
43 return true;
44 case EOpVectorTimesMatrix:
45 return left.getNominalSize() == right.getSecondarySize();
46 case EOpVectorTimesMatrixAssign:
47 return left.getNominalSize() == right.getSecondarySize() &&
48 left.getNominalSize() == right.getNominalSize();
49 case EOpMatrixTimesVector:
50 return left.getNominalSize() == right.getNominalSize();
51 case EOpMatrixTimesScalar:
52 case EOpMatrixTimesScalarAssign:
53 return true;
54 case EOpMatrixTimesMatrix:
55 return left.getNominalSize() == right.getSecondarySize();
56 case EOpMatrixTimesMatrixAssign:
57 return left.getNominalSize() == right.getNominalSize() &&
58 left.getSecondarySize() == right.getSecondarySize();
59 default:
Nicolas Capens3713cd42015-06-22 10:41:54 -040060 UNREACHABLE(op);
Alexis Hetu00106d42015-04-23 11:45:35 -040061 return false;
62 }
63}
64
Alexis Hetuec93b1d2016-12-09 16:01:29 -050065TOperator TypeToConstructorOperator(const TType &type)
66{
67 switch(type.getBasicType())
68 {
69 case EbtFloat:
70 if(type.isMatrix())
71 {
72 switch(type.getNominalSize())
73 {
74 case 2:
75 switch(type.getSecondarySize())
76 {
77 case 2:
78 return EOpConstructMat2;
79 case 3:
80 return EOpConstructMat2x3;
81 case 4:
82 return EOpConstructMat2x4;
83 default:
84 break;
85 }
86 break;
87
88 case 3:
89 switch(type.getSecondarySize())
90 {
91 case 2:
92 return EOpConstructMat3x2;
93 case 3:
94 return EOpConstructMat3;
95 case 4:
96 return EOpConstructMat3x4;
97 default:
98 break;
99 }
100 break;
101
102 case 4:
103 switch(type.getSecondarySize())
104 {
105 case 2:
106 return EOpConstructMat4x2;
107 case 3:
108 return EOpConstructMat4x3;
109 case 4:
110 return EOpConstructMat4;
111 default:
112 break;
113 }
114 break;
115 }
116 }
117 else
118 {
119 switch(type.getNominalSize())
120 {
121 case 1:
122 return EOpConstructFloat;
123 case 2:
124 return EOpConstructVec2;
125 case 3:
126 return EOpConstructVec3;
127 case 4:
128 return EOpConstructVec4;
129 default:
130 break;
131 }
132 }
133 break;
134
135 case EbtInt:
136 switch(type.getNominalSize())
137 {
138 case 1:
139 return EOpConstructInt;
140 case 2:
141 return EOpConstructIVec2;
142 case 3:
143 return EOpConstructIVec3;
144 case 4:
145 return EOpConstructIVec4;
146 default:
147 break;
148 }
149 break;
150
151 case EbtUInt:
152 switch(type.getNominalSize())
153 {
154 case 1:
155 return EOpConstructUInt;
156 case 2:
157 return EOpConstructUVec2;
158 case 3:
159 return EOpConstructUVec3;
160 case 4:
161 return EOpConstructUVec4;
162 default:
163 break;
164 }
165 break;
166
167 case EbtBool:
168 switch(type.getNominalSize())
169 {
170 case 1:
171 return EOpConstructBool;
172 case 2:
173 return EOpConstructBVec2;
174 case 3:
175 return EOpConstructBVec3;
176 case 4:
177 return EOpConstructBVec4;
178 default:
179 break;
180 }
181 break;
182
183 case EbtStruct:
184 return EOpConstructStruct;
185
186 default:
187 break;
188 }
189
190 return EOpNull;
191}
192
John Bauman66b8ab22014-05-06 15:57:45 -0400193const char* getOperatorString(TOperator op) {
Nicolas Capens0bac2852016-05-07 06:09:58 -0400194 switch (op) {
195 case EOpInitialize: return "=";
196 case EOpAssign: return "=";
197 case EOpAddAssign: return "+=";
198 case EOpSubAssign: return "-=";
199 case EOpDivAssign: return "/=";
200 case EOpIModAssign: return "%=";
201 case EOpBitShiftLeftAssign: return "<<=";
202 case EOpBitShiftRightAssign: return ">>=";
203 case EOpBitwiseAndAssign: return "&=";
204 case EOpBitwiseXorAssign: return "^=";
205 case EOpBitwiseOrAssign: return "|=";
John Bauman66b8ab22014-05-06 15:57:45 -0400206
Nicolas Capens0bac2852016-05-07 06:09:58 -0400207 // Fall-through.
208 case EOpMulAssign:
209 case EOpVectorTimesMatrixAssign:
210 case EOpVectorTimesScalarAssign:
211 case EOpMatrixTimesScalarAssign:
212 case EOpMatrixTimesMatrixAssign: return "*=";
John Bauman66b8ab22014-05-06 15:57:45 -0400213
Nicolas Capens0bac2852016-05-07 06:09:58 -0400214 // Fall-through.
215 case EOpIndexDirect:
216 case EOpIndexIndirect: return "[]";
John Bauman66b8ab22014-05-06 15:57:45 -0400217
Nicolas Capens0bac2852016-05-07 06:09:58 -0400218 case EOpIndexDirectStruct: return ".";
219 case EOpVectorSwizzle: return ".";
220 case EOpAdd: return "+";
221 case EOpSub: return "-";
222 case EOpMul: return "*";
223 case EOpDiv: return "/";
224 case EOpMod: UNIMPLEMENTED(); break;
225 case EOpEqual: return "==";
226 case EOpNotEqual: return "!=";
227 case EOpLessThan: return "<";
228 case EOpGreaterThan: return ">";
229 case EOpLessThanEqual: return "<=";
230 case EOpGreaterThanEqual: return ">=";
John Bauman66b8ab22014-05-06 15:57:45 -0400231
Nicolas Capens0bac2852016-05-07 06:09:58 -0400232 // Fall-through.
233 case EOpVectorTimesScalar:
234 case EOpVectorTimesMatrix:
235 case EOpMatrixTimesVector:
236 case EOpMatrixTimesScalar:
237 case EOpMatrixTimesMatrix: return "*";
John Bauman66b8ab22014-05-06 15:57:45 -0400238
Nicolas Capens0bac2852016-05-07 06:09:58 -0400239 case EOpLogicalOr: return "||";
240 case EOpLogicalXor: return "^^";
241 case EOpLogicalAnd: return "&&";
242 case EOpIMod: return "%";
243 case EOpBitShiftLeft: return "<<";
244 case EOpBitShiftRight: return ">>";
245 case EOpBitwiseAnd: return "&";
246 case EOpBitwiseXor: return "^";
247 case EOpBitwiseOr: return "|";
248 case EOpNegative: return "-";
249 case EOpVectorLogicalNot: return "not";
250 case EOpLogicalNot: return "!";
251 case EOpBitwiseNot: return "~";
252 case EOpPostIncrement: return "++";
253 case EOpPostDecrement: return "--";
254 case EOpPreIncrement: return "++";
255 case EOpPreDecrement: return "--";
John Bauman66b8ab22014-05-06 15:57:45 -0400256
Nicolas Capens0bac2852016-05-07 06:09:58 -0400257 case EOpRadians: return "radians";
258 case EOpDegrees: return "degrees";
259 case EOpSin: return "sin";
260 case EOpCos: return "cos";
261 case EOpTan: return "tan";
262 case EOpAsin: return "asin";
263 case EOpAcos: return "acos";
264 case EOpAtan: return "atan";
265 case EOpSinh: return "sinh";
266 case EOpCosh: return "cosh";
267 case EOpTanh: return "tanh";
268 case EOpAsinh: return "asinh";
269 case EOpAcosh: return "acosh";
270 case EOpAtanh: return "atanh";
271 case EOpExp: return "exp";
272 case EOpLog: return "log";
273 case EOpExp2: return "exp2";
274 case EOpLog2: return "log2";
275 case EOpSqrt: return "sqrt";
276 case EOpInverseSqrt: return "inversesqrt";
277 case EOpAbs: return "abs";
278 case EOpSign: return "sign";
279 case EOpFloor: return "floor";
280 case EOpTrunc: return "trunc";
281 case EOpRound: return "round";
282 case EOpRoundEven: return "roundEven";
283 case EOpCeil: return "ceil";
284 case EOpFract: return "fract";
285 case EOpLength: return "length";
286 case EOpNormalize: return "normalize";
287 case EOpDFdx: return "dFdx";
288 case EOpDFdy: return "dFdy";
289 case EOpFwidth: return "fwidth";
290 case EOpAny: return "any";
291 case EOpAll: return "all";
292 case EOpIsNan: return "isnan";
293 case EOpIsInf: return "isinf";
294 case EOpOuterProduct: return "outerProduct";
295 case EOpTranspose: return "transpose";
296 case EOpDeterminant: return "determinant";
297 case EOpInverse: return "inverse";
John Bauman66b8ab22014-05-06 15:57:45 -0400298
Nicolas Capens0bac2852016-05-07 06:09:58 -0400299 default: break;
300 }
301 return "";
John Bauman66b8ab22014-05-06 15:57:45 -0400302}
303
304////////////////////////////////////////////////////////////////////////////
305//
306// First set of functions are to help build the intermediate representation.
307// These functions are not member functions of the nodes.
308// They are called from parser productions.
309//
310/////////////////////////////////////////////////////////////////////////////
311
312//
313// Add a terminal node for an identifier in an expression.
314//
315// Returns the added node.
316//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400317TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400318{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400319 TIntermSymbol* node = new TIntermSymbol(id, name, type);
320 node->setLine(line);
John Bauman66b8ab22014-05-06 15:57:45 -0400321
Nicolas Capens0bac2852016-05-07 06:09:58 -0400322 return node;
John Bauman66b8ab22014-05-06 15:57:45 -0400323}
324
325//
326// Connect two nodes with a new parent that does a binary operation on the nodes.
327//
328// Returns the added node.
329//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400330TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400331{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400332 bool isBitShift = false;
333 switch (op) {
334 case EOpEqual:
335 case EOpNotEqual:
336 if (left->isArray())
337 return 0;
338 break;
339 case EOpLessThan:
340 case EOpGreaterThan:
341 case EOpLessThanEqual:
342 case EOpGreaterThanEqual:
343 if (left->isMatrix() || left->isArray() || left->isVector() || left->getBasicType() == EbtStruct) {
344 return 0;
345 }
346 break;
347 case EOpLogicalOr:
348 case EOpLogicalXor:
349 case EOpLogicalAnd:
350 if (left->getBasicType() != EbtBool || left->isMatrix() || left->isArray() || left->isVector()) {
351 return 0;
352 }
353 break;
354 case EOpBitwiseOr:
355 case EOpBitwiseXor:
356 case EOpBitwiseAnd:
357 if (!IsInteger(left->getBasicType()) || left->isMatrix() || left->isArray()) {
358 return 0;
359 }
360 break;
361 case EOpAdd:
362 case EOpSub:
363 case EOpDiv:
364 case EOpMul:
365 if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool) {
366 return 0;
367 }
368 break;
369 case EOpIMod:
370 // Note that this is only for the % operator, not for mod()
371 if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool || left->getBasicType() == EbtFloat) {
372 return 0;
373 }
374 break;
375 case EOpBitShiftLeft:
376 case EOpBitShiftRight:
377 case EOpBitShiftLeftAssign:
378 case EOpBitShiftRightAssign:
379 // Unsigned can be bit-shifted by signed and vice versa, but we need to
380 // check that the basic type is an integer type.
381 isBitShift = true;
382 if(!IsInteger(left->getBasicType()) || !IsInteger(right->getBasicType()))
383 {
384 return 0;
385 }
386 break;
387 default: break;
388 }
John Bauman66b8ab22014-05-06 15:57:45 -0400389
Nicolas Capens0bac2852016-05-07 06:09:58 -0400390 if(!isBitShift && left->getBasicType() != right->getBasicType())
391 {
392 return 0;
393 }
John Bauman66b8ab22014-05-06 15:57:45 -0400394
Nicolas Capens0bac2852016-05-07 06:09:58 -0400395 //
396 // Need a new node holding things together then. Make
397 // one and promote it to the right type.
398 //
399 TIntermBinary* node = new TIntermBinary(op);
400 node->setLine(line);
John Bauman66b8ab22014-05-06 15:57:45 -0400401
Nicolas Capens0bac2852016-05-07 06:09:58 -0400402 node->setLeft(left);
403 node->setRight(right);
404 if (!node->promote(infoSink))
405 return 0;
John Bauman66b8ab22014-05-06 15:57:45 -0400406
Nicolas Capens0bac2852016-05-07 06:09:58 -0400407 //
408 // See if we can fold constants.
409 //
410 TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion();
411 TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion();
412 if (leftTempConstant && rightTempConstant) {
413 TIntermTyped *typedReturnNode = leftTempConstant->fold(node->getOp(), rightTempConstant, infoSink);
John Bauman66b8ab22014-05-06 15:57:45 -0400414
Nicolas Capens0bac2852016-05-07 06:09:58 -0400415 if (typedReturnNode)
416 return typedReturnNode;
417 }
John Bauman66b8ab22014-05-06 15:57:45 -0400418
Nicolas Capens0bac2852016-05-07 06:09:58 -0400419 return node;
John Bauman66b8ab22014-05-06 15:57:45 -0400420}
421
422//
423// Connect two nodes through an assignment.
424//
425// Returns the added node.
426//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400427TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400428{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400429 if (left->getType().getStruct() || right->getType().getStruct())
430 {
431 if (left->getType() != right->getType())
432 {
433 return 0;
434 }
435 }
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400436
Nicolas Capens0bac2852016-05-07 06:09:58 -0400437 TIntermBinary* node = new TIntermBinary(op);
438 node->setLine(line);
John Bauman66b8ab22014-05-06 15:57:45 -0400439
Nicolas Capens0bac2852016-05-07 06:09:58 -0400440 node->setLeft(left);
441 node->setRight(right);
442 if (! node->promote(infoSink))
443 return 0;
John Bauman66b8ab22014-05-06 15:57:45 -0400444
Nicolas Capens0bac2852016-05-07 06:09:58 -0400445 return node;
John Bauman66b8ab22014-05-06 15:57:45 -0400446}
447
448//
449// Connect two nodes through an index operator, where the left node is the base
450// of an array or struct, and the right node is a direct or indirect offset.
451//
452// Returns the added node.
453// The caller should set the type of the returned node.
454//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400455TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400456{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400457 TIntermBinary* node = new TIntermBinary(op);
458 node->setLine(line);
459 node->setLeft(base);
460 node->setRight(index);
John Bauman66b8ab22014-05-06 15:57:45 -0400461
Nicolas Capens0bac2852016-05-07 06:09:58 -0400462 // caller should set the type
John Bauman66b8ab22014-05-06 15:57:45 -0400463
Nicolas Capens0bac2852016-05-07 06:09:58 -0400464 return node;
John Bauman66b8ab22014-05-06 15:57:45 -0400465}
466
467//
468// Add one node as the parent of another that it operates on.
469//
470// Returns the added node.
471//
Nicolas Capensd3d9b9c2016-04-10 01:53:59 -0400472TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermTyped* child, const TSourceLoc &line, const TType *funcReturnType)
John Bauman66b8ab22014-05-06 15:57:45 -0400473{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400474 if (child == 0) {
475 infoSink.info.message(EPrefixInternalError, "Bad type in AddUnaryMath", line);
476 return 0;
477 }
John Bauman66b8ab22014-05-06 15:57:45 -0400478
Nicolas Capens0bac2852016-05-07 06:09:58 -0400479 switch (op) {
480 case EOpBitwiseNot:
481 if (!IsInteger(child->getType().getBasicType()) || child->getType().isMatrix() || child->getType().isArray()) {
482 return 0;
483 }
484 break;
Alexis Hetud061e422015-05-13 16:37:50 -0400485
Nicolas Capens0bac2852016-05-07 06:09:58 -0400486 case EOpLogicalNot:
487 if (child->getType().getBasicType() != EbtBool || child->getType().isMatrix() || child->getType().isArray() || child->getType().isVector()) {
488 return 0;
489 }
490 break;
John Bauman66b8ab22014-05-06 15:57:45 -0400491
Nicolas Capens0bac2852016-05-07 06:09:58 -0400492 case EOpPostIncrement:
493 case EOpPreIncrement:
494 case EOpPostDecrement:
495 case EOpPreDecrement:
496 case EOpNegative:
497 if (child->getType().getBasicType() == EbtStruct || child->getType().isArray())
498 return 0;
499 default: break;
500 }
John Bauman66b8ab22014-05-06 15:57:45 -0400501
Nicolas Capens0bac2852016-05-07 06:09:58 -0400502 TIntermConstantUnion *childTempConstant = 0;
503 if (child->getAsConstantUnion())
504 childTempConstant = child->getAsConstantUnion();
John Bauman66b8ab22014-05-06 15:57:45 -0400505
Nicolas Capens0bac2852016-05-07 06:09:58 -0400506 //
507 // Make a new node for the operator.
508 //
509 TIntermUnary *node = new TIntermUnary(op);
510 node->setLine(line);
511 node->setOperand(child);
John Bauman66b8ab22014-05-06 15:57:45 -0400512
Nicolas Capens0bac2852016-05-07 06:09:58 -0400513 if (! node->promote(infoSink, funcReturnType))
514 return 0;
John Bauman66b8ab22014-05-06 15:57:45 -0400515
Nicolas Capens0bac2852016-05-07 06:09:58 -0400516 if (childTempConstant) {
517 TIntermTyped* newChild = childTempConstant->fold(op, 0, infoSink);
John Bauman66b8ab22014-05-06 15:57:45 -0400518
Nicolas Capens0bac2852016-05-07 06:09:58 -0400519 if (newChild)
520 return newChild;
521 }
John Bauman66b8ab22014-05-06 15:57:45 -0400522
Nicolas Capens0bac2852016-05-07 06:09:58 -0400523 return node;
John Bauman66b8ab22014-05-06 15:57:45 -0400524}
525
526//
527// This is the safe way to change the operator on an aggregate, as it
528// does lots of error checking and fixing. Especially for establishing
529// a function call's operation on it's set of parameters. Sequences
530// of instructions are also aggregates, but they just direnctly set
531// their operator to EOpSequence.
532//
533// Returns an aggregate node, which could be the one passed in if
534// it was already an aggregate but no operator was set.
535//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400536TIntermAggregate* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator op, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400537{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400538 TIntermAggregate* aggNode;
John Bauman66b8ab22014-05-06 15:57:45 -0400539
Nicolas Capens0bac2852016-05-07 06:09:58 -0400540 //
541 // Make sure we have an aggregate. If not turn it into one.
542 //
543 if (node) {
544 aggNode = node->getAsAggregate();
545 if (aggNode == 0 || aggNode->getOp() != EOpNull) {
546 //
547 // Make an aggregate containing this node.
548 //
549 aggNode = new TIntermAggregate();
550 aggNode->getSequence().push_back(node);
551 }
552 } else
553 aggNode = new TIntermAggregate();
John Bauman66b8ab22014-05-06 15:57:45 -0400554
Nicolas Capens0bac2852016-05-07 06:09:58 -0400555 //
556 // Set the operator.
557 //
558 aggNode->setOp(op);
John Bauman66b8ab22014-05-06 15:57:45 -0400559
Nicolas Capens0bac2852016-05-07 06:09:58 -0400560 return aggNode;
John Bauman66b8ab22014-05-06 15:57:45 -0400561}
562
563//
John Bauman66b8ab22014-05-06 15:57:45 -0400564// Safe way to combine two nodes into an aggregate. Works with null pointers,
565// a node that's not a aggregate yet, etc.
566//
567// Returns the resulting aggregate, unless 0 was passed in for
568// both existing nodes.
569//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400570TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400571{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400572 if (left == 0 && right == 0)
573 return 0;
John Bauman66b8ab22014-05-06 15:57:45 -0400574
Nicolas Capens0bac2852016-05-07 06:09:58 -0400575 TIntermAggregate* aggNode = 0;
576 if (left)
577 aggNode = left->getAsAggregate();
578 if (!aggNode || aggNode->getOp() != EOpNull) {
579 aggNode = new TIntermAggregate;
580 if (left)
581 aggNode->getSequence().push_back(left);
582 }
John Bauman66b8ab22014-05-06 15:57:45 -0400583
Nicolas Capens0bac2852016-05-07 06:09:58 -0400584 if (right)
585 aggNode->getSequence().push_back(right);
John Bauman66b8ab22014-05-06 15:57:45 -0400586
Nicolas Capens0bac2852016-05-07 06:09:58 -0400587 aggNode->setLine(line);
John Bauman66b8ab22014-05-06 15:57:45 -0400588
Nicolas Capens0bac2852016-05-07 06:09:58 -0400589 return aggNode;
John Bauman66b8ab22014-05-06 15:57:45 -0400590}
591
592//
593// Turn an existing node into an aggregate.
594//
595// Returns an aggregate, unless 0 was passed in for the existing node.
596//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400597TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400598{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400599 if (node == 0)
600 return 0;
John Bauman66b8ab22014-05-06 15:57:45 -0400601
Nicolas Capens0bac2852016-05-07 06:09:58 -0400602 TIntermAggregate* aggNode = new TIntermAggregate;
603 aggNode->getSequence().push_back(node);
John Bauman66b8ab22014-05-06 15:57:45 -0400604
Nicolas Capens0bac2852016-05-07 06:09:58 -0400605 aggNode->setLine(line);
John Bauman66b8ab22014-05-06 15:57:45 -0400606
Nicolas Capens0bac2852016-05-07 06:09:58 -0400607 return aggNode;
John Bauman66b8ab22014-05-06 15:57:45 -0400608}
609
610//
611// For "if" test nodes. There are three children; a condition,
612// a true path, and a false path. The two paths are in the
613// nodePair.
614//
615// Returns the selection node created.
616//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400617TIntermNode* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nodePair, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400618{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400619 //
620 // For compile time constant selections, prune the code and
621 // test now.
622 //
John Bauman66b8ab22014-05-06 15:57:45 -0400623
Nicolas Capens0bac2852016-05-07 06:09:58 -0400624 if (cond->getAsTyped() && cond->getAsTyped()->getAsConstantUnion()) {
625 if (cond->getAsConstantUnion()->getBConst(0) == true)
626 return nodePair.node1 ? setAggregateOperator(nodePair.node1, EOpSequence, nodePair.node1->getLine()) : nullptr;
627 else
628 return nodePair.node2 ? setAggregateOperator(nodePair.node2, EOpSequence, nodePair.node2->getLine()) : nullptr;
629 }
John Bauman66b8ab22014-05-06 15:57:45 -0400630
Nicolas Capens0bac2852016-05-07 06:09:58 -0400631 TIntermSelection* node = new TIntermSelection(cond, nodePair.node1, nodePair.node2);
632 node->setLine(line);
John Bauman66b8ab22014-05-06 15:57:45 -0400633
Nicolas Capens0bac2852016-05-07 06:09:58 -0400634 return node;
John Bauman66b8ab22014-05-06 15:57:45 -0400635}
636
637
Alexis Hetu253fdd12015-07-07 15:12:46 -0400638TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400639{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400640 if (left->getType().getQualifier() == EvqConstExpr && right->getType().getQualifier() == EvqConstExpr) {
641 return right;
642 } else {
643 TIntermTyped *commaAggregate = growAggregate(left, right, line);
644 commaAggregate->getAsAggregate()->setOp(EOpComma);
645 commaAggregate->setType(right->getType());
646 commaAggregate->getTypePointer()->setQualifier(EvqTemporary);
647 return commaAggregate;
648 }
John Bauman66b8ab22014-05-06 15:57:45 -0400649}
650
651//
652// For "?:" test nodes. There are three children; a condition,
653// a true path, and a false path. The two paths are specified
654// as separate parameters.
655//
656// Returns the selection node created, or 0 if one could not be.
657//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400658TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400659{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400660 if (trueBlock->getType() != falseBlock->getType())
661 {
662 return 0;
663 }
John Bauman66b8ab22014-05-06 15:57:45 -0400664
Nicolas Capens0bac2852016-05-07 06:09:58 -0400665 //
666 // See if all the operands are constant, then fold it otherwise not.
667 //
John Bauman66b8ab22014-05-06 15:57:45 -0400668
Nicolas Capens0bac2852016-05-07 06:09:58 -0400669 if (cond->getAsConstantUnion() && trueBlock->getAsConstantUnion() && falseBlock->getAsConstantUnion()) {
670 if (cond->getAsConstantUnion()->getBConst(0))
671 return trueBlock;
672 else
673 return falseBlock;
674 }
John Bauman66b8ab22014-05-06 15:57:45 -0400675
Nicolas Capens0bac2852016-05-07 06:09:58 -0400676 //
677 // Make a selection node.
678 //
679 TIntermSelection* node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType());
680 node->getTypePointer()->setQualifier(EvqTemporary);
681 node->setLine(line);
John Bauman66b8ab22014-05-06 15:57:45 -0400682
Nicolas Capens0bac2852016-05-07 06:09:58 -0400683 return node;
John Bauman66b8ab22014-05-06 15:57:45 -0400684}
685
Alexis Hetu76a343a2015-06-04 17:21:22 -0400686TIntermSwitch *TIntermediate::addSwitch(TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &line)
687{
688 TIntermSwitch *node = new TIntermSwitch(init, statementList);
689 node->setLine(line);
690
691 return node;
692}
693
694TIntermCase *TIntermediate::addCase(TIntermTyped *condition, const TSourceLoc &line)
695{
696 TIntermCase *node = new TIntermCase(condition);
697 node->setLine(line);
698
699 return node;
700}
701
John Bauman66b8ab22014-05-06 15:57:45 -0400702//
703// Constant terminal nodes. Has a union that contains bool, float or int constants
704//
705// Returns the constant union node created.
706//
707
Alexis Hetu253fdd12015-07-07 15:12:46 -0400708TIntermConstantUnion* TIntermediate::addConstantUnion(ConstantUnion* unionArrayPointer, const TType& t, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400709{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400710 TIntermConstantUnion* node = new TIntermConstantUnion(unionArrayPointer, t);
711 node->setLine(line);
John Bauman66b8ab22014-05-06 15:57:45 -0400712
Nicolas Capens0bac2852016-05-07 06:09:58 -0400713 return node;
John Bauman66b8ab22014-05-06 15:57:45 -0400714}
715
Alexis Hetu253fdd12015-07-07 15:12:46 -0400716TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400717{
718
Nicolas Capens0bac2852016-05-07 06:09:58 -0400719 TIntermAggregate* node = new TIntermAggregate(EOpSequence);
John Bauman66b8ab22014-05-06 15:57:45 -0400720
Nicolas Capens0bac2852016-05-07 06:09:58 -0400721 node->setLine(line);
722 TIntermConstantUnion* constIntNode;
723 TIntermSequence &sequenceVector = node->getSequence();
724 ConstantUnion* unionArray;
John Bauman66b8ab22014-05-06 15:57:45 -0400725
Nicolas Capens0bac2852016-05-07 06:09:58 -0400726 for (int i = 0; i < fields.num; i++) {
727 unionArray = new ConstantUnion[1];
728 unionArray->setIConst(fields.offsets[i]);
729 constIntNode = addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConstExpr), line);
730 sequenceVector.push_back(constIntNode);
731 }
John Bauman66b8ab22014-05-06 15:57:45 -0400732
Nicolas Capens0bac2852016-05-07 06:09:58 -0400733 return node;
John Bauman66b8ab22014-05-06 15:57:45 -0400734}
735
736//
737// Create loop nodes.
738//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400739TIntermNode* TIntermediate::addLoop(TLoopType type, TIntermNode* init, TIntermTyped* cond, TIntermTyped* expr, TIntermNode* body, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400740{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400741 TIntermNode* node = new TIntermLoop(type, init, cond, expr, body);
742 node->setLine(line);
John Bauman66b8ab22014-05-06 15:57:45 -0400743
Nicolas Capens0bac2852016-05-07 06:09:58 -0400744 return node;
John Bauman66b8ab22014-05-06 15:57:45 -0400745}
746
747//
748// Add branches.
749//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400750TIntermBranch* TIntermediate::addBranch(TOperator branchOp, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400751{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400752 return addBranch(branchOp, 0, line);
John Bauman66b8ab22014-05-06 15:57:45 -0400753}
754
Alexis Hetu253fdd12015-07-07 15:12:46 -0400755TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expression, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400756{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400757 TIntermBranch* node = new TIntermBranch(branchOp, expression);
758 node->setLine(line);
John Bauman66b8ab22014-05-06 15:57:45 -0400759
Nicolas Capens0bac2852016-05-07 06:09:58 -0400760 return node;
John Bauman66b8ab22014-05-06 15:57:45 -0400761}
762
763//
764// This is to be executed once the final root is put on top by the parsing
765// process.
766//
767bool TIntermediate::postProcess(TIntermNode* root)
768{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400769 if (root == 0)
770 return true;
John Bauman66b8ab22014-05-06 15:57:45 -0400771
Nicolas Capens0bac2852016-05-07 06:09:58 -0400772 //
773 // First, finish off the top level sequence, if any
774 //
775 TIntermAggregate* aggRoot = root->getAsAggregate();
776 if (aggRoot && aggRoot->getOp() == EOpNull)
777 aggRoot->setOp(EOpSequence);
John Bauman66b8ab22014-05-06 15:57:45 -0400778
Nicolas Capens0bac2852016-05-07 06:09:58 -0400779 return true;
John Bauman66b8ab22014-05-06 15:57:45 -0400780}
781
John Bauman66b8ab22014-05-06 15:57:45 -0400782////////////////////////////////////////////////////////////////
783//
784// Member functions of the nodes used for building the tree.
785//
786////////////////////////////////////////////////////////////////
787
Alexis Hetuec93b1d2016-12-09 16:01:29 -0500788// static
789TIntermTyped *TIntermTyped::CreateIndexNode(int index)
790{
791 ConstantUnion *u = new ConstantUnion[1];
792 u[0].setIConst(index);
793
794 TType type(EbtInt, EbpUndefined, EvqConstExpr, 1);
795 TIntermConstantUnion *node = new TIntermConstantUnion(u, type);
796 return node;
797}
798
John Bauman66b8ab22014-05-06 15:57:45 -0400799//
800// Say whether or not an operation node changes the value of a variable.
801//
802// Returns true if state is modified.
803//
804bool TIntermOperator::modifiesState() const
805{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400806 switch (op) {
807 case EOpPostIncrement:
808 case EOpPostDecrement:
809 case EOpPreIncrement:
810 case EOpPreDecrement:
811 case EOpAssign:
812 case EOpAddAssign:
813 case EOpSubAssign:
814 case EOpMulAssign:
815 case EOpVectorTimesMatrixAssign:
816 case EOpVectorTimesScalarAssign:
817 case EOpMatrixTimesScalarAssign:
818 case EOpMatrixTimesMatrixAssign:
819 case EOpDivAssign:
820 case EOpIModAssign:
821 case EOpBitShiftLeftAssign:
822 case EOpBitShiftRightAssign:
823 case EOpBitwiseAndAssign:
824 case EOpBitwiseXorAssign:
825 case EOpBitwiseOrAssign:
826 return true;
827 default:
828 return false;
829 }
John Bauman66b8ab22014-05-06 15:57:45 -0400830}
831
832//
833// returns true if the operator is for one of the constructors
834//
835bool TIntermOperator::isConstructor() const
836{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400837 switch (op) {
838 case EOpConstructVec2:
839 case EOpConstructVec3:
840 case EOpConstructVec4:
841 case EOpConstructMat2:
842 case EOpConstructMat2x3:
843 case EOpConstructMat2x4:
844 case EOpConstructMat3x2:
845 case EOpConstructMat3:
846 case EOpConstructMat3x4:
847 case EOpConstructMat4x2:
848 case EOpConstructMat4x3:
849 case EOpConstructMat4:
850 case EOpConstructFloat:
851 case EOpConstructIVec2:
852 case EOpConstructIVec3:
853 case EOpConstructIVec4:
854 case EOpConstructInt:
855 case EOpConstructUVec2:
856 case EOpConstructUVec3:
857 case EOpConstructUVec4:
858 case EOpConstructUInt:
859 case EOpConstructBVec2:
860 case EOpConstructBVec3:
861 case EOpConstructBVec4:
862 case EOpConstructBool:
863 case EOpConstructStruct:
864 return true;
865 default:
866 return false;
867 }
John Bauman66b8ab22014-05-06 15:57:45 -0400868}
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400869
John Bauman66b8ab22014-05-06 15:57:45 -0400870//
871// Make sure the type of a unary operator is appropriate for its
872// combination of operation and operand type.
873//
874// Returns false in nothing makes sense.
875//
Nicolas Capensd3d9b9c2016-04-10 01:53:59 -0400876bool TIntermUnary::promote(TInfoSink&, const TType *funcReturnType)
John Bauman66b8ab22014-05-06 15:57:45 -0400877{
Nicolas Capensd3d9b9c2016-04-10 01:53:59 -0400878 setType(funcReturnType ? *funcReturnType : operand->getType());
879
880 // Unary operations result in temporary variables unless const.
Nicolas Capens0bac2852016-05-07 06:09:58 -0400881 if(type.getQualifier() != EvqConstExpr)
Nicolas Capensd3d9b9c2016-04-10 01:53:59 -0400882 {
Nicolas Capens0bac2852016-05-07 06:09:58 -0400883 type.setQualifier(EvqTemporary);
884 }
Nicolas Capensd3d9b9c2016-04-10 01:53:59 -0400885
Nicolas Capens0bac2852016-05-07 06:09:58 -0400886 switch (op) {
887 case EOpLogicalNot:
888 if (operand->getBasicType() != EbtBool)
889 return false;
890 break;
891 case EOpBitwiseNot:
892 if (!IsInteger(operand->getBasicType()))
893 return false;
894 break;
895 case EOpNegative:
896 case EOpPostIncrement:
897 case EOpPostDecrement:
898 case EOpPreIncrement:
899 case EOpPreDecrement:
900 if (operand->getBasicType() == EbtBool)
901 return false;
902 break;
John Bauman66b8ab22014-05-06 15:57:45 -0400903
Nicolas Capens0bac2852016-05-07 06:09:58 -0400904 // operators for built-ins are already type checked against their prototype
905 case EOpAny:
906 case EOpAll:
907 case EOpVectorLogicalNot:
Alexis Hetu0f448072016-03-18 10:56:08 -0400908 case EOpAbs:
909 case EOpSign:
910 case EOpIsNan:
911 case EOpIsInf:
912 case EOpFloatBitsToInt:
913 case EOpFloatBitsToUint:
914 case EOpIntBitsToFloat:
915 case EOpUintBitsToFloat:
916 case EOpPackSnorm2x16:
917 case EOpPackUnorm2x16:
918 case EOpPackHalf2x16:
919 case EOpUnpackSnorm2x16:
920 case EOpUnpackUnorm2x16:
921 case EOpUnpackHalf2x16:
Nicolas Capens0bac2852016-05-07 06:09:58 -0400922 return true;
John Bauman66b8ab22014-05-06 15:57:45 -0400923
Nicolas Capens0bac2852016-05-07 06:09:58 -0400924 default:
925 if (operand->getBasicType() != EbtFloat)
926 return false;
927 }
John Bauman66b8ab22014-05-06 15:57:45 -0400928
Nicolas Capens0bac2852016-05-07 06:09:58 -0400929 return true;
John Bauman66b8ab22014-05-06 15:57:45 -0400930}
931
932//
933// Establishes the type of the resultant operation, as well as
934// makes the operator the correct one for the operands.
935//
936// Returns false if operator can't work on operands.
937//
938bool TIntermBinary::promote(TInfoSink& infoSink)
939{
Alexis Hetue5246692015-06-18 12:34:52 -0400940 ASSERT(left->isArray() == right->isArray());
John Bauman66b8ab22014-05-06 15:57:45 -0400941
Nicolas Capens0bac2852016-05-07 06:09:58 -0400942 // GLSL ES 2.0 does not support implicit type casting.
943 // So the basic type should always match.
Alexis Hetu92ab1982015-08-18 15:28:27 -0400944 // GLSL ES 3.0 supports integer shift operands of different signedness.
945 if(op != EOpBitShiftLeft &&
946 op != EOpBitShiftRight &&
947 op != EOpBitShiftLeftAssign &&
948 op != EOpBitShiftRightAssign &&
949 left->getBasicType() != right->getBasicType())
Nicolas Capens0bac2852016-05-07 06:09:58 -0400950 {
951 return false;
952 }
John Bauman66b8ab22014-05-06 15:57:45 -0400953
Nicolas Capens0bac2852016-05-07 06:09:58 -0400954 //
955 // Base assumption: just make the type the same as the left
956 // operand. Then only deviations from this need be coded.
957 //
958 setType(left->getType());
John Bauman66b8ab22014-05-06 15:57:45 -0400959
Nicolas Capens0bac2852016-05-07 06:09:58 -0400960 // The result gets promoted to the highest precision.
961 TPrecision higherPrecision = GetHigherPrecision(left->getPrecision(), right->getPrecision());
962 getTypePointer()->setPrecision(higherPrecision);
John Bauman66b8ab22014-05-06 15:57:45 -0400963
Nicolas Capens0bac2852016-05-07 06:09:58 -0400964 // Binary operations results in temporary variables unless both
965 // operands are const.
966 if (left->getQualifier() != EvqConstExpr || right->getQualifier() != EvqConstExpr) {
967 getTypePointer()->setQualifier(EvqTemporary);
968 }
John Bauman66b8ab22014-05-06 15:57:45 -0400969
Nicolas Capens0bac2852016-05-07 06:09:58 -0400970 int primarySize = std::max(left->getNominalSize(), right->getNominalSize());
John Bauman66b8ab22014-05-06 15:57:45 -0400971
Nicolas Capens0bac2852016-05-07 06:09:58 -0400972 //
973 // All scalars. Code after this test assumes this case is removed!
974 //
975 if (primarySize == 1) {
976 switch (op) {
977 //
978 // Promote to conditional
979 //
980 case EOpEqual:
981 case EOpNotEqual:
982 case EOpLessThan:
983 case EOpGreaterThan:
984 case EOpLessThanEqual:
985 case EOpGreaterThanEqual:
986 setType(TType(EbtBool, EbpUndefined));
987 break;
John Bauman66b8ab22014-05-06 15:57:45 -0400988
Nicolas Capens0bac2852016-05-07 06:09:58 -0400989 //
990 // And and Or operate on conditionals
991 //
992 case EOpLogicalAnd:
993 case EOpLogicalOr:
994 case EOpLogicalXor:
995 // Both operands must be of type bool.
996 if (left->getBasicType() != EbtBool || right->getBasicType() != EbtBool)
997 return false;
998 setType(TType(EbtBool, EbpUndefined));
999 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001000
Nicolas Capens0bac2852016-05-07 06:09:58 -04001001 default:
1002 break;
1003 }
1004 return true;
1005 }
John Bauman66b8ab22014-05-06 15:57:45 -04001006
Nicolas Capens0bac2852016-05-07 06:09:58 -04001007 // If we reach here, at least one of the operands is vector or matrix.
1008 // The other operand could be a scalar, vector, or matrix.
1009 // Can these two operands be combined?
1010 //
1011 TBasicType basicType = left->getBasicType();
1012 switch (op) {
1013 case EOpMul:
1014 if (!left->isMatrix() && right->isMatrix()) {
1015 if (left->isVector())
1016 {
1017 op = EOpVectorTimesMatrix;
1018 setType(TType(basicType, higherPrecision, EvqTemporary,
1019 static_cast<unsigned char>(right->getNominalSize()), 1));
1020 }
1021 else {
1022 op = EOpMatrixTimesScalar;
1023 setType(TType(basicType, higherPrecision, EvqTemporary,
1024 static_cast<unsigned char>(right->getNominalSize()), static_cast<unsigned char>(right->getSecondarySize())));
1025 }
1026 } else if (left->isMatrix() && !right->isMatrix()) {
1027 if (right->isVector()) {
1028 op = EOpMatrixTimesVector;
1029 setType(TType(basicType, higherPrecision, EvqTemporary,
1030 static_cast<unsigned char>(left->getSecondarySize()), 1));
1031 } else {
1032 op = EOpMatrixTimesScalar;
1033 }
1034 } else if (left->isMatrix() && right->isMatrix()) {
1035 op = EOpMatrixTimesMatrix;
1036 setType(TType(basicType, higherPrecision, EvqTemporary,
1037 static_cast<unsigned char>(right->getNominalSize()), static_cast<unsigned char>(left->getSecondarySize())));
1038 } else if (!left->isMatrix() && !right->isMatrix()) {
1039 if (left->isVector() && right->isVector()) {
1040 // leave as component product
1041 } else if (left->isVector() || right->isVector()) {
1042 op = EOpVectorTimesScalar;
1043 setType(TType(basicType, higherPrecision, EvqTemporary,
1044 static_cast<unsigned char>(primarySize), 1));
1045 }
1046 } else {
1047 infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
1048 return false;
1049 }
Alexis Hetu00106d42015-04-23 11:45:35 -04001050
Nicolas Capens0bac2852016-05-07 06:09:58 -04001051 if(!ValidateMultiplication(op, left->getType(), right->getType()))
1052 {
1053 return false;
1054 }
1055 break;
1056 case EOpMulAssign:
1057 if (!left->isMatrix() && right->isMatrix()) {
1058 if (left->isVector())
1059 op = EOpVectorTimesMatrixAssign;
1060 else {
1061 return false;
1062 }
1063 } else if (left->isMatrix() && !right->isMatrix()) {
1064 if (right->isVector()) {
1065 return false;
1066 } else {
1067 op = EOpMatrixTimesScalarAssign;
1068 }
1069 } else if (left->isMatrix() && right->isMatrix()) {
1070 op = EOpMatrixTimesMatrixAssign;
1071 setType(TType(basicType, higherPrecision, EvqTemporary,
1072 static_cast<unsigned char>(right->getNominalSize()), static_cast<unsigned char>(left->getSecondarySize())));
1073 } else if (!left->isMatrix() && !right->isMatrix()) {
1074 if (left->isVector() && right->isVector()) {
1075 // leave as component product
1076 } else if (left->isVector() || right->isVector()) {
1077 if (! left->isVector())
1078 return false;
1079 op = EOpVectorTimesScalarAssign;
1080 setType(TType(basicType, higherPrecision, EvqTemporary,
1081 static_cast<unsigned char>(left->getNominalSize()), 1));
1082 }
1083 } else {
1084 infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
1085 return false;
1086 }
Alexis Hetu00106d42015-04-23 11:45:35 -04001087
Nicolas Capens0bac2852016-05-07 06:09:58 -04001088 if(!ValidateMultiplication(op, left->getType(), right->getType()))
1089 {
1090 return false;
1091 }
1092 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001093
Nicolas Capens0bac2852016-05-07 06:09:58 -04001094 case EOpAssign:
1095 case EOpInitialize:
1096 // No more additional checks are needed.
1097 if ((left->getNominalSize() != right->getNominalSize()) ||
1098 (left->getSecondarySize() != right->getSecondarySize()))
1099 return false;
1100 break;
1101 case EOpAdd:
1102 case EOpSub:
1103 case EOpDiv:
1104 case EOpIMod:
1105 case EOpBitShiftLeft:
1106 case EOpBitShiftRight:
1107 case EOpBitwiseAnd:
1108 case EOpBitwiseXor:
1109 case EOpBitwiseOr:
1110 case EOpAddAssign:
1111 case EOpSubAssign:
1112 case EOpDivAssign:
1113 case EOpIModAssign:
1114 case EOpBitShiftLeftAssign:
1115 case EOpBitShiftRightAssign:
1116 case EOpBitwiseAndAssign:
1117 case EOpBitwiseXorAssign:
1118 case EOpBitwiseOrAssign:
1119 if ((left->isMatrix() && right->isVector()) ||
1120 (left->isVector() && right->isMatrix()))
1121 return false;
Alexis Hetud061e422015-05-13 16:37:50 -04001122
Nicolas Capens0bac2852016-05-07 06:09:58 -04001123 // Are the sizes compatible?
1124 if(left->getNominalSize() != right->getNominalSize() ||
1125 left->getSecondarySize() != right->getSecondarySize())
1126 {
1127 // If the nominal sizes of operands do not match:
1128 // One of them must be a scalar.
1129 if(!left->isScalar() && !right->isScalar())
1130 return false;
Alexis Hetud061e422015-05-13 16:37:50 -04001131
Nicolas Capens0bac2852016-05-07 06:09:58 -04001132 // In the case of compound assignment other than multiply-assign,
1133 // the right side needs to be a scalar. Otherwise a vector/matrix
1134 // would be assigned to a scalar. A scalar can't be shifted by a
1135 // vector either.
1136 if(!right->isScalar() && (modifiesState() || op == EOpBitShiftLeft || op == EOpBitShiftRight))
1137 return false;
1138 }
Alexis Hetud061e422015-05-13 16:37:50 -04001139
Nicolas Capens0bac2852016-05-07 06:09:58 -04001140 {
1141 const int secondarySize = std::max(
1142 left->getSecondarySize(), right->getSecondarySize());
1143 setType(TType(basicType, higherPrecision, EvqTemporary,
1144 static_cast<unsigned char>(primarySize), static_cast<unsigned char>(secondarySize)));
1145 if(left->isArray())
1146 {
1147 ASSERT(left->getArraySize() == right->getArraySize());
1148 type.setArraySize(left->getArraySize());
1149 }
1150 }
1151 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001152
Nicolas Capens0bac2852016-05-07 06:09:58 -04001153 case EOpEqual:
1154 case EOpNotEqual:
1155 case EOpLessThan:
1156 case EOpGreaterThan:
1157 case EOpLessThanEqual:
1158 case EOpGreaterThanEqual:
1159 if ((left->getNominalSize() != right->getNominalSize()) ||
1160 (left->getSecondarySize() != right->getSecondarySize()))
1161 return false;
1162 setType(TType(EbtBool, EbpUndefined));
1163 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001164
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001165 case EOpOuterProduct:
1166 if(!left->isVector() || !right->isVector())
1167 return false;
1168 setType(TType(EbtFloat, right->getNominalSize(), left->getNominalSize()));
1169 break;
1170
1171 case EOpTranspose:
1172 if(!right->isMatrix())
1173 return false;
1174 setType(TType(EbtFloat, right->getSecondarySize(), right->getNominalSize()));
1175 break;
1176
1177 case EOpDeterminant:
1178 if(!right->isMatrix())
1179 return false;
1180 setType(TType(EbtFloat));
1181 break;
1182
1183 case EOpInverse:
1184 if(!right->isMatrix() || right->getNominalSize() != right->getSecondarySize())
1185 return false;
1186 setType(right->getType());
1187 break;
1188
Nicolas Capens0bac2852016-05-07 06:09:58 -04001189 default:
1190 return false;
1191 }
Nicolas Capens5e0c3542016-04-05 17:18:24 -04001192
Nicolas Capens0bac2852016-05-07 06:09:58 -04001193 return true;
John Bauman66b8ab22014-05-06 15:57:45 -04001194}
1195
1196bool CompareStruct(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
1197{
Nicolas Capens0bac2852016-05-07 06:09:58 -04001198 const TFieldList& fields = leftNodeType.getStruct()->fields();
John Bauman66b8ab22014-05-06 15:57:45 -04001199
Nicolas Capens0bac2852016-05-07 06:09:58 -04001200 size_t structSize = fields.size();
1201 int index = 0;
John Bauman66b8ab22014-05-06 15:57:45 -04001202
Nicolas Capens0bac2852016-05-07 06:09:58 -04001203 for (size_t j = 0; j < structSize; j++) {
1204 size_t size = fields[j]->type()->getObjectSize();
1205 for(size_t i = 0; i < size; i++) {
1206 if (fields[j]->type()->getBasicType() == EbtStruct) {
1207 if (!CompareStructure(*(fields[j]->type()), &rightUnionArray[index], &leftUnionArray[index]))
1208 return false;
1209 } else {
1210 if (leftUnionArray[index] != rightUnionArray[index])
1211 return false;
1212 index++;
1213 }
John Bauman66b8ab22014-05-06 15:57:45 -04001214
Nicolas Capens0bac2852016-05-07 06:09:58 -04001215 }
1216 }
1217 return true;
John Bauman66b8ab22014-05-06 15:57:45 -04001218}
1219
1220bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
1221{
Nicolas Capens0bac2852016-05-07 06:09:58 -04001222 if (leftNodeType.isArray()) {
1223 TType typeWithoutArrayness = leftNodeType;
1224 typeWithoutArrayness.clearArrayness();
John Bauman66b8ab22014-05-06 15:57:45 -04001225
Nicolas Capens0bac2852016-05-07 06:09:58 -04001226 int arraySize = leftNodeType.getArraySize();
John Bauman66b8ab22014-05-06 15:57:45 -04001227
Nicolas Capens0bac2852016-05-07 06:09:58 -04001228 for (int i = 0; i < arraySize; ++i) {
1229 size_t offset = typeWithoutArrayness.getObjectSize() * i;
1230 if (!CompareStruct(typeWithoutArrayness, &rightUnionArray[offset], &leftUnionArray[offset]))
1231 return false;
1232 }
1233 } else
1234 return CompareStruct(leftNodeType, rightUnionArray, leftUnionArray);
John Bauman66b8ab22014-05-06 15:57:45 -04001235
Nicolas Capens0bac2852016-05-07 06:09:58 -04001236 return true;
John Bauman66b8ab22014-05-06 15:57:45 -04001237}
1238
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001239float determinant2(float m00, float m01, float m10, float m11)
1240{
1241 return m00 * m11 - m01 * m10;
1242}
1243
1244float determinant3(float m00, float m01, float m02,
Nicolas Capens0bac2852016-05-07 06:09:58 -04001245 float m10, float m11, float m12,
1246 float m20, float m21, float m22)
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001247{
1248 return m00 * determinant2(m11, m12, m21, m22) -
Nicolas Capens0bac2852016-05-07 06:09:58 -04001249 m10 * determinant2(m01, m02, m21, m22) +
1250 m20 * determinant2(m01, m02, m11, m12);
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001251}
1252
1253float determinant4(float m00, float m01, float m02, float m03,
Nicolas Capens0bac2852016-05-07 06:09:58 -04001254 float m10, float m11, float m12, float m13,
1255 float m20, float m21, float m22, float m23,
1256 float m30, float m31, float m32, float m33)
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001257{
1258 return m00 * determinant3(m11, m12, m13, m21, m22, m23, m31, m32, m33) -
Nicolas Capens0bac2852016-05-07 06:09:58 -04001259 m10 * determinant3(m01, m02, m03, m21, m22, m23, m31, m32, m33) +
1260 m20 * determinant3(m01, m02, m03, m11, m12, m13, m31, m32, m33) -
1261 m30 * determinant3(m01, m02, m03, m11, m12, m13, m21, m22, m23);
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001262}
1263
1264float ComputeDeterminant(int size, ConstantUnion* unionArray)
1265{
1266 switch(size)
1267 {
1268 case 2:
1269 return determinant2(unionArray[0].getFConst(),
Nicolas Capens0bac2852016-05-07 06:09:58 -04001270 unionArray[1].getFConst(),
1271 unionArray[2].getFConst(),
1272 unionArray[3].getFConst());
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001273 case 3:
1274 return determinant3(unionArray[0].getFConst(),
Nicolas Capens0bac2852016-05-07 06:09:58 -04001275 unionArray[1].getFConst(),
1276 unionArray[2].getFConst(),
1277 unionArray[3].getFConst(),
1278 unionArray[4].getFConst(),
1279 unionArray[5].getFConst(),
1280 unionArray[6].getFConst(),
1281 unionArray[7].getFConst(),
1282 unionArray[8].getFConst());
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001283 case 4:
1284 return determinant4(unionArray[0].getFConst(),
Nicolas Capens0bac2852016-05-07 06:09:58 -04001285 unionArray[1].getFConst(),
1286 unionArray[2].getFConst(),
1287 unionArray[3].getFConst(),
1288 unionArray[4].getFConst(),
1289 unionArray[5].getFConst(),
1290 unionArray[6].getFConst(),
1291 unionArray[7].getFConst(),
1292 unionArray[8].getFConst(),
1293 unionArray[9].getFConst(),
1294 unionArray[10].getFConst(),
1295 unionArray[11].getFConst(),
1296 unionArray[12].getFConst(),
1297 unionArray[13].getFConst(),
1298 unionArray[14].getFConst(),
1299 unionArray[15].getFConst());
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001300 default:
Nicolas Capens3713cd42015-06-22 10:41:54 -04001301 UNREACHABLE(size);
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001302 return 0.0f;
1303 }
1304}
1305
1306ConstantUnion* CreateInverse(TIntermConstantUnion* node, ConstantUnion* unionArray)
1307{
1308 ConstantUnion* tempConstArray = 0;
1309 int size = node->getNominalSize();
1310 float determinant = ComputeDeterminant(size, unionArray);
1311 if(determinant != 0.0f)
1312 {
1313 float invDet = 1.0f / determinant;
1314 tempConstArray = new ConstantUnion[size*size];
1315 switch(size)
1316 {
1317 case 2:
1318 {
1319 float m00 = unionArray[0].getFConst(); // Matrix is:
1320 float m01 = unionArray[1].getFConst(); // (m00, m01)
1321 float m10 = unionArray[2].getFConst(); // (m10, m11)
1322 float m11 = unionArray[3].getFConst();
1323 tempConstArray[0].setFConst( invDet * m11);
1324 tempConstArray[1].setFConst(-invDet * m01);
1325 tempConstArray[2].setFConst(-invDet * m10);
1326 tempConstArray[3].setFConst( invDet * m00);
1327 }
1328 break;
1329 case 3:
1330 {
1331 float m00 = unionArray[0].getFConst(); // Matrix is:
1332 float m01 = unionArray[1].getFConst(); // (m00, m01, m02)
1333 float m02 = unionArray[2].getFConst(); // (m10, m11, m12)
1334 float m10 = unionArray[3].getFConst(); // (m20, m21, m22)
1335 float m11 = unionArray[4].getFConst();
1336 float m12 = unionArray[5].getFConst();
1337 float m20 = unionArray[6].getFConst();
1338 float m21 = unionArray[7].getFConst();
1339 float m22 = unionArray[8].getFConst();
1340 tempConstArray[0].setFConst(invDet * determinant2(m11, m12, m21, m22)); // m00 = invDet * (m11 * m22 - m12 * m21)
1341 tempConstArray[1].setFConst(invDet * determinant2(m12, m10, m22, m20)); // m01 = -invDet * (m10 * m22 - m12 * m20)
1342 tempConstArray[2].setFConst(invDet * determinant2(m10, m11, m20, m21)); // m02 = invDet * (m10 * m21 - m11 * m20)
1343 tempConstArray[3].setFConst(invDet * determinant2(m21, m22, m01, m02)); // m10 = -invDet * (m01 * m22 - m02 * m21)
1344 tempConstArray[4].setFConst(invDet * determinant2(m00, m02, m20, m22)); // m11 = invDet * (m00 * m22 - m02 * m20)
1345 tempConstArray[5].setFConst(invDet * determinant2(m20, m21, m00, m01)); // m12 = -invDet * (m00 * m21 - m01 * m20)
1346 tempConstArray[6].setFConst(invDet * determinant2(m01, m02, m11, m12)); // m20 = invDet * (m01 * m12 - m02 * m11)
1347 tempConstArray[7].setFConst(invDet * determinant2(m10, m12, m00, m02)); // m21 = -invDet * (m00 * m12 - m02 * m10)
1348 tempConstArray[8].setFConst(invDet * determinant2(m00, m01, m10, m11)); // m22 = invDet * (m00 * m11 - m01 * m10)
1349 }
1350 break;
1351 case 4:
1352 {
1353 float m00 = unionArray[0].getFConst(); // Matrix is:
1354 float m01 = unionArray[1].getFConst(); // (m00, m01, m02, m03)
1355 float m02 = unionArray[2].getFConst(); // (m10, m11, m12, m13)
1356 float m03 = unionArray[3].getFConst(); // (m20, m21, m22, m23)
1357 float m10 = unionArray[4].getFConst(); // (m30, m31, m32, m33)
1358 float m11 = unionArray[5].getFConst();
1359 float m12 = unionArray[6].getFConst();
1360 float m13 = unionArray[7].getFConst();
1361 float m20 = unionArray[8].getFConst();
1362 float m21 = unionArray[9].getFConst();
1363 float m22 = unionArray[10].getFConst();
1364 float m23 = unionArray[11].getFConst();
1365 float m30 = unionArray[12].getFConst();
1366 float m31 = unionArray[13].getFConst();
1367 float m32 = unionArray[14].getFConst();
1368 float m33 = unionArray[15].getFConst();
1369 tempConstArray[ 0].setFConst( invDet * determinant3(m11, m12, m13, m21, m22, m23, m31, m32, m33)); // m00
1370 tempConstArray[ 1].setFConst(-invDet * determinant3(m10, m12, m13, m20, m22, m23, m30, m32, m33)); // m01
1371 tempConstArray[ 2].setFConst( invDet * determinant3(m10, m11, m13, m20, m21, m23, m30, m31, m33)); // m02
1372 tempConstArray[ 3].setFConst(-invDet * determinant3(m10, m11, m12, m20, m21, m22, m30, m31, m32)); // m03
1373 tempConstArray[ 4].setFConst( invDet * determinant3(m01, m02, m03, m21, m22, m23, m31, m32, m33)); // m10
1374 tempConstArray[ 5].setFConst(-invDet * determinant3(m00, m02, m03, m20, m22, m23, m30, m32, m33)); // m11
1375 tempConstArray[ 6].setFConst( invDet * determinant3(m00, m01, m03, m20, m21, m23, m30, m31, m33)); // m12
1376 tempConstArray[ 7].setFConst(-invDet * determinant3(m00, m01, m02, m20, m21, m22, m30, m31, m32)); // m13
1377 tempConstArray[ 8].setFConst( invDet * determinant3(m01, m02, m03, m11, m12, m13, m31, m32, m33)); // m20
1378 tempConstArray[ 9].setFConst(-invDet * determinant3(m00, m02, m03, m10, m12, m13, m30, m32, m33)); // m21
1379 tempConstArray[10].setFConst( invDet * determinant3(m00, m01, m03, m10, m11, m13, m30, m31, m33)); // m22
1380 tempConstArray[11].setFConst(-invDet * determinant3(m00, m01, m02, m10, m11, m12, m30, m31, m32)); // m23
1381 tempConstArray[12].setFConst( invDet * determinant3(m01, m02, m03, m11, m12, m13, m21, m22, m23)); // m30
1382 tempConstArray[13].setFConst(-invDet * determinant3(m00, m02, m03, m10, m12, m13, m20, m22, m23)); // m31
1383 tempConstArray[14].setFConst( invDet * determinant3(m00, m01, m03, m10, m11, m13, m20, m21, m23)); // m32
1384 tempConstArray[15].setFConst(-invDet * determinant3(m00, m01, m02, m10, m11, m12, m20, m21, m22)); // m33
1385 }
1386 break;
1387 default:
Nicolas Capens3713cd42015-06-22 10:41:54 -04001388 UNREACHABLE(size);
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001389 }
1390 }
1391 return tempConstArray;
1392}
1393
John Bauman66b8ab22014-05-06 15:57:45 -04001394//
1395// The fold functions see if an operation on a constant can be done in place,
1396// without generating run-time code.
1397//
1398// Returns the node to keep using, which may or may not be the node passed in.
1399//
1400
1401TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNode, TInfoSink& infoSink)
1402{
Nicolas Capens0bac2852016-05-07 06:09:58 -04001403 ConstantUnion *unionArray = getUnionArrayPointer();
1404 size_t objectSize = getType().getObjectSize();
John Bauman66b8ab22014-05-06 15:57:45 -04001405
Nicolas Capens0bac2852016-05-07 06:09:58 -04001406 if (constantNode) { // binary operations
1407 TIntermConstantUnion *node = constantNode->getAsConstantUnion();
1408 ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
1409 TType returnType = getType();
John Bauman66b8ab22014-05-06 15:57:45 -04001410
Nicolas Capens0bac2852016-05-07 06:09:58 -04001411 // for a case like float f = 1.2 + vec4(2,3,4,5);
1412 if (constantNode->getType().getObjectSize() == 1 && objectSize > 1) {
1413 rightUnionArray = new ConstantUnion[objectSize];
1414 for (size_t i = 0; i < objectSize; ++i)
1415 rightUnionArray[i] = *node->getUnionArrayPointer();
1416 returnType = getType();
1417 } else if (constantNode->getType().getObjectSize() > 1 && objectSize == 1) {
1418 // for a case like float f = vec4(2,3,4,5) + 1.2;
1419 unionArray = new ConstantUnion[constantNode->getType().getObjectSize()];
1420 for (size_t i = 0; i < constantNode->getType().getObjectSize(); ++i)
1421 unionArray[i] = *getUnionArrayPointer();
1422 returnType = node->getType();
1423 objectSize = constantNode->getType().getObjectSize();
1424 }
John Bauman66b8ab22014-05-06 15:57:45 -04001425
Nicolas Capens0bac2852016-05-07 06:09:58 -04001426 ConstantUnion* tempConstArray = 0;
1427 TIntermConstantUnion *tempNode;
John Bauman66b8ab22014-05-06 15:57:45 -04001428
Nicolas Capens0bac2852016-05-07 06:09:58 -04001429 switch(op) {
1430 case EOpAdd:
1431 tempConstArray = new ConstantUnion[objectSize];
1432 {// support MSVC++6.0
1433 for (size_t i = 0; i < objectSize; i++)
1434 tempConstArray[i] = unionArray[i] + rightUnionArray[i];
1435 }
1436 break;
1437 case EOpSub:
1438 tempConstArray = new ConstantUnion[objectSize];
1439 {// support MSVC++6.0
1440 for (size_t i = 0; i < objectSize; i++)
1441 tempConstArray[i] = unionArray[i] - rightUnionArray[i];
1442 }
1443 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001444
Nicolas Capens0bac2852016-05-07 06:09:58 -04001445 case EOpMul:
1446 case EOpVectorTimesScalar:
1447 case EOpMatrixTimesScalar:
1448 tempConstArray = new ConstantUnion[objectSize];
1449 {// support MSVC++6.0
1450 for (size_t i = 0; i < objectSize; i++)
1451 tempConstArray[i] = unionArray[i] * rightUnionArray[i];
1452 }
1453 break;
1454 case EOpMatrixTimesMatrix:
1455 if (getType().getBasicType() != EbtFloat || node->getBasicType() != EbtFloat) {
1456 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix multiply", getLine());
1457 return 0;
1458 }
1459 {// support MSVC++6.0
1460 int leftNumCols = getNominalSize();
1461 int leftNumRows = getSecondarySize();
1462 int rightNumCols = node->getNominalSize();
1463 int rightNumRows = node->getSecondarySize();
1464 if(leftNumCols != rightNumRows) {
1465 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix multiply", getLine());
1466 return 0;
1467 }
1468 int tempNumCols = rightNumCols;
1469 int tempNumRows = leftNumRows;
1470 int tempNumAdds = leftNumCols;
1471 tempConstArray = new ConstantUnion[tempNumCols*tempNumRows];
1472 for (int row = 0; row < tempNumRows; row++) {
1473 for (int column = 0; column < tempNumCols; column++) {
1474 tempConstArray[tempNumRows * column + row].setFConst(0.0f);
1475 for (int i = 0; i < tempNumAdds; i++) {
1476 tempConstArray[tempNumRows * column + row].setFConst(tempConstArray[tempNumRows * column + row].getFConst() + unionArray[i * leftNumRows + row].getFConst() * (rightUnionArray[column * rightNumRows + i].getFConst()));
1477 }
1478 }
1479 }
1480 // update return type for matrix product
1481 returnType.setNominalSize(static_cast<unsigned char>(tempNumCols));
1482 returnType.setSecondarySize(static_cast<unsigned char>(tempNumRows));
1483 }
1484 break;
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001485
1486 case EOpOuterProduct:
1487 {
1488 int leftSize = getNominalSize();
1489 int rightSize = node->getNominalSize();
1490 tempConstArray = new ConstantUnion[leftSize*rightSize];
1491 for(int row = 0; row < leftSize; row++) {
1492 for(int column = 0; column < rightSize; column++) {
1493 tempConstArray[leftSize * column + row].setFConst(unionArray[row].getFConst() * rightUnionArray[column].getFConst());
1494 }
1495 }
1496 // update return type for outer product
1497 returnType.setNominalSize(static_cast<unsigned char>(rightSize));
1498 returnType.setSecondarySize(static_cast<unsigned char>(leftSize));
1499 }
1500 break;
1501
1502 case EOpTranspose:
1503 {
1504 int rightCol = node->getNominalSize();
1505 int rightRow = node->getSecondarySize();
1506 tempConstArray = new ConstantUnion[rightCol*rightRow];
1507 for(int row = 0; row < rightRow; row++) {
1508 for(int column = 0; column < rightCol; column++) {
1509 tempConstArray[rightRow * column + row].setFConst(rightUnionArray[rightCol * row + column].getFConst());
1510 }
1511 }
1512 // update return type for transpose
1513 returnType.setNominalSize(static_cast<unsigned char>(rightRow));
1514 returnType.setSecondarySize(static_cast<unsigned char>(rightCol));
1515 }
1516 break;
1517
1518 case EOpDeterminant:
1519 {
1520 ASSERT(node->getNominalSize() == node->getSecondarySize());
1521
1522 tempConstArray = new ConstantUnion[1];
1523 tempConstArray[0].setFConst(ComputeDeterminant(node->getNominalSize(), rightUnionArray));
1524 // update return type for determinant
1525 returnType.setNominalSize(1);
1526 returnType.setSecondarySize(1);
1527 }
1528 break;
1529
1530 case EOpInverse:
1531 {
1532 ASSERT(node->getNominalSize() == node->getSecondarySize());
1533
1534 tempConstArray = CreateInverse(node, rightUnionArray);
1535 if(!tempConstArray)
1536 {
1537 // Singular matrix, just copy
1538 tempConstArray = new ConstantUnion[objectSize];
Alexis Hetuab752792016-04-21 16:11:31 -04001539 for(size_t i = 0; i < objectSize; i++)
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001540 tempConstArray[i] = rightUnionArray[i];
1541 }
1542 }
1543 break;
1544
Nicolas Capens0bac2852016-05-07 06:09:58 -04001545 case EOpDiv:
1546 case EOpIMod:
Nicolas Capens5e0c3542016-04-05 17:18:24 -04001547 tempConstArray = new ConstantUnion[objectSize];
Nicolas Capens0bac2852016-05-07 06:09:58 -04001548 {// support MSVC++6.0
1549 for (size_t i = 0; i < objectSize; i++) {
1550 switch (getType().getBasicType()) {
1551 case EbtFloat:
1552 if (rightUnionArray[i] == 0.0f) {
1553 infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
1554 tempConstArray[i].setFConst(FLT_MAX);
1555 } else {
1556 ASSERT(op == EOpDiv);
1557 tempConstArray[i].setFConst(unionArray[i].getFConst() / rightUnionArray[i].getFConst());
1558 }
1559 break;
1560
1561 case EbtInt:
1562 if (rightUnionArray[i] == 0) {
1563 infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
1564 tempConstArray[i].setIConst(INT_MAX);
1565 } else {
1566 if(op == EOpDiv) {
1567 tempConstArray[i].setIConst(unionArray[i].getIConst() / rightUnionArray[i].getIConst());
1568 } else {
1569 ASSERT(op == EOpIMod);
1570 tempConstArray[i].setIConst(unionArray[i].getIConst() % rightUnionArray[i].getIConst());
1571 }
1572 }
1573 break;
1574 case EbtUInt:
1575 if (rightUnionArray[i] == 0) {
1576 infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
1577 tempConstArray[i].setUConst(UINT_MAX);
1578 } else {
1579 if(op == EOpDiv) {
1580 tempConstArray[i].setUConst(unionArray[i].getUConst() / rightUnionArray[i].getUConst());
1581 } else {
1582 ASSERT(op == EOpIMod);
1583 tempConstArray[i].setUConst(unionArray[i].getUConst() % rightUnionArray[i].getUConst());
1584 }
1585 }
1586 break;
1587 default:
1588 infoSink.info.message(EPrefixInternalError, "Constant folding cannot be done for \"/\"", getLine());
1589 return 0;
1590 }
1591 }
1592 }
1593 break;
1594
1595 case EOpMatrixTimesVector:
1596 if (node->getBasicType() != EbtFloat) {
1597 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix times vector", getLine());
1598 return 0;
1599 }
1600 tempConstArray = new ConstantUnion[getNominalSize()];
1601
1602 {// support MSVC++6.0
1603 for (int size = getNominalSize(), i = 0; i < size; i++) {
1604 tempConstArray[i].setFConst(0.0f);
1605 for (int j = 0; j < size; j++) {
1606 tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j*size + i].getFConst()) * rightUnionArray[j].getFConst()));
1607 }
1608 }
1609 }
1610
1611 tempNode = new TIntermConstantUnion(tempConstArray, node->getType());
1612 tempNode->setLine(getLine());
1613
1614 return tempNode;
1615
1616 case EOpVectorTimesMatrix:
1617 if (getType().getBasicType() != EbtFloat) {
1618 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for vector times matrix", getLine());
1619 return 0;
1620 }
1621
1622 tempConstArray = new ConstantUnion[getNominalSize()];
1623 {// support MSVC++6.0
1624 for (int size = getNominalSize(), i = 0; i < size; i++) {
1625 tempConstArray[i].setFConst(0.0f);
1626 for (int j = 0; j < size; j++) {
1627 tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j].getFConst()) * rightUnionArray[i*size + j].getFConst()));
1628 }
1629 }
1630 }
1631 break;
1632
1633 case EOpLogicalAnd: // this code is written for possible future use, will not get executed currently
1634 tempConstArray = new ConstantUnion[objectSize];
1635 {// support MSVC++6.0
1636 for (size_t i = 0; i < objectSize; i++)
1637 tempConstArray[i] = unionArray[i] && rightUnionArray[i];
1638 }
1639 break;
1640
1641 case EOpLogicalOr: // this code is written for possible future use, will not get executed currently
1642 tempConstArray = new ConstantUnion[objectSize];
1643 {// support MSVC++6.0
1644 for (size_t i = 0; i < objectSize; i++)
1645 tempConstArray[i] = unionArray[i] || rightUnionArray[i];
1646 }
1647 break;
1648
1649 case EOpLogicalXor:
1650 tempConstArray = new ConstantUnion[objectSize];
1651 {// support MSVC++6.0
1652 for (size_t i = 0; i < objectSize; i++)
1653 switch (getType().getBasicType()) {
1654 case EbtBool: tempConstArray[i].setBConst((unionArray[i] == rightUnionArray[i]) ? false : true); break;
1655 default: assert(false && "Default missing");
1656 }
1657 }
1658 break;
1659
1660 case EOpBitwiseAnd:
1661 tempConstArray = new ConstantUnion[objectSize];
1662 for(size_t i = 0; i < objectSize; i++)
1663 tempConstArray[i] = unionArray[i] & rightUnionArray[i];
1664 break;
1665 case EOpBitwiseXor:
1666 tempConstArray = new ConstantUnion[objectSize];
1667 for(size_t i = 0; i < objectSize; i++)
1668 tempConstArray[i] = unionArray[i] ^ rightUnionArray[i];
1669 break;
1670 case EOpBitwiseOr:
1671 tempConstArray = new ConstantUnion[objectSize];
1672 for(size_t i = 0; i < objectSize; i++)
1673 tempConstArray[i] = unionArray[i] | rightUnionArray[i];
1674 break;
1675 case EOpBitShiftLeft:
1676 tempConstArray = new ConstantUnion[objectSize];
1677 for(size_t i = 0; i < objectSize; i++)
1678 tempConstArray[i] = unionArray[i] << rightUnionArray[i];
1679 break;
1680 case EOpBitShiftRight:
1681 tempConstArray = new ConstantUnion[objectSize];
1682 for(size_t i = 0; i < objectSize; i++)
1683 tempConstArray[i] = unionArray[i] >> rightUnionArray[i];
1684 break;
1685
1686 case EOpLessThan:
1687 tempConstArray = new ConstantUnion[objectSize];
1688 for(size_t i = 0; i < objectSize; i++)
1689 tempConstArray[i].setBConst(unionArray[i] < rightUnionArray[i]);
1690 returnType = TType(EbtBool, EbpUndefined, EvqConstExpr, objectSize);
1691 break;
1692 case EOpGreaterThan:
1693 tempConstArray = new ConstantUnion[objectSize];
1694 for(size_t i = 0; i < objectSize; i++)
Nicolas Capens5e0c3542016-04-05 17:18:24 -04001695 tempConstArray[i].setBConst(unionArray[i] > rightUnionArray[i]);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001696 returnType = TType(EbtBool, EbpUndefined, EvqConstExpr, objectSize);
1697 break;
1698 case EOpLessThanEqual:
1699 tempConstArray = new ConstantUnion[objectSize];
1700 for(size_t i = 0; i < objectSize; i++)
Nicolas Capens5e0c3542016-04-05 17:18:24 -04001701 tempConstArray[i].setBConst(unionArray[i] <= rightUnionArray[i]);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001702 returnType = TType(EbtBool, EbpUndefined, EvqConstExpr, objectSize);
1703 break;
1704 case EOpGreaterThanEqual:
1705 tempConstArray = new ConstantUnion[objectSize];
1706 for(size_t i = 0; i < objectSize; i++)
Nicolas Capens5e0c3542016-04-05 17:18:24 -04001707 tempConstArray[i].setBConst(unionArray[i] >= rightUnionArray[i]);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001708 returnType = TType(EbtBool, EbpUndefined, EvqConstExpr, objectSize);
1709 break;
1710 case EOpEqual:
Alexis Hetu26ea8f52016-04-28 12:45:48 -04001711 tempConstArray = new ConstantUnion[1];
1712
1713 if(getType().getBasicType() == EbtStruct) {
1714 tempConstArray->setBConst(CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray));
Nicolas Capens0bac2852016-05-07 06:09:58 -04001715 } else {
Alexis Hetu26ea8f52016-04-28 12:45:48 -04001716 bool boolNodeFlag = true;
Nicolas Capens0bac2852016-05-07 06:09:58 -04001717 for (size_t i = 0; i < objectSize; i++) {
1718 if (unionArray[i] != rightUnionArray[i]) {
1719 boolNodeFlag = false;
1720 break; // break out of for loop
1721 }
1722 }
Alexis Hetu26ea8f52016-04-28 12:45:48 -04001723 tempConstArray->setBConst(boolNodeFlag);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001724 }
John Bauman66b8ab22014-05-06 15:57:45 -04001725
Nicolas Capens0bac2852016-05-07 06:09:58 -04001726 tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConstExpr));
1727 tempNode->setLine(getLine());
John Bauman66b8ab22014-05-06 15:57:45 -04001728
Nicolas Capens0bac2852016-05-07 06:09:58 -04001729 return tempNode;
John Bauman66b8ab22014-05-06 15:57:45 -04001730
Nicolas Capens0bac2852016-05-07 06:09:58 -04001731 case EOpNotEqual:
Alexis Hetu26ea8f52016-04-28 12:45:48 -04001732 tempConstArray = new ConstantUnion[1];
1733
1734 if(getType().getBasicType() == EbtStruct) {
1735 tempConstArray->setBConst(!CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray));
Nicolas Capens0bac2852016-05-07 06:09:58 -04001736 } else {
Alexis Hetu26ea8f52016-04-28 12:45:48 -04001737 bool boolNodeFlag = false;
Nicolas Capens0bac2852016-05-07 06:09:58 -04001738 for (size_t i = 0; i < objectSize; i++) {
1739 if (unionArray[i] != rightUnionArray[i]) {
1740 boolNodeFlag = true;
1741 break; // break out of for loop
1742 }
1743 }
Alexis Hetu26ea8f52016-04-28 12:45:48 -04001744 tempConstArray->setBConst(boolNodeFlag);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001745 }
John Bauman66b8ab22014-05-06 15:57:45 -04001746
Nicolas Capens0bac2852016-05-07 06:09:58 -04001747 tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConstExpr));
1748 tempNode->setLine(getLine());
John Bauman66b8ab22014-05-06 15:57:45 -04001749
Nicolas Capens0bac2852016-05-07 06:09:58 -04001750 return tempNode;
Nicolas Capens91dfb972016-04-09 23:45:12 -04001751 case EOpMax:
Nicolas Capens0bac2852016-05-07 06:09:58 -04001752 tempConstArray = new ConstantUnion[objectSize];
1753 {// support MSVC++6.0
1754 for (size_t i = 0; i < objectSize; i++)
1755 tempConstArray[i] = unionArray[i] > rightUnionArray[i] ? unionArray[i] : rightUnionArray[i];
1756 }
1757 break;
1758 case EOpMin:
1759 tempConstArray = new ConstantUnion[objectSize];
1760 {// support MSVC++6.0
1761 for (size_t i = 0; i < objectSize; i++)
1762 tempConstArray[i] = unionArray[i] < rightUnionArray[i] ? unionArray[i] : rightUnionArray[i];
1763 }
1764 break;
1765 default:
1766 return 0;
1767 }
1768 tempNode = new TIntermConstantUnion(tempConstArray, returnType);
1769 tempNode->setLine(getLine());
John Bauman66b8ab22014-05-06 15:57:45 -04001770
Nicolas Capens0bac2852016-05-07 06:09:58 -04001771 return tempNode;
1772 } else {
1773 //
1774 // Do unary operations
1775 //
1776 TIntermConstantUnion *newNode = 0;
1777 ConstantUnion* tempConstArray = new ConstantUnion[objectSize];
1778 for (size_t i = 0; i < objectSize; i++) {
1779 switch(op) {
1780 case EOpNegative:
1781 switch (getType().getBasicType()) {
1782 case EbtFloat: tempConstArray[i].setFConst(-unionArray[i].getFConst()); break;
1783 case EbtInt: tempConstArray[i].setIConst(-unionArray[i].getIConst()); break;
1784 default:
1785 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1786 return 0;
1787 }
1788 break;
1789 case EOpLogicalNot: // this code is written for possible future use, will not get executed currently
1790 switch (getType().getBasicType()) {
1791 case EbtBool: tempConstArray[i].setBConst(!unionArray[i].getBConst()); break;
1792 default:
1793 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1794 return 0;
1795 }
1796 break;
1797 case EOpBitwiseNot:
1798 switch(getType().getBasicType()) {
1799 case EbtInt: tempConstArray[i].setIConst(~unionArray[i].getIConst()); break;
1800 case EbtUInt: tempConstArray[i].setUConst(~unionArray[i].getUConst()); break;
1801 default:
1802 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1803 return 0;
1804 }
1805 break;
Alexis Hetu6c6b4702016-04-26 16:30:22 -04001806 case EOpRadians:
1807 switch(getType().getBasicType()) {
1808 case EbtFloat: tempConstArray[i].setFConst(unionArray[i].getFConst() * 1.74532925e-2f); break;
1809 default:
1810 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1811 return 0;
1812 }
1813 break;
1814 case EOpDegrees:
1815 switch(getType().getBasicType()) {
1816 case EbtFloat: tempConstArray[i].setFConst(unionArray[i].getFConst() * 5.72957795e+1f); break;
1817 default:
1818 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1819 return 0;
1820 }
1821 break;
1822 case EOpSin:
1823 switch(getType().getBasicType()) {
1824 case EbtFloat: tempConstArray[i].setFConst(sinf(unionArray[i].getFConst())); break;
1825 default:
1826 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1827 return 0;
1828 }
1829 break;
1830 case EOpCos:
1831 switch(getType().getBasicType()) {
1832 case EbtFloat: tempConstArray[i].setFConst(cosf(unionArray[i].getFConst())); break;
1833 default:
1834 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1835 return 0;
1836 }
1837 break;
1838 case EOpTan:
1839 switch(getType().getBasicType()) {
1840 case EbtFloat: tempConstArray[i].setFConst(tanf(unionArray[i].getFConst())); break;
1841 default:
1842 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1843 return 0;
1844 }
1845 break;
1846 case EOpAsin:
1847 switch(getType().getBasicType()) {
1848 case EbtFloat: tempConstArray[i].setFConst(asinf(unionArray[i].getFConst())); break;
1849 default:
1850 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1851 return 0;
1852 }
1853 break;
1854 case EOpAcos:
1855 switch(getType().getBasicType()) {
1856 case EbtFloat: tempConstArray[i].setFConst(acosf(unionArray[i].getFConst())); break;
1857 default:
1858 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1859 return 0;
1860 }
1861 break;
1862 case EOpAtan:
1863 switch(getType().getBasicType()) {
1864 case EbtFloat: tempConstArray[i].setFConst(atanf(unionArray[i].getFConst())); break;
1865 default:
1866 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1867 return 0;
1868 }
1869 break;
1870 case EOpSinh:
1871 switch(getType().getBasicType()) {
1872 case EbtFloat: tempConstArray[i].setFConst(sinhf(unionArray[i].getFConst())); break;
1873 default:
1874 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1875 return 0;
1876 }
1877 break;
1878 case EOpCosh:
1879 switch(getType().getBasicType()) {
1880 case EbtFloat: tempConstArray[i].setFConst(coshf(unionArray[i].getFConst())); break;
1881 default:
1882 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1883 return 0;
1884 }
1885 break;
1886 case EOpTanh:
1887 switch(getType().getBasicType()) {
1888 case EbtFloat: tempConstArray[i].setFConst(tanhf(unionArray[i].getFConst())); break;
1889 default:
1890 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1891 return 0;
1892 }
1893 break;
1894 case EOpAsinh:
1895 switch(getType().getBasicType()) {
1896 case EbtFloat: tempConstArray[i].setFConst(asinhf(unionArray[i].getFConst())); break;
1897 default:
1898 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1899 return 0;
1900 }
1901 break;
1902 case EOpAcosh:
1903 switch(getType().getBasicType()) {
1904 case EbtFloat: tempConstArray[i].setFConst(acoshf(unionArray[i].getFConst())); break;
1905 default:
1906 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1907 return 0;
1908 }
1909 break;
1910 case EOpAtanh:
1911 switch(getType().getBasicType()) {
1912 case EbtFloat: tempConstArray[i].setFConst(atanhf(unionArray[i].getFConst())); break;
1913 default:
1914 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1915 return 0;
1916 }
1917 break;
1918 case EOpLog:
1919 switch(getType().getBasicType()) {
1920 case EbtFloat: tempConstArray[i].setFConst(logf(unionArray[i].getFConst())); break;
1921 default:
1922 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1923 return 0;
1924 }
1925 break;
1926 case EOpLog2:
1927 switch(getType().getBasicType()) {
Alexis Hetu2ce222c2016-05-02 11:20:52 -04001928 case EbtFloat: tempConstArray[i].setFConst(sw::log2(unionArray[i].getFConst())); break;
Alexis Hetu6c6b4702016-04-26 16:30:22 -04001929 default:
1930 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1931 return 0;
1932 }
1933 break;
1934 case EOpExp:
1935 switch(getType().getBasicType()) {
1936 case EbtFloat: tempConstArray[i].setFConst(expf(unionArray[i].getFConst())); break;
1937 default:
1938 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1939 return 0;
1940 }
1941 break;
1942 case EOpExp2:
1943 switch(getType().getBasicType()) {
1944 case EbtFloat: tempConstArray[i].setFConst(exp2f(unionArray[i].getFConst())); break;
1945 default:
1946 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1947 return 0;
1948 }
1949 break;
1950 case EOpSqrt:
1951 switch(getType().getBasicType()) {
1952 case EbtFloat: tempConstArray[i].setFConst(sqrtf(unionArray[i].getFConst())); break;
1953 default:
1954 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1955 return 0;
1956 }
1957 break;
1958 case EOpInverseSqrt:
1959 switch(getType().getBasicType()) {
1960 case EbtFloat: tempConstArray[i].setFConst(1.0f / sqrtf(unionArray[i].getFConst())); break;
1961 default:
1962 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1963 return 0;
1964 }
1965 break;
1966 default:
Nicolas Capens0bac2852016-05-07 06:09:58 -04001967 return 0;
1968 }
1969 }
1970 newNode = new TIntermConstantUnion(tempConstArray, getType());
1971 newNode->setLine(getLine());
1972 return newNode;
1973 }
John Bauman66b8ab22014-05-06 15:57:45 -04001974}
1975
1976TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermConstantUnion* node)
1977{
Nicolas Capens0bac2852016-05-07 06:09:58 -04001978 size_t size = node->getType().getObjectSize();
John Bauman66b8ab22014-05-06 15:57:45 -04001979
Nicolas Capens0bac2852016-05-07 06:09:58 -04001980 ConstantUnion *leftUnionArray = new ConstantUnion[size];
John Bauman66b8ab22014-05-06 15:57:45 -04001981
Nicolas Capens0bac2852016-05-07 06:09:58 -04001982 for(size_t i = 0; i < size; i++) {
1983 switch (promoteTo) {
1984 case EbtFloat:
1985 switch (node->getType().getBasicType()) {
1986 case EbtInt:
1987 leftUnionArray[i].setFConst(static_cast<float>(node->getIConst(i)));
1988 break;
1989 case EbtUInt:
1990 leftUnionArray[i].setFConst(static_cast<float>(node->getUConst(i)));
1991 break;
1992 case EbtBool:
1993 leftUnionArray[i].setFConst(static_cast<float>(node->getBConst(i)));
1994 break;
1995 case EbtFloat:
1996 leftUnionArray[i].setFConst(static_cast<float>(node->getFConst(i)));
1997 break;
1998 default:
1999 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
2000 return 0;
2001 }
2002 break;
2003 case EbtInt:
2004 switch (node->getType().getBasicType()) {
2005 case EbtInt:
2006 leftUnionArray[i].setIConst(static_cast<int>(node->getIConst(i)));
2007 break;
2008 case EbtUInt:
2009 leftUnionArray[i].setIConst(static_cast<int>(node->getUConst(i)));
2010 break;
2011 case EbtBool:
2012 leftUnionArray[i].setIConst(static_cast<int>(node->getBConst(i)));
2013 break;
2014 case EbtFloat:
2015 leftUnionArray[i].setIConst(static_cast<int>(node->getFConst(i)));
2016 break;
2017 default:
2018 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
2019 return 0;
2020 }
2021 break;
2022 case EbtUInt:
2023 switch (node->getType().getBasicType()) {
2024 case EbtInt:
2025 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getIConst(i)));
2026 break;
2027 case EbtUInt:
2028 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getUConst(i)));
2029 break;
2030 case EbtBool:
2031 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getBConst(i)));
2032 break;
2033 case EbtFloat:
2034 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getFConst(i)));
2035 break;
2036 default:
2037 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
2038 return 0;
2039 }
2040 break;
2041 case EbtBool:
2042 switch (node->getType().getBasicType()) {
2043 case EbtInt:
2044 leftUnionArray[i].setBConst(node->getIConst(i) != 0);
2045 break;
2046 case EbtUInt:
2047 leftUnionArray[i].setBConst(node->getUConst(i) != 0);
2048 break;
2049 case EbtBool:
2050 leftUnionArray[i].setBConst(node->getBConst(i));
2051 break;
2052 case EbtFloat:
2053 leftUnionArray[i].setBConst(node->getFConst(i) != 0.0f);
2054 break;
2055 default:
2056 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
2057 return 0;
2058 }
John Bauman66b8ab22014-05-06 15:57:45 -04002059
Nicolas Capens0bac2852016-05-07 06:09:58 -04002060 break;
2061 default:
2062 infoSink.info.message(EPrefixInternalError, "Incorrect data type found", node->getLine());
2063 return 0;
2064 }
John Bauman66b8ab22014-05-06 15:57:45 -04002065
Nicolas Capens0bac2852016-05-07 06:09:58 -04002066 }
John Bauman66b8ab22014-05-06 15:57:45 -04002067
Nicolas Capens0bac2852016-05-07 06:09:58 -04002068 const TType& t = node->getType();
John Bauman66b8ab22014-05-06 15:57:45 -04002069
Alexis Hetub14178b2015-04-13 13:23:20 -04002070 return addConstantUnion(leftUnionArray, TType(promoteTo, t.getPrecision(), t.getQualifier(), t.getNominalSize(), t.getSecondarySize(), t.isArray()), node->getLine());
John Bauman66b8ab22014-05-06 15:57:45 -04002071}
2072