blob: ee77a2fbf5e6977894024a4be5ba62ce4b4e7a31 [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))
Nicolas Capensaa028482018-01-26 01:35:42 +0000405 {
406 delete node;
Nicolas Capens0bac2852016-05-07 06:09:58 -0400407 return 0;
Nicolas Capensaa028482018-01-26 01:35:42 +0000408 }
John Bauman66b8ab22014-05-06 15:57:45 -0400409
Nicolas Capens0bac2852016-05-07 06:09:58 -0400410 //
411 // See if we can fold constants.
412 //
413 TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion();
414 TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion();
415 if (leftTempConstant && rightTempConstant) {
416 TIntermTyped *typedReturnNode = leftTempConstant->fold(node->getOp(), rightTempConstant, infoSink);
John Bauman66b8ab22014-05-06 15:57:45 -0400417
Nicolas Capens0bac2852016-05-07 06:09:58 -0400418 if (typedReturnNode)
419 return typedReturnNode;
420 }
John Bauman66b8ab22014-05-06 15:57:45 -0400421
Nicolas Capens0bac2852016-05-07 06:09:58 -0400422 return node;
John Bauman66b8ab22014-05-06 15:57:45 -0400423}
424
425//
426// Connect two nodes through an assignment.
427//
428// Returns the added node.
429//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400430TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400431{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400432 if (left->getType().getStruct() || right->getType().getStruct())
433 {
434 if (left->getType() != right->getType())
435 {
436 return 0;
437 }
438 }
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400439
Nicolas Capens0bac2852016-05-07 06:09:58 -0400440 TIntermBinary* node = new TIntermBinary(op);
441 node->setLine(line);
John Bauman66b8ab22014-05-06 15:57:45 -0400442
Nicolas Capens0bac2852016-05-07 06:09:58 -0400443 node->setLeft(left);
444 node->setRight(right);
445 if (! node->promote(infoSink))
446 return 0;
John Bauman66b8ab22014-05-06 15:57:45 -0400447
Nicolas Capens0bac2852016-05-07 06:09:58 -0400448 return node;
John Bauman66b8ab22014-05-06 15:57:45 -0400449}
450
451//
452// Connect two nodes through an index operator, where the left node is the base
453// of an array or struct, and the right node is a direct or indirect offset.
454//
455// Returns the added node.
456// The caller should set the type of the returned node.
457//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400458TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400459{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400460 TIntermBinary* node = new TIntermBinary(op);
461 node->setLine(line);
462 node->setLeft(base);
463 node->setRight(index);
John Bauman66b8ab22014-05-06 15:57:45 -0400464
Nicolas Capens0bac2852016-05-07 06:09:58 -0400465 // caller should set the type
John Bauman66b8ab22014-05-06 15:57:45 -0400466
Nicolas Capens0bac2852016-05-07 06:09:58 -0400467 return node;
John Bauman66b8ab22014-05-06 15:57:45 -0400468}
469
470//
471// Add one node as the parent of another that it operates on.
472//
473// Returns the added node.
474//
Nicolas Capensd3d9b9c2016-04-10 01:53:59 -0400475TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermTyped* child, const TSourceLoc &line, const TType *funcReturnType)
John Bauman66b8ab22014-05-06 15:57:45 -0400476{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400477 if (child == 0) {
478 infoSink.info.message(EPrefixInternalError, "Bad type in AddUnaryMath", line);
479 return 0;
480 }
John Bauman66b8ab22014-05-06 15:57:45 -0400481
Nicolas Capens0bac2852016-05-07 06:09:58 -0400482 switch (op) {
483 case EOpBitwiseNot:
484 if (!IsInteger(child->getType().getBasicType()) || child->getType().isMatrix() || child->getType().isArray()) {
485 return 0;
486 }
487 break;
Alexis Hetud061e422015-05-13 16:37:50 -0400488
Nicolas Capens0bac2852016-05-07 06:09:58 -0400489 case EOpLogicalNot:
490 if (child->getType().getBasicType() != EbtBool || child->getType().isMatrix() || child->getType().isArray() || child->getType().isVector()) {
491 return 0;
492 }
493 break;
John Bauman66b8ab22014-05-06 15:57:45 -0400494
Nicolas Capens0bac2852016-05-07 06:09:58 -0400495 case EOpPostIncrement:
496 case EOpPreIncrement:
497 case EOpPostDecrement:
498 case EOpPreDecrement:
499 case EOpNegative:
500 if (child->getType().getBasicType() == EbtStruct || child->getType().isArray())
501 return 0;
502 default: break;
503 }
John Bauman66b8ab22014-05-06 15:57:45 -0400504
Nicolas Capens0bac2852016-05-07 06:09:58 -0400505 TIntermConstantUnion *childTempConstant = 0;
506 if (child->getAsConstantUnion())
507 childTempConstant = child->getAsConstantUnion();
John Bauman66b8ab22014-05-06 15:57:45 -0400508
Nicolas Capens0bac2852016-05-07 06:09:58 -0400509 //
510 // Make a new node for the operator.
511 //
512 TIntermUnary *node = new TIntermUnary(op);
513 node->setLine(line);
514 node->setOperand(child);
John Bauman66b8ab22014-05-06 15:57:45 -0400515
Nicolas Capens0bac2852016-05-07 06:09:58 -0400516 if (! node->promote(infoSink, funcReturnType))
517 return 0;
John Bauman66b8ab22014-05-06 15:57:45 -0400518
Nicolas Capens0bac2852016-05-07 06:09:58 -0400519 if (childTempConstant) {
520 TIntermTyped* newChild = childTempConstant->fold(op, 0, infoSink);
John Bauman66b8ab22014-05-06 15:57:45 -0400521
Nicolas Capens0bac2852016-05-07 06:09:58 -0400522 if (newChild)
523 return newChild;
524 }
John Bauman66b8ab22014-05-06 15:57:45 -0400525
Nicolas Capens0bac2852016-05-07 06:09:58 -0400526 return node;
John Bauman66b8ab22014-05-06 15:57:45 -0400527}
528
529//
530// This is the safe way to change the operator on an aggregate, as it
531// does lots of error checking and fixing. Especially for establishing
Nicolas Capens41320522018-06-06 13:47:19 -0400532// a function call's operation on its set of parameters. Sequences
533// of instructions are also aggregates, but they just directly set
John Bauman66b8ab22014-05-06 15:57:45 -0400534// their operator to EOpSequence.
535//
536// Returns an aggregate node, which could be the one passed in if
537// it was already an aggregate but no operator was set.
538//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400539TIntermAggregate* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator op, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400540{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400541 TIntermAggregate* aggNode;
John Bauman66b8ab22014-05-06 15:57:45 -0400542
Nicolas Capens0bac2852016-05-07 06:09:58 -0400543 //
544 // Make sure we have an aggregate. If not turn it into one.
545 //
546 if (node) {
547 aggNode = node->getAsAggregate();
548 if (aggNode == 0 || aggNode->getOp() != EOpNull) {
549 //
550 // Make an aggregate containing this node.
551 //
552 aggNode = new TIntermAggregate();
553 aggNode->getSequence().push_back(node);
554 }
555 } else
556 aggNode = new TIntermAggregate();
John Bauman66b8ab22014-05-06 15:57:45 -0400557
Nicolas Capens0bac2852016-05-07 06:09:58 -0400558 //
559 // Set the operator.
560 //
561 aggNode->setOp(op);
John Bauman66b8ab22014-05-06 15:57:45 -0400562
Nicolas Capens0bac2852016-05-07 06:09:58 -0400563 return aggNode;
John Bauman66b8ab22014-05-06 15:57:45 -0400564}
565
566//
John Bauman66b8ab22014-05-06 15:57:45 -0400567// Safe way to combine two nodes into an aggregate. Works with null pointers,
568// a node that's not a aggregate yet, etc.
569//
570// Returns the resulting aggregate, unless 0 was passed in for
571// both existing nodes.
572//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400573TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400574{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400575 if (left == 0 && right == 0)
576 return 0;
John Bauman66b8ab22014-05-06 15:57:45 -0400577
Nicolas Capens0bac2852016-05-07 06:09:58 -0400578 TIntermAggregate* aggNode = 0;
579 if (left)
580 aggNode = left->getAsAggregate();
581 if (!aggNode || aggNode->getOp() != EOpNull) {
582 aggNode = new TIntermAggregate;
583 if (left)
584 aggNode->getSequence().push_back(left);
585 }
John Bauman66b8ab22014-05-06 15:57:45 -0400586
Nicolas Capens0bac2852016-05-07 06:09:58 -0400587 if (right)
588 aggNode->getSequence().push_back(right);
John Bauman66b8ab22014-05-06 15:57:45 -0400589
Nicolas Capens0bac2852016-05-07 06:09:58 -0400590 aggNode->setLine(line);
John Bauman66b8ab22014-05-06 15:57:45 -0400591
Nicolas Capens0bac2852016-05-07 06:09:58 -0400592 return aggNode;
John Bauman66b8ab22014-05-06 15:57:45 -0400593}
594
595//
596// Turn an existing node into an aggregate.
597//
598// Returns an aggregate, unless 0 was passed in for the existing node.
599//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400600TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400601{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400602 if (node == 0)
603 return 0;
John Bauman66b8ab22014-05-06 15:57:45 -0400604
Nicolas Capens0bac2852016-05-07 06:09:58 -0400605 TIntermAggregate* aggNode = new TIntermAggregate;
606 aggNode->getSequence().push_back(node);
John Bauman66b8ab22014-05-06 15:57:45 -0400607
Nicolas Capens0bac2852016-05-07 06:09:58 -0400608 aggNode->setLine(line);
John Bauman66b8ab22014-05-06 15:57:45 -0400609
Nicolas Capens0bac2852016-05-07 06:09:58 -0400610 return aggNode;
John Bauman66b8ab22014-05-06 15:57:45 -0400611}
612
613//
614// For "if" test nodes. There are three children; a condition,
615// a true path, and a false path. The two paths are in the
616// nodePair.
617//
618// Returns the selection node created.
619//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400620TIntermNode* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nodePair, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400621{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400622 //
623 // For compile time constant selections, prune the code and
624 // test now.
625 //
John Bauman66b8ab22014-05-06 15:57:45 -0400626
Nicolas Capens0bac2852016-05-07 06:09:58 -0400627 if (cond->getAsTyped() && cond->getAsTyped()->getAsConstantUnion()) {
628 if (cond->getAsConstantUnion()->getBConst(0) == true)
629 return nodePair.node1 ? setAggregateOperator(nodePair.node1, EOpSequence, nodePair.node1->getLine()) : nullptr;
630 else
631 return nodePair.node2 ? setAggregateOperator(nodePair.node2, EOpSequence, nodePair.node2->getLine()) : nullptr;
632 }
John Bauman66b8ab22014-05-06 15:57:45 -0400633
Nicolas Capens0bac2852016-05-07 06:09:58 -0400634 TIntermSelection* node = new TIntermSelection(cond, nodePair.node1, nodePair.node2);
635 node->setLine(line);
John Bauman66b8ab22014-05-06 15:57:45 -0400636
Nicolas Capens0bac2852016-05-07 06:09:58 -0400637 return node;
John Bauman66b8ab22014-05-06 15:57:45 -0400638}
639
640
Alexis Hetu253fdd12015-07-07 15:12:46 -0400641TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400642{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400643 if (left->getType().getQualifier() == EvqConstExpr && right->getType().getQualifier() == EvqConstExpr) {
644 return right;
645 } else {
646 TIntermTyped *commaAggregate = growAggregate(left, right, line);
647 commaAggregate->getAsAggregate()->setOp(EOpComma);
648 commaAggregate->setType(right->getType());
649 commaAggregate->getTypePointer()->setQualifier(EvqTemporary);
650 return commaAggregate;
651 }
John Bauman66b8ab22014-05-06 15:57:45 -0400652}
653
654//
655// For "?:" test nodes. There are three children; a condition,
656// a true path, and a false path. The two paths are specified
657// as separate parameters.
658//
659// Returns the selection node created, or 0 if one could not be.
660//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400661TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400662{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400663 if (trueBlock->getType() != falseBlock->getType())
664 {
665 return 0;
666 }
John Bauman66b8ab22014-05-06 15:57:45 -0400667
Nicolas Capens0bac2852016-05-07 06:09:58 -0400668 //
669 // See if all the operands are constant, then fold it otherwise not.
670 //
John Bauman66b8ab22014-05-06 15:57:45 -0400671
Nicolas Capens0bac2852016-05-07 06:09:58 -0400672 if (cond->getAsConstantUnion() && trueBlock->getAsConstantUnion() && falseBlock->getAsConstantUnion()) {
673 if (cond->getAsConstantUnion()->getBConst(0))
674 return trueBlock;
675 else
676 return falseBlock;
677 }
John Bauman66b8ab22014-05-06 15:57:45 -0400678
Nicolas Capens0bac2852016-05-07 06:09:58 -0400679 //
680 // Make a selection node.
681 //
682 TIntermSelection* node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType());
683 node->getTypePointer()->setQualifier(EvqTemporary);
684 node->setLine(line);
John Bauman66b8ab22014-05-06 15:57:45 -0400685
Nicolas Capens0bac2852016-05-07 06:09:58 -0400686 return node;
John Bauman66b8ab22014-05-06 15:57:45 -0400687}
688
Alexis Hetu76a343a2015-06-04 17:21:22 -0400689TIntermSwitch *TIntermediate::addSwitch(TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &line)
690{
691 TIntermSwitch *node = new TIntermSwitch(init, statementList);
692 node->setLine(line);
693
694 return node;
695}
696
697TIntermCase *TIntermediate::addCase(TIntermTyped *condition, const TSourceLoc &line)
698{
699 TIntermCase *node = new TIntermCase(condition);
700 node->setLine(line);
701
702 return node;
703}
704
John Bauman66b8ab22014-05-06 15:57:45 -0400705//
706// Constant terminal nodes. Has a union that contains bool, float or int constants
707//
708// Returns the constant union node created.
709//
710
Alexis Hetu253fdd12015-07-07 15:12:46 -0400711TIntermConstantUnion* TIntermediate::addConstantUnion(ConstantUnion* unionArrayPointer, const TType& t, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400712{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400713 TIntermConstantUnion* node = new TIntermConstantUnion(unionArrayPointer, t);
714 node->setLine(line);
John Bauman66b8ab22014-05-06 15:57:45 -0400715
Nicolas Capens0bac2852016-05-07 06:09:58 -0400716 return node;
John Bauman66b8ab22014-05-06 15:57:45 -0400717}
718
Alexis Hetu253fdd12015-07-07 15:12:46 -0400719TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400720{
721
Nicolas Capens0bac2852016-05-07 06:09:58 -0400722 TIntermAggregate* node = new TIntermAggregate(EOpSequence);
John Bauman66b8ab22014-05-06 15:57:45 -0400723
Nicolas Capens0bac2852016-05-07 06:09:58 -0400724 node->setLine(line);
725 TIntermConstantUnion* constIntNode;
726 TIntermSequence &sequenceVector = node->getSequence();
727 ConstantUnion* unionArray;
John Bauman66b8ab22014-05-06 15:57:45 -0400728
Nicolas Capens0bac2852016-05-07 06:09:58 -0400729 for (int i = 0; i < fields.num; i++) {
730 unionArray = new ConstantUnion[1];
731 unionArray->setIConst(fields.offsets[i]);
732 constIntNode = addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConstExpr), line);
733 sequenceVector.push_back(constIntNode);
734 }
John Bauman66b8ab22014-05-06 15:57:45 -0400735
Nicolas Capens0bac2852016-05-07 06:09:58 -0400736 return node;
John Bauman66b8ab22014-05-06 15:57:45 -0400737}
738
739//
740// Create loop nodes.
741//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400742TIntermNode* TIntermediate::addLoop(TLoopType type, TIntermNode* init, TIntermTyped* cond, TIntermTyped* expr, TIntermNode* body, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400743{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400744 TIntermNode* node = new TIntermLoop(type, init, cond, expr, body);
745 node->setLine(line);
John Bauman66b8ab22014-05-06 15:57:45 -0400746
Nicolas Capens0bac2852016-05-07 06:09:58 -0400747 return node;
John Bauman66b8ab22014-05-06 15:57:45 -0400748}
749
750//
751// Add branches.
752//
Alexis Hetu253fdd12015-07-07 15:12:46 -0400753TIntermBranch* TIntermediate::addBranch(TOperator branchOp, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400754{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400755 return addBranch(branchOp, 0, line);
John Bauman66b8ab22014-05-06 15:57:45 -0400756}
757
Alexis Hetu253fdd12015-07-07 15:12:46 -0400758TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expression, const TSourceLoc &line)
John Bauman66b8ab22014-05-06 15:57:45 -0400759{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400760 TIntermBranch* node = new TIntermBranch(branchOp, expression);
761 node->setLine(line);
John Bauman66b8ab22014-05-06 15:57:45 -0400762
Nicolas Capens0bac2852016-05-07 06:09:58 -0400763 return node;
John Bauman66b8ab22014-05-06 15:57:45 -0400764}
765
766//
767// This is to be executed once the final root is put on top by the parsing
768// process.
769//
770bool TIntermediate::postProcess(TIntermNode* root)
771{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400772 if (root == 0)
773 return true;
John Bauman66b8ab22014-05-06 15:57:45 -0400774
Nicolas Capens0bac2852016-05-07 06:09:58 -0400775 //
776 // First, finish off the top level sequence, if any
777 //
778 TIntermAggregate* aggRoot = root->getAsAggregate();
779 if (aggRoot && aggRoot->getOp() == EOpNull)
780 aggRoot->setOp(EOpSequence);
John Bauman66b8ab22014-05-06 15:57:45 -0400781
Nicolas Capens0bac2852016-05-07 06:09:58 -0400782 return true;
John Bauman66b8ab22014-05-06 15:57:45 -0400783}
784
John Bauman66b8ab22014-05-06 15:57:45 -0400785////////////////////////////////////////////////////////////////
786//
787// Member functions of the nodes used for building the tree.
788//
789////////////////////////////////////////////////////////////////
790
Alexis Hetuec93b1d2016-12-09 16:01:29 -0500791// static
792TIntermTyped *TIntermTyped::CreateIndexNode(int index)
793{
794 ConstantUnion *u = new ConstantUnion[1];
795 u[0].setIConst(index);
796
797 TType type(EbtInt, EbpUndefined, EvqConstExpr, 1);
798 TIntermConstantUnion *node = new TIntermConstantUnion(u, type);
799 return node;
800}
801
John Bauman66b8ab22014-05-06 15:57:45 -0400802//
803// Say whether or not an operation node changes the value of a variable.
804//
805// Returns true if state is modified.
806//
807bool TIntermOperator::modifiesState() const
808{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400809 switch (op) {
810 case EOpPostIncrement:
811 case EOpPostDecrement:
812 case EOpPreIncrement:
813 case EOpPreDecrement:
814 case EOpAssign:
815 case EOpAddAssign:
816 case EOpSubAssign:
817 case EOpMulAssign:
818 case EOpVectorTimesMatrixAssign:
819 case EOpVectorTimesScalarAssign:
820 case EOpMatrixTimesScalarAssign:
821 case EOpMatrixTimesMatrixAssign:
822 case EOpDivAssign:
823 case EOpIModAssign:
824 case EOpBitShiftLeftAssign:
825 case EOpBitShiftRightAssign:
826 case EOpBitwiseAndAssign:
827 case EOpBitwiseXorAssign:
828 case EOpBitwiseOrAssign:
829 return true;
830 default:
831 return false;
832 }
John Bauman66b8ab22014-05-06 15:57:45 -0400833}
834
835//
836// returns true if the operator is for one of the constructors
837//
838bool TIntermOperator::isConstructor() const
839{
Nicolas Capens0bac2852016-05-07 06:09:58 -0400840 switch (op) {
841 case EOpConstructVec2:
842 case EOpConstructVec3:
843 case EOpConstructVec4:
844 case EOpConstructMat2:
845 case EOpConstructMat2x3:
846 case EOpConstructMat2x4:
847 case EOpConstructMat3x2:
848 case EOpConstructMat3:
849 case EOpConstructMat3x4:
850 case EOpConstructMat4x2:
851 case EOpConstructMat4x3:
852 case EOpConstructMat4:
853 case EOpConstructFloat:
854 case EOpConstructIVec2:
855 case EOpConstructIVec3:
856 case EOpConstructIVec4:
857 case EOpConstructInt:
858 case EOpConstructUVec2:
859 case EOpConstructUVec3:
860 case EOpConstructUVec4:
861 case EOpConstructUInt:
862 case EOpConstructBVec2:
863 case EOpConstructBVec3:
864 case EOpConstructBVec4:
865 case EOpConstructBool:
866 case EOpConstructStruct:
867 return true;
868 default:
869 return false;
870 }
John Bauman66b8ab22014-05-06 15:57:45 -0400871}
Nicolas Capens7c0ec1e2014-06-12 12:18:44 -0400872
John Bauman66b8ab22014-05-06 15:57:45 -0400873//
874// Make sure the type of a unary operator is appropriate for its
875// combination of operation and operand type.
876//
877// Returns false in nothing makes sense.
878//
Nicolas Capensd3d9b9c2016-04-10 01:53:59 -0400879bool TIntermUnary::promote(TInfoSink&, const TType *funcReturnType)
John Bauman66b8ab22014-05-06 15:57:45 -0400880{
Nicolas Capensd3d9b9c2016-04-10 01:53:59 -0400881 setType(funcReturnType ? *funcReturnType : operand->getType());
882
883 // Unary operations result in temporary variables unless const.
Nicolas Capens0bac2852016-05-07 06:09:58 -0400884 if(type.getQualifier() != EvqConstExpr)
Nicolas Capensd3d9b9c2016-04-10 01:53:59 -0400885 {
Nicolas Capens0bac2852016-05-07 06:09:58 -0400886 type.setQualifier(EvqTemporary);
887 }
Nicolas Capensd3d9b9c2016-04-10 01:53:59 -0400888
Nicolas Capens0bac2852016-05-07 06:09:58 -0400889 switch (op) {
890 case EOpLogicalNot:
891 if (operand->getBasicType() != EbtBool)
892 return false;
893 break;
894 case EOpBitwiseNot:
895 if (!IsInteger(operand->getBasicType()))
896 return false;
897 break;
898 case EOpNegative:
899 case EOpPostIncrement:
900 case EOpPostDecrement:
901 case EOpPreIncrement:
902 case EOpPreDecrement:
903 if (operand->getBasicType() == EbtBool)
904 return false;
905 break;
John Bauman66b8ab22014-05-06 15:57:45 -0400906
Nicolas Capens0bac2852016-05-07 06:09:58 -0400907 // operators for built-ins are already type checked against their prototype
908 case EOpAny:
909 case EOpAll:
910 case EOpVectorLogicalNot:
Alexis Hetu0f448072016-03-18 10:56:08 -0400911 case EOpAbs:
912 case EOpSign:
913 case EOpIsNan:
914 case EOpIsInf:
915 case EOpFloatBitsToInt:
916 case EOpFloatBitsToUint:
917 case EOpIntBitsToFloat:
918 case EOpUintBitsToFloat:
919 case EOpPackSnorm2x16:
920 case EOpPackUnorm2x16:
921 case EOpPackHalf2x16:
922 case EOpUnpackSnorm2x16:
923 case EOpUnpackUnorm2x16:
924 case EOpUnpackHalf2x16:
Nicolas Capens0bac2852016-05-07 06:09:58 -0400925 return true;
John Bauman66b8ab22014-05-06 15:57:45 -0400926
Nicolas Capens0bac2852016-05-07 06:09:58 -0400927 default:
928 if (operand->getBasicType() != EbtFloat)
929 return false;
930 }
John Bauman66b8ab22014-05-06 15:57:45 -0400931
Nicolas Capens0bac2852016-05-07 06:09:58 -0400932 return true;
John Bauman66b8ab22014-05-06 15:57:45 -0400933}
934
935//
936// Establishes the type of the resultant operation, as well as
937// makes the operator the correct one for the operands.
938//
939// Returns false if operator can't work on operands.
940//
941bool TIntermBinary::promote(TInfoSink& infoSink)
942{
Alexis Hetue5246692015-06-18 12:34:52 -0400943 ASSERT(left->isArray() == right->isArray());
John Bauman66b8ab22014-05-06 15:57:45 -0400944
Nicolas Capens0bac2852016-05-07 06:09:58 -0400945 // GLSL ES 2.0 does not support implicit type casting.
946 // So the basic type should always match.
Alexis Hetu92ab1982015-08-18 15:28:27 -0400947 // GLSL ES 3.0 supports integer shift operands of different signedness.
948 if(op != EOpBitShiftLeft &&
949 op != EOpBitShiftRight &&
950 op != EOpBitShiftLeftAssign &&
951 op != EOpBitShiftRightAssign &&
952 left->getBasicType() != right->getBasicType())
Nicolas Capens0bac2852016-05-07 06:09:58 -0400953 {
954 return false;
955 }
John Bauman66b8ab22014-05-06 15:57:45 -0400956
Nicolas Capens0bac2852016-05-07 06:09:58 -0400957 //
958 // Base assumption: just make the type the same as the left
959 // operand. Then only deviations from this need be coded.
960 //
961 setType(left->getType());
John Bauman66b8ab22014-05-06 15:57:45 -0400962
Nicolas Capens0bac2852016-05-07 06:09:58 -0400963 // The result gets promoted to the highest precision.
964 TPrecision higherPrecision = GetHigherPrecision(left->getPrecision(), right->getPrecision());
965 getTypePointer()->setPrecision(higherPrecision);
John Bauman66b8ab22014-05-06 15:57:45 -0400966
Nicolas Capens0bac2852016-05-07 06:09:58 -0400967 // Binary operations results in temporary variables unless both
968 // operands are const.
969 if (left->getQualifier() != EvqConstExpr || right->getQualifier() != EvqConstExpr) {
970 getTypePointer()->setQualifier(EvqTemporary);
971 }
John Bauman66b8ab22014-05-06 15:57:45 -0400972
Nicolas Capens0bac2852016-05-07 06:09:58 -0400973 int primarySize = std::max(left->getNominalSize(), right->getNominalSize());
John Bauman66b8ab22014-05-06 15:57:45 -0400974
Nicolas Capens0bac2852016-05-07 06:09:58 -0400975 //
976 // All scalars. Code after this test assumes this case is removed!
977 //
978 if (primarySize == 1) {
979 switch (op) {
980 //
981 // Promote to conditional
982 //
983 case EOpEqual:
984 case EOpNotEqual:
985 case EOpLessThan:
986 case EOpGreaterThan:
987 case EOpLessThanEqual:
988 case EOpGreaterThanEqual:
989 setType(TType(EbtBool, EbpUndefined));
990 break;
John Bauman66b8ab22014-05-06 15:57:45 -0400991
Nicolas Capens0bac2852016-05-07 06:09:58 -0400992 //
993 // And and Or operate on conditionals
994 //
995 case EOpLogicalAnd:
996 case EOpLogicalOr:
997 case EOpLogicalXor:
998 // Both operands must be of type bool.
999 if (left->getBasicType() != EbtBool || right->getBasicType() != EbtBool)
1000 return false;
1001 setType(TType(EbtBool, EbpUndefined));
1002 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001003
Nicolas Capens0bac2852016-05-07 06:09:58 -04001004 default:
1005 break;
1006 }
1007 return true;
1008 }
John Bauman66b8ab22014-05-06 15:57:45 -04001009
Nicolas Capens0bac2852016-05-07 06:09:58 -04001010 // If we reach here, at least one of the operands is vector or matrix.
1011 // The other operand could be a scalar, vector, or matrix.
1012 // Can these two operands be combined?
1013 //
1014 TBasicType basicType = left->getBasicType();
1015 switch (op) {
1016 case EOpMul:
1017 if (!left->isMatrix() && right->isMatrix()) {
1018 if (left->isVector())
1019 {
1020 op = EOpVectorTimesMatrix;
1021 setType(TType(basicType, higherPrecision, EvqTemporary,
1022 static_cast<unsigned char>(right->getNominalSize()), 1));
1023 }
1024 else {
1025 op = EOpMatrixTimesScalar;
1026 setType(TType(basicType, higherPrecision, EvqTemporary,
1027 static_cast<unsigned char>(right->getNominalSize()), static_cast<unsigned char>(right->getSecondarySize())));
1028 }
1029 } else if (left->isMatrix() && !right->isMatrix()) {
1030 if (right->isVector()) {
1031 op = EOpMatrixTimesVector;
1032 setType(TType(basicType, higherPrecision, EvqTemporary,
1033 static_cast<unsigned char>(left->getSecondarySize()), 1));
1034 } else {
1035 op = EOpMatrixTimesScalar;
1036 }
1037 } else if (left->isMatrix() && right->isMatrix()) {
1038 op = EOpMatrixTimesMatrix;
1039 setType(TType(basicType, higherPrecision, EvqTemporary,
1040 static_cast<unsigned char>(right->getNominalSize()), static_cast<unsigned char>(left->getSecondarySize())));
1041 } else if (!left->isMatrix() && !right->isMatrix()) {
1042 if (left->isVector() && right->isVector()) {
1043 // leave as component product
1044 } else if (left->isVector() || right->isVector()) {
1045 op = EOpVectorTimesScalar;
1046 setType(TType(basicType, higherPrecision, EvqTemporary,
1047 static_cast<unsigned char>(primarySize), 1));
1048 }
1049 } else {
1050 infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
1051 return false;
1052 }
Alexis Hetu00106d42015-04-23 11:45:35 -04001053
Nicolas Capens0bac2852016-05-07 06:09:58 -04001054 if(!ValidateMultiplication(op, left->getType(), right->getType()))
1055 {
1056 return false;
1057 }
1058 break;
1059 case EOpMulAssign:
1060 if (!left->isMatrix() && right->isMatrix()) {
1061 if (left->isVector())
1062 op = EOpVectorTimesMatrixAssign;
1063 else {
1064 return false;
1065 }
1066 } else if (left->isMatrix() && !right->isMatrix()) {
1067 if (right->isVector()) {
1068 return false;
1069 } else {
1070 op = EOpMatrixTimesScalarAssign;
1071 }
1072 } else if (left->isMatrix() && right->isMatrix()) {
1073 op = EOpMatrixTimesMatrixAssign;
1074 setType(TType(basicType, higherPrecision, EvqTemporary,
1075 static_cast<unsigned char>(right->getNominalSize()), static_cast<unsigned char>(left->getSecondarySize())));
1076 } else if (!left->isMatrix() && !right->isMatrix()) {
1077 if (left->isVector() && right->isVector()) {
1078 // leave as component product
1079 } else if (left->isVector() || right->isVector()) {
1080 if (! left->isVector())
1081 return false;
1082 op = EOpVectorTimesScalarAssign;
1083 setType(TType(basicType, higherPrecision, EvqTemporary,
1084 static_cast<unsigned char>(left->getNominalSize()), 1));
1085 }
1086 } else {
1087 infoSink.info.message(EPrefixInternalError, "Missing elses", getLine());
1088 return false;
1089 }
Alexis Hetu00106d42015-04-23 11:45:35 -04001090
Nicolas Capens0bac2852016-05-07 06:09:58 -04001091 if(!ValidateMultiplication(op, left->getType(), right->getType()))
1092 {
1093 return false;
1094 }
1095 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001096
Nicolas Capens0bac2852016-05-07 06:09:58 -04001097 case EOpAssign:
1098 case EOpInitialize:
1099 // No more additional checks are needed.
1100 if ((left->getNominalSize() != right->getNominalSize()) ||
1101 (left->getSecondarySize() != right->getSecondarySize()))
1102 return false;
1103 break;
1104 case EOpAdd:
1105 case EOpSub:
1106 case EOpDiv:
1107 case EOpIMod:
1108 case EOpBitShiftLeft:
1109 case EOpBitShiftRight:
1110 case EOpBitwiseAnd:
1111 case EOpBitwiseXor:
1112 case EOpBitwiseOr:
1113 case EOpAddAssign:
1114 case EOpSubAssign:
1115 case EOpDivAssign:
1116 case EOpIModAssign:
1117 case EOpBitShiftLeftAssign:
1118 case EOpBitShiftRightAssign:
1119 case EOpBitwiseAndAssign:
1120 case EOpBitwiseXorAssign:
1121 case EOpBitwiseOrAssign:
1122 if ((left->isMatrix() && right->isVector()) ||
1123 (left->isVector() && right->isMatrix()))
1124 return false;
Alexis Hetud061e422015-05-13 16:37:50 -04001125
Nicolas Capens0bac2852016-05-07 06:09:58 -04001126 // Are the sizes compatible?
1127 if(left->getNominalSize() != right->getNominalSize() ||
1128 left->getSecondarySize() != right->getSecondarySize())
1129 {
1130 // If the nominal sizes of operands do not match:
1131 // One of them must be a scalar.
1132 if(!left->isScalar() && !right->isScalar())
1133 return false;
Alexis Hetud061e422015-05-13 16:37:50 -04001134
Nicolas Capens0bac2852016-05-07 06:09:58 -04001135 // In the case of compound assignment other than multiply-assign,
1136 // the right side needs to be a scalar. Otherwise a vector/matrix
1137 // would be assigned to a scalar. A scalar can't be shifted by a
1138 // vector either.
1139 if(!right->isScalar() && (modifiesState() || op == EOpBitShiftLeft || op == EOpBitShiftRight))
1140 return false;
1141 }
Alexis Hetud061e422015-05-13 16:37:50 -04001142
Nicolas Capens0bac2852016-05-07 06:09:58 -04001143 {
1144 const int secondarySize = std::max(
1145 left->getSecondarySize(), right->getSecondarySize());
1146 setType(TType(basicType, higherPrecision, EvqTemporary,
1147 static_cast<unsigned char>(primarySize), static_cast<unsigned char>(secondarySize)));
1148 if(left->isArray())
1149 {
1150 ASSERT(left->getArraySize() == right->getArraySize());
1151 type.setArraySize(left->getArraySize());
1152 }
1153 }
1154 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001155
Nicolas Capens0bac2852016-05-07 06:09:58 -04001156 case EOpEqual:
1157 case EOpNotEqual:
1158 case EOpLessThan:
1159 case EOpGreaterThan:
1160 case EOpLessThanEqual:
1161 case EOpGreaterThanEqual:
1162 if ((left->getNominalSize() != right->getNominalSize()) ||
1163 (left->getSecondarySize() != right->getSecondarySize()))
1164 return false;
1165 setType(TType(EbtBool, EbpUndefined));
1166 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001167
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001168 case EOpOuterProduct:
1169 if(!left->isVector() || !right->isVector())
1170 return false;
1171 setType(TType(EbtFloat, right->getNominalSize(), left->getNominalSize()));
1172 break;
1173
1174 case EOpTranspose:
1175 if(!right->isMatrix())
1176 return false;
1177 setType(TType(EbtFloat, right->getSecondarySize(), right->getNominalSize()));
1178 break;
1179
1180 case EOpDeterminant:
1181 if(!right->isMatrix())
1182 return false;
1183 setType(TType(EbtFloat));
1184 break;
1185
1186 case EOpInverse:
1187 if(!right->isMatrix() || right->getNominalSize() != right->getSecondarySize())
1188 return false;
1189 setType(right->getType());
1190 break;
1191
Nicolas Capens0bac2852016-05-07 06:09:58 -04001192 default:
1193 return false;
1194 }
Nicolas Capens5e0c3542016-04-05 17:18:24 -04001195
Nicolas Capens0bac2852016-05-07 06:09:58 -04001196 return true;
John Bauman66b8ab22014-05-06 15:57:45 -04001197}
1198
1199bool CompareStruct(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
1200{
Nicolas Capens0bac2852016-05-07 06:09:58 -04001201 const TFieldList& fields = leftNodeType.getStruct()->fields();
John Bauman66b8ab22014-05-06 15:57:45 -04001202
Nicolas Capens0bac2852016-05-07 06:09:58 -04001203 size_t structSize = fields.size();
1204 int index = 0;
John Bauman66b8ab22014-05-06 15:57:45 -04001205
Nicolas Capens0bac2852016-05-07 06:09:58 -04001206 for (size_t j = 0; j < structSize; j++) {
1207 size_t size = fields[j]->type()->getObjectSize();
1208 for(size_t i = 0; i < size; i++) {
1209 if (fields[j]->type()->getBasicType() == EbtStruct) {
1210 if (!CompareStructure(*(fields[j]->type()), &rightUnionArray[index], &leftUnionArray[index]))
1211 return false;
1212 } else {
1213 if (leftUnionArray[index] != rightUnionArray[index])
1214 return false;
1215 index++;
1216 }
John Bauman66b8ab22014-05-06 15:57:45 -04001217
Nicolas Capens0bac2852016-05-07 06:09:58 -04001218 }
1219 }
1220 return true;
John Bauman66b8ab22014-05-06 15:57:45 -04001221}
1222
1223bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray)
1224{
Nicolas Capens0bac2852016-05-07 06:09:58 -04001225 if (leftNodeType.isArray()) {
1226 TType typeWithoutArrayness = leftNodeType;
1227 typeWithoutArrayness.clearArrayness();
John Bauman66b8ab22014-05-06 15:57:45 -04001228
Nicolas Capens0bac2852016-05-07 06:09:58 -04001229 int arraySize = leftNodeType.getArraySize();
John Bauman66b8ab22014-05-06 15:57:45 -04001230
Nicolas Capens0bac2852016-05-07 06:09:58 -04001231 for (int i = 0; i < arraySize; ++i) {
1232 size_t offset = typeWithoutArrayness.getObjectSize() * i;
1233 if (!CompareStruct(typeWithoutArrayness, &rightUnionArray[offset], &leftUnionArray[offset]))
1234 return false;
1235 }
1236 } else
1237 return CompareStruct(leftNodeType, rightUnionArray, leftUnionArray);
John Bauman66b8ab22014-05-06 15:57:45 -04001238
Nicolas Capens0bac2852016-05-07 06:09:58 -04001239 return true;
John Bauman66b8ab22014-05-06 15:57:45 -04001240}
1241
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001242float determinant2(float m00, float m01, float m10, float m11)
1243{
1244 return m00 * m11 - m01 * m10;
1245}
1246
1247float determinant3(float m00, float m01, float m02,
Nicolas Capens0bac2852016-05-07 06:09:58 -04001248 float m10, float m11, float m12,
1249 float m20, float m21, float m22)
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001250{
1251 return m00 * determinant2(m11, m12, m21, m22) -
Nicolas Capens0bac2852016-05-07 06:09:58 -04001252 m10 * determinant2(m01, m02, m21, m22) +
1253 m20 * determinant2(m01, m02, m11, m12);
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001254}
1255
1256float determinant4(float m00, float m01, float m02, float m03,
Nicolas Capens0bac2852016-05-07 06:09:58 -04001257 float m10, float m11, float m12, float m13,
1258 float m20, float m21, float m22, float m23,
1259 float m30, float m31, float m32, float m33)
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001260{
1261 return m00 * determinant3(m11, m12, m13, m21, m22, m23, m31, m32, m33) -
Nicolas Capens0bac2852016-05-07 06:09:58 -04001262 m10 * determinant3(m01, m02, m03, m21, m22, m23, m31, m32, m33) +
1263 m20 * determinant3(m01, m02, m03, m11, m12, m13, m31, m32, m33) -
1264 m30 * determinant3(m01, m02, m03, m11, m12, m13, m21, m22, m23);
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001265}
1266
1267float ComputeDeterminant(int size, ConstantUnion* unionArray)
1268{
1269 switch(size)
1270 {
1271 case 2:
1272 return determinant2(unionArray[0].getFConst(),
Nicolas Capens0bac2852016-05-07 06:09:58 -04001273 unionArray[1].getFConst(),
1274 unionArray[2].getFConst(),
1275 unionArray[3].getFConst());
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001276 case 3:
1277 return determinant3(unionArray[0].getFConst(),
Nicolas Capens0bac2852016-05-07 06:09:58 -04001278 unionArray[1].getFConst(),
1279 unionArray[2].getFConst(),
1280 unionArray[3].getFConst(),
1281 unionArray[4].getFConst(),
1282 unionArray[5].getFConst(),
1283 unionArray[6].getFConst(),
1284 unionArray[7].getFConst(),
1285 unionArray[8].getFConst());
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001286 case 4:
1287 return determinant4(unionArray[0].getFConst(),
Nicolas Capens0bac2852016-05-07 06:09:58 -04001288 unionArray[1].getFConst(),
1289 unionArray[2].getFConst(),
1290 unionArray[3].getFConst(),
1291 unionArray[4].getFConst(),
1292 unionArray[5].getFConst(),
1293 unionArray[6].getFConst(),
1294 unionArray[7].getFConst(),
1295 unionArray[8].getFConst(),
1296 unionArray[9].getFConst(),
1297 unionArray[10].getFConst(),
1298 unionArray[11].getFConst(),
1299 unionArray[12].getFConst(),
1300 unionArray[13].getFConst(),
1301 unionArray[14].getFConst(),
1302 unionArray[15].getFConst());
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001303 default:
Nicolas Capens3713cd42015-06-22 10:41:54 -04001304 UNREACHABLE(size);
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001305 return 0.0f;
1306 }
1307}
1308
1309ConstantUnion* CreateInverse(TIntermConstantUnion* node, ConstantUnion* unionArray)
1310{
1311 ConstantUnion* tempConstArray = 0;
1312 int size = node->getNominalSize();
1313 float determinant = ComputeDeterminant(size, unionArray);
1314 if(determinant != 0.0f)
1315 {
1316 float invDet = 1.0f / determinant;
1317 tempConstArray = new ConstantUnion[size*size];
1318 switch(size)
1319 {
1320 case 2:
1321 {
1322 float m00 = unionArray[0].getFConst(); // Matrix is:
1323 float m01 = unionArray[1].getFConst(); // (m00, m01)
1324 float m10 = unionArray[2].getFConst(); // (m10, m11)
1325 float m11 = unionArray[3].getFConst();
1326 tempConstArray[0].setFConst( invDet * m11);
1327 tempConstArray[1].setFConst(-invDet * m01);
1328 tempConstArray[2].setFConst(-invDet * m10);
1329 tempConstArray[3].setFConst( invDet * m00);
1330 }
1331 break;
1332 case 3:
1333 {
1334 float m00 = unionArray[0].getFConst(); // Matrix is:
1335 float m01 = unionArray[1].getFConst(); // (m00, m01, m02)
1336 float m02 = unionArray[2].getFConst(); // (m10, m11, m12)
1337 float m10 = unionArray[3].getFConst(); // (m20, m21, m22)
1338 float m11 = unionArray[4].getFConst();
1339 float m12 = unionArray[5].getFConst();
1340 float m20 = unionArray[6].getFConst();
1341 float m21 = unionArray[7].getFConst();
1342 float m22 = unionArray[8].getFConst();
1343 tempConstArray[0].setFConst(invDet * determinant2(m11, m12, m21, m22)); // m00 = invDet * (m11 * m22 - m12 * m21)
1344 tempConstArray[1].setFConst(invDet * determinant2(m12, m10, m22, m20)); // m01 = -invDet * (m10 * m22 - m12 * m20)
1345 tempConstArray[2].setFConst(invDet * determinant2(m10, m11, m20, m21)); // m02 = invDet * (m10 * m21 - m11 * m20)
1346 tempConstArray[3].setFConst(invDet * determinant2(m21, m22, m01, m02)); // m10 = -invDet * (m01 * m22 - m02 * m21)
1347 tempConstArray[4].setFConst(invDet * determinant2(m00, m02, m20, m22)); // m11 = invDet * (m00 * m22 - m02 * m20)
1348 tempConstArray[5].setFConst(invDet * determinant2(m20, m21, m00, m01)); // m12 = -invDet * (m00 * m21 - m01 * m20)
1349 tempConstArray[6].setFConst(invDet * determinant2(m01, m02, m11, m12)); // m20 = invDet * (m01 * m12 - m02 * m11)
1350 tempConstArray[7].setFConst(invDet * determinant2(m10, m12, m00, m02)); // m21 = -invDet * (m00 * m12 - m02 * m10)
1351 tempConstArray[8].setFConst(invDet * determinant2(m00, m01, m10, m11)); // m22 = invDet * (m00 * m11 - m01 * m10)
1352 }
1353 break;
1354 case 4:
1355 {
1356 float m00 = unionArray[0].getFConst(); // Matrix is:
1357 float m01 = unionArray[1].getFConst(); // (m00, m01, m02, m03)
1358 float m02 = unionArray[2].getFConst(); // (m10, m11, m12, m13)
1359 float m03 = unionArray[3].getFConst(); // (m20, m21, m22, m23)
1360 float m10 = unionArray[4].getFConst(); // (m30, m31, m32, m33)
1361 float m11 = unionArray[5].getFConst();
1362 float m12 = unionArray[6].getFConst();
1363 float m13 = unionArray[7].getFConst();
1364 float m20 = unionArray[8].getFConst();
1365 float m21 = unionArray[9].getFConst();
1366 float m22 = unionArray[10].getFConst();
1367 float m23 = unionArray[11].getFConst();
1368 float m30 = unionArray[12].getFConst();
1369 float m31 = unionArray[13].getFConst();
1370 float m32 = unionArray[14].getFConst();
1371 float m33 = unionArray[15].getFConst();
1372 tempConstArray[ 0].setFConst( invDet * determinant3(m11, m12, m13, m21, m22, m23, m31, m32, m33)); // m00
1373 tempConstArray[ 1].setFConst(-invDet * determinant3(m10, m12, m13, m20, m22, m23, m30, m32, m33)); // m01
1374 tempConstArray[ 2].setFConst( invDet * determinant3(m10, m11, m13, m20, m21, m23, m30, m31, m33)); // m02
1375 tempConstArray[ 3].setFConst(-invDet * determinant3(m10, m11, m12, m20, m21, m22, m30, m31, m32)); // m03
1376 tempConstArray[ 4].setFConst( invDet * determinant3(m01, m02, m03, m21, m22, m23, m31, m32, m33)); // m10
1377 tempConstArray[ 5].setFConst(-invDet * determinant3(m00, m02, m03, m20, m22, m23, m30, m32, m33)); // m11
1378 tempConstArray[ 6].setFConst( invDet * determinant3(m00, m01, m03, m20, m21, m23, m30, m31, m33)); // m12
1379 tempConstArray[ 7].setFConst(-invDet * determinant3(m00, m01, m02, m20, m21, m22, m30, m31, m32)); // m13
1380 tempConstArray[ 8].setFConst( invDet * determinant3(m01, m02, m03, m11, m12, m13, m31, m32, m33)); // m20
1381 tempConstArray[ 9].setFConst(-invDet * determinant3(m00, m02, m03, m10, m12, m13, m30, m32, m33)); // m21
1382 tempConstArray[10].setFConst( invDet * determinant3(m00, m01, m03, m10, m11, m13, m30, m31, m33)); // m22
1383 tempConstArray[11].setFConst(-invDet * determinant3(m00, m01, m02, m10, m11, m12, m30, m31, m32)); // m23
1384 tempConstArray[12].setFConst( invDet * determinant3(m01, m02, m03, m11, m12, m13, m21, m22, m23)); // m30
1385 tempConstArray[13].setFConst(-invDet * determinant3(m00, m02, m03, m10, m12, m13, m20, m22, m23)); // m31
1386 tempConstArray[14].setFConst( invDet * determinant3(m00, m01, m03, m10, m11, m13, m20, m21, m23)); // m32
1387 tempConstArray[15].setFConst(-invDet * determinant3(m00, m01, m02, m10, m11, m12, m20, m21, m22)); // m33
1388 }
1389 break;
1390 default:
Nicolas Capens3713cd42015-06-22 10:41:54 -04001391 UNREACHABLE(size);
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001392 }
1393 }
1394 return tempConstArray;
1395}
1396
John Bauman66b8ab22014-05-06 15:57:45 -04001397//
1398// The fold functions see if an operation on a constant can be done in place,
1399// without generating run-time code.
1400//
1401// Returns the node to keep using, which may or may not be the node passed in.
1402//
1403
1404TIntermTyped* TIntermConstantUnion::fold(TOperator op, TIntermTyped* constantNode, TInfoSink& infoSink)
1405{
Nicolas Capens0bac2852016-05-07 06:09:58 -04001406 ConstantUnion *unionArray = getUnionArrayPointer();
1407 size_t objectSize = getType().getObjectSize();
John Bauman66b8ab22014-05-06 15:57:45 -04001408
Nicolas Capens0bac2852016-05-07 06:09:58 -04001409 if (constantNode) { // binary operations
1410 TIntermConstantUnion *node = constantNode->getAsConstantUnion();
1411 ConstantUnion *rightUnionArray = node->getUnionArrayPointer();
1412 TType returnType = getType();
John Bauman66b8ab22014-05-06 15:57:45 -04001413
Nicolas Capens0bac2852016-05-07 06:09:58 -04001414 // for a case like float f = 1.2 + vec4(2,3,4,5);
1415 if (constantNode->getType().getObjectSize() == 1 && objectSize > 1) {
1416 rightUnionArray = new ConstantUnion[objectSize];
1417 for (size_t i = 0; i < objectSize; ++i)
1418 rightUnionArray[i] = *node->getUnionArrayPointer();
1419 returnType = getType();
1420 } else if (constantNode->getType().getObjectSize() > 1 && objectSize == 1) {
1421 // for a case like float f = vec4(2,3,4,5) + 1.2;
1422 unionArray = new ConstantUnion[constantNode->getType().getObjectSize()];
1423 for (size_t i = 0; i < constantNode->getType().getObjectSize(); ++i)
1424 unionArray[i] = *getUnionArrayPointer();
1425 returnType = node->getType();
1426 objectSize = constantNode->getType().getObjectSize();
1427 }
John Bauman66b8ab22014-05-06 15:57:45 -04001428
Nicolas Capens0bac2852016-05-07 06:09:58 -04001429 ConstantUnion* tempConstArray = 0;
1430 TIntermConstantUnion *tempNode;
John Bauman66b8ab22014-05-06 15:57:45 -04001431
Nicolas Capens0bac2852016-05-07 06:09:58 -04001432 switch(op) {
1433 case EOpAdd:
1434 tempConstArray = new ConstantUnion[objectSize];
1435 {// support MSVC++6.0
1436 for (size_t i = 0; i < objectSize; i++)
1437 tempConstArray[i] = unionArray[i] + rightUnionArray[i];
1438 }
1439 break;
1440 case EOpSub:
1441 tempConstArray = new ConstantUnion[objectSize];
1442 {// support MSVC++6.0
1443 for (size_t i = 0; i < objectSize; i++)
1444 tempConstArray[i] = unionArray[i] - rightUnionArray[i];
1445 }
1446 break;
John Bauman66b8ab22014-05-06 15:57:45 -04001447
Nicolas Capens0bac2852016-05-07 06:09:58 -04001448 case EOpMul:
1449 case EOpVectorTimesScalar:
1450 case EOpMatrixTimesScalar:
1451 tempConstArray = new ConstantUnion[objectSize];
1452 {// support MSVC++6.0
1453 for (size_t i = 0; i < objectSize; i++)
1454 tempConstArray[i] = unionArray[i] * rightUnionArray[i];
1455 }
1456 break;
1457 case EOpMatrixTimesMatrix:
1458 if (getType().getBasicType() != EbtFloat || node->getBasicType() != EbtFloat) {
1459 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix multiply", getLine());
1460 return 0;
1461 }
1462 {// support MSVC++6.0
1463 int leftNumCols = getNominalSize();
1464 int leftNumRows = getSecondarySize();
1465 int rightNumCols = node->getNominalSize();
1466 int rightNumRows = node->getSecondarySize();
1467 if(leftNumCols != rightNumRows) {
1468 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix multiply", getLine());
1469 return 0;
1470 }
1471 int tempNumCols = rightNumCols;
1472 int tempNumRows = leftNumRows;
1473 int tempNumAdds = leftNumCols;
1474 tempConstArray = new ConstantUnion[tempNumCols*tempNumRows];
1475 for (int row = 0; row < tempNumRows; row++) {
1476 for (int column = 0; column < tempNumCols; column++) {
1477 tempConstArray[tempNumRows * column + row].setFConst(0.0f);
1478 for (int i = 0; i < tempNumAdds; i++) {
1479 tempConstArray[tempNumRows * column + row].setFConst(tempConstArray[tempNumRows * column + row].getFConst() + unionArray[i * leftNumRows + row].getFConst() * (rightUnionArray[column * rightNumRows + i].getFConst()));
1480 }
1481 }
1482 }
1483 // update return type for matrix product
1484 returnType.setNominalSize(static_cast<unsigned char>(tempNumCols));
1485 returnType.setSecondarySize(static_cast<unsigned char>(tempNumRows));
1486 }
1487 break;
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001488
1489 case EOpOuterProduct:
1490 {
1491 int leftSize = getNominalSize();
1492 int rightSize = node->getNominalSize();
1493 tempConstArray = new ConstantUnion[leftSize*rightSize];
1494 for(int row = 0; row < leftSize; row++) {
1495 for(int column = 0; column < rightSize; column++) {
1496 tempConstArray[leftSize * column + row].setFConst(unionArray[row].getFConst() * rightUnionArray[column].getFConst());
1497 }
1498 }
1499 // update return type for outer product
1500 returnType.setNominalSize(static_cast<unsigned char>(rightSize));
1501 returnType.setSecondarySize(static_cast<unsigned char>(leftSize));
1502 }
1503 break;
1504
1505 case EOpTranspose:
1506 {
1507 int rightCol = node->getNominalSize();
1508 int rightRow = node->getSecondarySize();
1509 tempConstArray = new ConstantUnion[rightCol*rightRow];
1510 for(int row = 0; row < rightRow; row++) {
1511 for(int column = 0; column < rightCol; column++) {
1512 tempConstArray[rightRow * column + row].setFConst(rightUnionArray[rightCol * row + column].getFConst());
1513 }
1514 }
1515 // update return type for transpose
1516 returnType.setNominalSize(static_cast<unsigned char>(rightRow));
1517 returnType.setSecondarySize(static_cast<unsigned char>(rightCol));
1518 }
1519 break;
1520
1521 case EOpDeterminant:
1522 {
1523 ASSERT(node->getNominalSize() == node->getSecondarySize());
1524
1525 tempConstArray = new ConstantUnion[1];
1526 tempConstArray[0].setFConst(ComputeDeterminant(node->getNominalSize(), rightUnionArray));
1527 // update return type for determinant
1528 returnType.setNominalSize(1);
1529 returnType.setSecondarySize(1);
1530 }
1531 break;
1532
1533 case EOpInverse:
1534 {
1535 ASSERT(node->getNominalSize() == node->getSecondarySize());
1536
1537 tempConstArray = CreateInverse(node, rightUnionArray);
1538 if(!tempConstArray)
1539 {
1540 // Singular matrix, just copy
1541 tempConstArray = new ConstantUnion[objectSize];
Alexis Hetuab752792016-04-21 16:11:31 -04001542 for(size_t i = 0; i < objectSize; i++)
Alexis Hetu3815b6c2015-05-27 11:21:37 -04001543 tempConstArray[i] = rightUnionArray[i];
1544 }
1545 }
1546 break;
1547
Nicolas Capens0bac2852016-05-07 06:09:58 -04001548 case EOpDiv:
1549 case EOpIMod:
Nicolas Capens5e0c3542016-04-05 17:18:24 -04001550 tempConstArray = new ConstantUnion[objectSize];
Nicolas Capens0bac2852016-05-07 06:09:58 -04001551 {// support MSVC++6.0
1552 for (size_t i = 0; i < objectSize; i++) {
1553 switch (getType().getBasicType()) {
1554 case EbtFloat:
1555 if (rightUnionArray[i] == 0.0f) {
1556 infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
1557 tempConstArray[i].setFConst(FLT_MAX);
1558 } else {
1559 ASSERT(op == EOpDiv);
1560 tempConstArray[i].setFConst(unionArray[i].getFConst() / rightUnionArray[i].getFConst());
1561 }
1562 break;
1563
1564 case EbtInt:
1565 if (rightUnionArray[i] == 0) {
1566 infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
1567 tempConstArray[i].setIConst(INT_MAX);
1568 } else {
1569 if(op == EOpDiv) {
1570 tempConstArray[i].setIConst(unionArray[i].getIConst() / rightUnionArray[i].getIConst());
1571 } else {
1572 ASSERT(op == EOpIMod);
1573 tempConstArray[i].setIConst(unionArray[i].getIConst() % rightUnionArray[i].getIConst());
1574 }
1575 }
1576 break;
1577 case EbtUInt:
1578 if (rightUnionArray[i] == 0) {
1579 infoSink.info.message(EPrefixWarning, "Divide by zero error during constant folding", getLine());
1580 tempConstArray[i].setUConst(UINT_MAX);
1581 } else {
1582 if(op == EOpDiv) {
1583 tempConstArray[i].setUConst(unionArray[i].getUConst() / rightUnionArray[i].getUConst());
1584 } else {
1585 ASSERT(op == EOpIMod);
1586 tempConstArray[i].setUConst(unionArray[i].getUConst() % rightUnionArray[i].getUConst());
1587 }
1588 }
1589 break;
1590 default:
1591 infoSink.info.message(EPrefixInternalError, "Constant folding cannot be done for \"/\"", getLine());
1592 return 0;
1593 }
1594 }
1595 }
1596 break;
1597
1598 case EOpMatrixTimesVector:
1599 if (node->getBasicType() != EbtFloat) {
1600 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for matrix times vector", getLine());
1601 return 0;
1602 }
Chris Forbesc5e68ab2018-09-21 13:24:17 -07001603 tempConstArray = new ConstantUnion[getSecondarySize()];
Nicolas Capens0bac2852016-05-07 06:09:58 -04001604
1605 {// support MSVC++6.0
Chris Forbesc5e68ab2018-09-21 13:24:17 -07001606 for (int rows = getSecondarySize(), i = 0; i < rows; i++) {
Nicolas Capens0bac2852016-05-07 06:09:58 -04001607 tempConstArray[i].setFConst(0.0f);
Chris Forbesc5e68ab2018-09-21 13:24:17 -07001608 for (int cols = getNominalSize(), j = 0; j < cols; j++) {
1609 tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j*rows + i].getFConst()) * rightUnionArray[j].getFConst()));
Nicolas Capens0bac2852016-05-07 06:09:58 -04001610 }
1611 }
1612 }
1613
Chris Forbesc5e68ab2018-09-21 13:24:17 -07001614 tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtFloat, EbpUndefined, EvqConstExpr, getSecondarySize()));
Nicolas Capens0bac2852016-05-07 06:09:58 -04001615 tempNode->setLine(getLine());
1616
1617 return tempNode;
1618
1619 case EOpVectorTimesMatrix:
1620 if (getType().getBasicType() != EbtFloat) {
1621 infoSink.info.message(EPrefixInternalError, "Constant Folding cannot be done for vector times matrix", getLine());
1622 return 0;
1623 }
1624
Chris Forbesc5e68ab2018-09-21 13:24:17 -07001625 tempConstArray = new ConstantUnion[node->getNominalSize()];
Nicolas Capens0bac2852016-05-07 06:09:58 -04001626 {// support MSVC++6.0
Chris Forbesc5e68ab2018-09-21 13:24:17 -07001627 for (int cols = node->getNominalSize(), i = 0; i < cols; i++) {
Nicolas Capens0bac2852016-05-07 06:09:58 -04001628 tempConstArray[i].setFConst(0.0f);
Chris Forbesc5e68ab2018-09-21 13:24:17 -07001629 for (int rows = node->getSecondarySize(), j = 0; j < rows; j++) {
1630 tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j].getFConst()) * rightUnionArray[i*rows + j].getFConst()));
Nicolas Capens0bac2852016-05-07 06:09:58 -04001631 }
1632 }
1633 }
Chris Forbesc5e68ab2018-09-21 13:24:17 -07001634
1635 tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtFloat, EbpUndefined, EvqConstExpr, node->getNominalSize()));
1636 tempNode->setLine(getLine());
1637 return tempNode;
Nicolas Capens0bac2852016-05-07 06:09:58 -04001638
1639 case EOpLogicalAnd: // this code is written for possible future use, will not get executed currently
1640 tempConstArray = new ConstantUnion[objectSize];
1641 {// support MSVC++6.0
1642 for (size_t i = 0; i < objectSize; i++)
1643 tempConstArray[i] = unionArray[i] && rightUnionArray[i];
1644 }
1645 break;
1646
1647 case EOpLogicalOr: // this code is written for possible future use, will not get executed currently
1648 tempConstArray = new ConstantUnion[objectSize];
1649 {// support MSVC++6.0
1650 for (size_t i = 0; i < objectSize; i++)
1651 tempConstArray[i] = unionArray[i] || rightUnionArray[i];
1652 }
1653 break;
1654
1655 case EOpLogicalXor:
1656 tempConstArray = new ConstantUnion[objectSize];
1657 {// support MSVC++6.0
1658 for (size_t i = 0; i < objectSize; i++)
1659 switch (getType().getBasicType()) {
1660 case EbtBool: tempConstArray[i].setBConst((unionArray[i] == rightUnionArray[i]) ? false : true); break;
1661 default: assert(false && "Default missing");
1662 }
1663 }
1664 break;
1665
1666 case EOpBitwiseAnd:
1667 tempConstArray = new ConstantUnion[objectSize];
1668 for(size_t i = 0; i < objectSize; i++)
1669 tempConstArray[i] = unionArray[i] & rightUnionArray[i];
1670 break;
1671 case EOpBitwiseXor:
1672 tempConstArray = new ConstantUnion[objectSize];
1673 for(size_t i = 0; i < objectSize; i++)
1674 tempConstArray[i] = unionArray[i] ^ rightUnionArray[i];
1675 break;
1676 case EOpBitwiseOr:
1677 tempConstArray = new ConstantUnion[objectSize];
1678 for(size_t i = 0; i < objectSize; i++)
1679 tempConstArray[i] = unionArray[i] | rightUnionArray[i];
1680 break;
1681 case EOpBitShiftLeft:
1682 tempConstArray = new ConstantUnion[objectSize];
1683 for(size_t i = 0; i < objectSize; i++)
1684 tempConstArray[i] = unionArray[i] << rightUnionArray[i];
1685 break;
1686 case EOpBitShiftRight:
1687 tempConstArray = new ConstantUnion[objectSize];
1688 for(size_t i = 0; i < objectSize; i++)
1689 tempConstArray[i] = unionArray[i] >> rightUnionArray[i];
1690 break;
1691
1692 case EOpLessThan:
1693 tempConstArray = new ConstantUnion[objectSize];
1694 for(size_t i = 0; i < objectSize; i++)
1695 tempConstArray[i].setBConst(unionArray[i] < rightUnionArray[i]);
1696 returnType = TType(EbtBool, EbpUndefined, EvqConstExpr, objectSize);
1697 break;
1698 case EOpGreaterThan:
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 EOpLessThanEqual:
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 EOpGreaterThanEqual:
1711 tempConstArray = new ConstantUnion[objectSize];
1712 for(size_t i = 0; i < objectSize; i++)
Nicolas Capens5e0c3542016-04-05 17:18:24 -04001713 tempConstArray[i].setBConst(unionArray[i] >= rightUnionArray[i]);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001714 returnType = TType(EbtBool, EbpUndefined, EvqConstExpr, objectSize);
1715 break;
1716 case EOpEqual:
Alexis Hetu26ea8f52016-04-28 12:45:48 -04001717 tempConstArray = new ConstantUnion[1];
1718
1719 if(getType().getBasicType() == EbtStruct) {
1720 tempConstArray->setBConst(CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray));
Nicolas Capens0bac2852016-05-07 06:09:58 -04001721 } else {
Alexis Hetu26ea8f52016-04-28 12:45:48 -04001722 bool boolNodeFlag = true;
Nicolas Capens0bac2852016-05-07 06:09:58 -04001723 for (size_t i = 0; i < objectSize; i++) {
1724 if (unionArray[i] != rightUnionArray[i]) {
1725 boolNodeFlag = false;
1726 break; // break out of for loop
1727 }
1728 }
Alexis Hetu26ea8f52016-04-28 12:45:48 -04001729 tempConstArray->setBConst(boolNodeFlag);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001730 }
John Bauman66b8ab22014-05-06 15:57:45 -04001731
Nicolas Capens0bac2852016-05-07 06:09:58 -04001732 tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConstExpr));
1733 tempNode->setLine(getLine());
John Bauman66b8ab22014-05-06 15:57:45 -04001734
Nicolas Capens0bac2852016-05-07 06:09:58 -04001735 return tempNode;
John Bauman66b8ab22014-05-06 15:57:45 -04001736
Nicolas Capens0bac2852016-05-07 06:09:58 -04001737 case EOpNotEqual:
Alexis Hetu26ea8f52016-04-28 12:45:48 -04001738 tempConstArray = new ConstantUnion[1];
1739
1740 if(getType().getBasicType() == EbtStruct) {
1741 tempConstArray->setBConst(!CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray));
Nicolas Capens0bac2852016-05-07 06:09:58 -04001742 } else {
Alexis Hetu26ea8f52016-04-28 12:45:48 -04001743 bool boolNodeFlag = false;
Nicolas Capens0bac2852016-05-07 06:09:58 -04001744 for (size_t i = 0; i < objectSize; i++) {
1745 if (unionArray[i] != rightUnionArray[i]) {
1746 boolNodeFlag = true;
1747 break; // break out of for loop
1748 }
1749 }
Alexis Hetu26ea8f52016-04-28 12:45:48 -04001750 tempConstArray->setBConst(boolNodeFlag);
Nicolas Capens0bac2852016-05-07 06:09:58 -04001751 }
John Bauman66b8ab22014-05-06 15:57:45 -04001752
Nicolas Capens0bac2852016-05-07 06:09:58 -04001753 tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConstExpr));
1754 tempNode->setLine(getLine());
John Bauman66b8ab22014-05-06 15:57:45 -04001755
Nicolas Capens0bac2852016-05-07 06:09:58 -04001756 return tempNode;
Nicolas Capens91dfb972016-04-09 23:45:12 -04001757 case EOpMax:
Nicolas Capens0bac2852016-05-07 06:09:58 -04001758 tempConstArray = new ConstantUnion[objectSize];
1759 {// support MSVC++6.0
1760 for (size_t i = 0; i < objectSize; i++)
1761 tempConstArray[i] = unionArray[i] > rightUnionArray[i] ? unionArray[i] : rightUnionArray[i];
1762 }
1763 break;
1764 case EOpMin:
1765 tempConstArray = new ConstantUnion[objectSize];
1766 {// support MSVC++6.0
1767 for (size_t i = 0; i < objectSize; i++)
1768 tempConstArray[i] = unionArray[i] < rightUnionArray[i] ? unionArray[i] : rightUnionArray[i];
1769 }
1770 break;
1771 default:
1772 return 0;
1773 }
1774 tempNode = new TIntermConstantUnion(tempConstArray, returnType);
1775 tempNode->setLine(getLine());
John Bauman66b8ab22014-05-06 15:57:45 -04001776
Nicolas Capens0bac2852016-05-07 06:09:58 -04001777 return tempNode;
1778 } else {
1779 //
1780 // Do unary operations
1781 //
1782 TIntermConstantUnion *newNode = 0;
1783 ConstantUnion* tempConstArray = new ConstantUnion[objectSize];
Alexis Hetu40f48ab2018-01-24 15:58:05 -05001784 TType type = getType();
1785 TBasicType basicType = type.getBasicType();
Nicolas Capens0bac2852016-05-07 06:09:58 -04001786 for (size_t i = 0; i < objectSize; i++) {
1787 switch(op) {
1788 case EOpNegative:
Alexis Hetu40f48ab2018-01-24 15:58:05 -05001789 switch (basicType) {
Nicolas Capens0bac2852016-05-07 06:09:58 -04001790 case EbtFloat: tempConstArray[i].setFConst(-unionArray[i].getFConst()); break;
1791 case EbtInt: tempConstArray[i].setIConst(-unionArray[i].getIConst()); break;
1792 default:
1793 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1794 return 0;
1795 }
1796 break;
1797 case EOpLogicalNot: // this code is written for possible future use, will not get executed currently
Alexis Hetu40f48ab2018-01-24 15:58:05 -05001798 switch (basicType) {
Nicolas Capens0bac2852016-05-07 06:09:58 -04001799 case EbtBool: tempConstArray[i].setBConst(!unionArray[i].getBConst()); break;
1800 default:
1801 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1802 return 0;
1803 }
1804 break;
1805 case EOpBitwiseNot:
Alexis Hetu40f48ab2018-01-24 15:58:05 -05001806 switch(basicType) {
Nicolas Capens0bac2852016-05-07 06:09:58 -04001807 case EbtInt: tempConstArray[i].setIConst(~unionArray[i].getIConst()); break;
1808 case EbtUInt: tempConstArray[i].setUConst(~unionArray[i].getUConst()); break;
1809 default:
1810 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1811 return 0;
1812 }
1813 break;
Alexis Hetu6c6b4702016-04-26 16:30:22 -04001814 case EOpRadians:
Alexis Hetu40f48ab2018-01-24 15:58:05 -05001815 switch(basicType) {
Alexis Hetu6c6b4702016-04-26 16:30:22 -04001816 case EbtFloat: tempConstArray[i].setFConst(unionArray[i].getFConst() * 1.74532925e-2f); break;
1817 default:
1818 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1819 return 0;
1820 }
1821 break;
1822 case EOpDegrees:
Alexis Hetu40f48ab2018-01-24 15:58:05 -05001823 switch(basicType) {
Alexis Hetu6c6b4702016-04-26 16:30:22 -04001824 case EbtFloat: tempConstArray[i].setFConst(unionArray[i].getFConst() * 5.72957795e+1f); break;
1825 default:
1826 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1827 return 0;
1828 }
1829 break;
1830 case EOpSin:
Alexis Hetu40f48ab2018-01-24 15:58:05 -05001831 switch(basicType) {
Alexis Hetu6c6b4702016-04-26 16:30:22 -04001832 case EbtFloat: tempConstArray[i].setFConst(sinf(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 EOpCos:
Alexis Hetu40f48ab2018-01-24 15:58:05 -05001839 switch(basicType) {
Alexis Hetu6c6b4702016-04-26 16:30:22 -04001840 case EbtFloat: tempConstArray[i].setFConst(cosf(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 EOpTan:
Alexis Hetu40f48ab2018-01-24 15:58:05 -05001847 switch(basicType) {
Alexis Hetu6c6b4702016-04-26 16:30:22 -04001848 case EbtFloat: tempConstArray[i].setFConst(tanf(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 EOpAsin:
Alexis Hetu40f48ab2018-01-24 15:58:05 -05001855 switch(basicType) {
Alexis Hetu6c6b4702016-04-26 16:30:22 -04001856 case EbtFloat: tempConstArray[i].setFConst(asinf(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 EOpAcos:
Alexis Hetu40f48ab2018-01-24 15:58:05 -05001863 switch(basicType) {
Alexis Hetu6c6b4702016-04-26 16:30:22 -04001864 case EbtFloat: tempConstArray[i].setFConst(acosf(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 EOpAtan:
Alexis Hetu40f48ab2018-01-24 15:58:05 -05001871 switch(basicType) {
Alexis Hetu6c6b4702016-04-26 16:30:22 -04001872 case EbtFloat: tempConstArray[i].setFConst(atanf(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 EOpSinh:
Alexis Hetu40f48ab2018-01-24 15:58:05 -05001879 switch(basicType) {
Alexis Hetu6c6b4702016-04-26 16:30:22 -04001880 case EbtFloat: tempConstArray[i].setFConst(sinhf(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 EOpCosh:
Alexis Hetu40f48ab2018-01-24 15:58:05 -05001887 switch(basicType) {
Alexis Hetu6c6b4702016-04-26 16:30:22 -04001888 case EbtFloat: tempConstArray[i].setFConst(coshf(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 EOpTanh:
Alexis Hetu40f48ab2018-01-24 15:58:05 -05001895 switch(basicType) {
Alexis Hetu6c6b4702016-04-26 16:30:22 -04001896 case EbtFloat: tempConstArray[i].setFConst(tanhf(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 EOpAsinh:
Alexis Hetu40f48ab2018-01-24 15:58:05 -05001903 switch(basicType) {
Alexis Hetu6c6b4702016-04-26 16:30:22 -04001904 case EbtFloat: tempConstArray[i].setFConst(asinhf(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 EOpAcosh:
Alexis Hetu40f48ab2018-01-24 15:58:05 -05001911 switch(basicType) {
Alexis Hetu6c6b4702016-04-26 16:30:22 -04001912 case EbtFloat: tempConstArray[i].setFConst(acoshf(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 EOpAtanh:
Alexis Hetu40f48ab2018-01-24 15:58:05 -05001919 switch(basicType) {
Alexis Hetu6c6b4702016-04-26 16:30:22 -04001920 case EbtFloat: tempConstArray[i].setFConst(atanhf(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 EOpLog:
Alexis Hetu40f48ab2018-01-24 15:58:05 -05001927 switch(basicType) {
Alexis Hetu6c6b4702016-04-26 16:30:22 -04001928 case EbtFloat: tempConstArray[i].setFConst(logf(unionArray[i].getFConst())); break;
1929 default:
1930 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1931 return 0;
1932 }
1933 break;
1934 case EOpLog2:
Alexis Hetu40f48ab2018-01-24 15:58:05 -05001935 switch(basicType) {
Alexis Hetu2ce222c2016-05-02 11:20:52 -04001936 case EbtFloat: tempConstArray[i].setFConst(sw::log2(unionArray[i].getFConst())); break;
Alexis Hetu6c6b4702016-04-26 16:30:22 -04001937 default:
1938 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1939 return 0;
1940 }
1941 break;
1942 case EOpExp:
Alexis Hetu40f48ab2018-01-24 15:58:05 -05001943 switch(basicType) {
Alexis Hetu6c6b4702016-04-26 16:30:22 -04001944 case EbtFloat: tempConstArray[i].setFConst(expf(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 EOpExp2:
Alexis Hetu40f48ab2018-01-24 15:58:05 -05001951 switch(basicType) {
Alexis Hetu6c6b4702016-04-26 16:30:22 -04001952 case EbtFloat: tempConstArray[i].setFConst(exp2f(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 EOpSqrt:
Alexis Hetu40f48ab2018-01-24 15:58:05 -05001959 switch(basicType) {
Alexis Hetu6c6b4702016-04-26 16:30:22 -04001960 case EbtFloat: tempConstArray[i].setFConst(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 case EOpInverseSqrt:
Alexis Hetu40f48ab2018-01-24 15:58:05 -05001967 switch(basicType) {
Alexis Hetu6c6b4702016-04-26 16:30:22 -04001968 case EbtFloat: tempConstArray[i].setFConst(1.0f / sqrtf(unionArray[i].getFConst())); break;
1969 default:
1970 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1971 return 0;
1972 }
1973 break;
Alexis Hetu40f48ab2018-01-24 15:58:05 -05001974 case EOpFloatBitsToInt:
1975 switch(basicType) {
1976 case EbtFloat:
1977 tempConstArray[i].setIConst(sw::bitCast<int>(unionArray[i].getFConst()));
1978 type.setBasicType(EbtInt);
1979 break;
1980 default:
1981 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1982 return 0;
1983 }
1984 break;
1985 break;
1986 case EOpFloatBitsToUint:
1987 switch(basicType) {
1988 case EbtFloat:
1989 tempConstArray[i].setUConst(sw::bitCast<unsigned int>(unionArray[i].getFConst()));
1990 type.setBasicType(EbtUInt);
1991 break;
1992 default:
1993 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
1994 return 0;
1995 }
1996 break;
1997 case EOpIntBitsToFloat:
1998 switch(basicType) {
1999 case EbtInt:
2000 tempConstArray[i].setFConst(sw::bitCast<float>(unionArray[i].getIConst()));
2001 type.setBasicType(EbtFloat);
2002 break;
2003 default:
2004 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
2005 return 0;
2006 }
2007 break;
2008 case EOpUintBitsToFloat:
2009 switch(basicType) {
2010 case EbtUInt:
2011 tempConstArray[i].setFConst(sw::bitCast<float>(unionArray[i].getUConst()));
2012 type.setBasicType(EbtFloat);
2013 break;
2014 default:
2015 infoSink.info.message(EPrefixInternalError, "Unary operation not folded into constant", getLine());
2016 return 0;
2017 }
2018 break;
Alexis Hetu6c6b4702016-04-26 16:30:22 -04002019 default:
Nicolas Capens0bac2852016-05-07 06:09:58 -04002020 return 0;
2021 }
2022 }
Alexis Hetu40f48ab2018-01-24 15:58:05 -05002023 newNode = new TIntermConstantUnion(tempConstArray, type);
Nicolas Capens0bac2852016-05-07 06:09:58 -04002024 newNode->setLine(getLine());
2025 return newNode;
2026 }
John Bauman66b8ab22014-05-06 15:57:45 -04002027}
2028
2029TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermConstantUnion* node)
2030{
Nicolas Capens0bac2852016-05-07 06:09:58 -04002031 size_t size = node->getType().getObjectSize();
John Bauman66b8ab22014-05-06 15:57:45 -04002032
Nicolas Capens0bac2852016-05-07 06:09:58 -04002033 ConstantUnion *leftUnionArray = new ConstantUnion[size];
John Bauman66b8ab22014-05-06 15:57:45 -04002034
Nicolas Capens0bac2852016-05-07 06:09:58 -04002035 for(size_t i = 0; i < size; i++) {
2036 switch (promoteTo) {
2037 case EbtFloat:
2038 switch (node->getType().getBasicType()) {
2039 case EbtInt:
2040 leftUnionArray[i].setFConst(static_cast<float>(node->getIConst(i)));
2041 break;
2042 case EbtUInt:
2043 leftUnionArray[i].setFConst(static_cast<float>(node->getUConst(i)));
2044 break;
2045 case EbtBool:
2046 leftUnionArray[i].setFConst(static_cast<float>(node->getBConst(i)));
2047 break;
2048 case EbtFloat:
2049 leftUnionArray[i].setFConst(static_cast<float>(node->getFConst(i)));
2050 break;
2051 default:
2052 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
2053 return 0;
2054 }
2055 break;
2056 case EbtInt:
2057 switch (node->getType().getBasicType()) {
2058 case EbtInt:
2059 leftUnionArray[i].setIConst(static_cast<int>(node->getIConst(i)));
2060 break;
2061 case EbtUInt:
2062 leftUnionArray[i].setIConst(static_cast<int>(node->getUConst(i)));
2063 break;
2064 case EbtBool:
2065 leftUnionArray[i].setIConst(static_cast<int>(node->getBConst(i)));
2066 break;
2067 case EbtFloat:
2068 leftUnionArray[i].setIConst(static_cast<int>(node->getFConst(i)));
2069 break;
2070 default:
2071 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
2072 return 0;
2073 }
2074 break;
2075 case EbtUInt:
2076 switch (node->getType().getBasicType()) {
2077 case EbtInt:
2078 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getIConst(i)));
2079 break;
2080 case EbtUInt:
2081 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getUConst(i)));
2082 break;
2083 case EbtBool:
2084 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getBConst(i)));
2085 break;
2086 case EbtFloat:
2087 leftUnionArray[i].setUConst(static_cast<unsigned int>(node->getFConst(i)));
2088 break;
2089 default:
2090 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
2091 return 0;
2092 }
2093 break;
2094 case EbtBool:
2095 switch (node->getType().getBasicType()) {
2096 case EbtInt:
2097 leftUnionArray[i].setBConst(node->getIConst(i) != 0);
2098 break;
2099 case EbtUInt:
2100 leftUnionArray[i].setBConst(node->getUConst(i) != 0);
2101 break;
2102 case EbtBool:
2103 leftUnionArray[i].setBConst(node->getBConst(i));
2104 break;
2105 case EbtFloat:
2106 leftUnionArray[i].setBConst(node->getFConst(i) != 0.0f);
2107 break;
2108 default:
2109 infoSink.info.message(EPrefixInternalError, "Cannot promote", node->getLine());
2110 return 0;
2111 }
John Bauman66b8ab22014-05-06 15:57:45 -04002112
Nicolas Capens0bac2852016-05-07 06:09:58 -04002113 break;
2114 default:
2115 infoSink.info.message(EPrefixInternalError, "Incorrect data type found", node->getLine());
2116 return 0;
2117 }
John Bauman66b8ab22014-05-06 15:57:45 -04002118
Nicolas Capens0bac2852016-05-07 06:09:58 -04002119 }
John Bauman66b8ab22014-05-06 15:57:45 -04002120
Nicolas Capens0bac2852016-05-07 06:09:58 -04002121 const TType& t = node->getType();
John Bauman66b8ab22014-05-06 15:57:45 -04002122
Alexis Hetub14178b2015-04-13 13:23:20 -04002123 return addConstantUnion(leftUnionArray, TType(promoteTo, t.getPrecision(), t.getQualifier(), t.getNominalSize(), t.getSecondarySize(), t.isArray()), node->getLine());
John Bauman66b8ab22014-05-06 15:57:45 -04002124}
2125