1 //
2 // Copyright (C) 2002-2005 3Dlabs Inc. Ltd.
3 // Copyright (C) 2012-2015 LunarG, Inc.
4 // Copyright (C) 2015-2018 Google, Inc.
5 // Copyright (C) 2017 ARM Limited.
6 //
7 // All rights reserved.
8 //
9 // Redistribution and use in source and binary forms, with or without
10 // modification, are permitted provided that the following conditions
11 // are met:
12 //
13 // Redistributions of source code must retain the above copyright
14 // notice, this list of conditions and the following disclaimer.
15 //
16 // Redistributions in binary form must reproduce the above
17 // copyright notice, this list of conditions and the following
18 // disclaimer in the documentation and/or other materials provided
19 // with the distribution.
20 //
21 // Neither the name of 3Dlabs Inc. Ltd. nor the names of its
22 // contributors may be used to endorse or promote products derived
23 // from this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
28 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
29 // COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
30 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
31 // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
32 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
33 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
35 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 // POSSIBILITY OF SUCH DAMAGE.
37 //
38
39 //
40 // Build the intermediate representation.
41 //
42
43 #include "localintermediate.h"
44 #include "RemoveTree.h"
45 #include "SymbolTable.h"
46 #include "propagateNoContraction.h"
47
48 #include <cfloat>
49 #include <utility>
50 #include <tuple>
51
52 namespace glslang {
53
54 ////////////////////////////////////////////////////////////////////////////
55 //
56 // First set of functions are to help build the intermediate representation.
57 // These functions are not member functions of the nodes.
58 // They are called from parser productions.
59 //
60 /////////////////////////////////////////////////////////////////////////////
61
62 //
63 // Add a terminal node for an identifier in an expression.
64 //
65 // Returns the added node.
66 //
67
addSymbol(int id,const TString & name,const TType & type,const TConstUnionArray & constArray,TIntermTyped * constSubtree,const TSourceLoc & loc)68 TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, const TConstUnionArray& constArray,
69 TIntermTyped* constSubtree, const TSourceLoc& loc)
70 {
71 TIntermSymbol* node = new TIntermSymbol(id, name, type);
72 node->setLoc(loc);
73 node->setConstArray(constArray);
74 node->setConstSubtree(constSubtree);
75
76 return node;
77 }
78
addSymbol(const TIntermSymbol & intermSymbol)79 TIntermSymbol* TIntermediate::addSymbol(const TIntermSymbol& intermSymbol)
80 {
81 return addSymbol(intermSymbol.getId(),
82 intermSymbol.getName(),
83 intermSymbol.getType(),
84 intermSymbol.getConstArray(),
85 intermSymbol.getConstSubtree(),
86 intermSymbol.getLoc());
87 }
88
addSymbol(const TVariable & variable)89 TIntermSymbol* TIntermediate::addSymbol(const TVariable& variable)
90 {
91 glslang::TSourceLoc loc; // just a null location
92 loc.init();
93
94 return addSymbol(variable, loc);
95 }
96
addSymbol(const TVariable & variable,const TSourceLoc & loc)97 TIntermSymbol* TIntermediate::addSymbol(const TVariable& variable, const TSourceLoc& loc)
98 {
99 return addSymbol(variable.getUniqueId(), variable.getName(), variable.getType(), variable.getConstArray(), variable.getConstSubtree(), loc);
100 }
101
addSymbol(const TType & type,const TSourceLoc & loc)102 TIntermSymbol* TIntermediate::addSymbol(const TType& type, const TSourceLoc& loc)
103 {
104 TConstUnionArray unionArray; // just a null constant
105
106 return addSymbol(0, "", type, unionArray, nullptr, loc);
107 }
108
109 //
110 // Connect two nodes with a new parent that does a binary operation on the nodes.
111 //
112 // Returns the added node.
113 //
114 // Returns nullptr if the working conversions and promotions could not be found.
115 //
addBinaryMath(TOperator op,TIntermTyped * left,TIntermTyped * right,TSourceLoc loc)116 TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc loc)
117 {
118 // No operations work on blocks
119 if (left->getType().getBasicType() == EbtBlock || right->getType().getBasicType() == EbtBlock)
120 return nullptr;
121
122 // Try converting the children's base types to compatible types.
123 auto children = addConversion(op, left, right);
124 left = std::get<0>(children);
125 right = std::get<1>(children);
126
127 if (left == nullptr || right == nullptr)
128 return nullptr;
129
130 // Convert the children's type shape to be compatible.
131 addBiShapeConversion(op, left, right);
132 if (left == nullptr || right == nullptr)
133 return nullptr;
134
135 //
136 // Need a new node holding things together. Make
137 // one and promote it to the right type.
138 //
139 TIntermBinary* node = addBinaryNode(op, left, right, loc);
140 if (! promote(node))
141 return nullptr;
142
143 node->updatePrecision();
144
145 //
146 // If they are both (non-specialization) constants, they must be folded.
147 // (Unless it's the sequence (comma) operator, but that's handled in addComma().)
148 //
149 TIntermConstantUnion *leftTempConstant = node->getLeft()->getAsConstantUnion();
150 TIntermConstantUnion *rightTempConstant = node->getRight()->getAsConstantUnion();
151 if (leftTempConstant && rightTempConstant) {
152 TIntermTyped* folded = leftTempConstant->fold(node->getOp(), rightTempConstant);
153 if (folded)
154 return folded;
155 }
156
157 // If can propagate spec-constantness and if the operation is an allowed
158 // specialization-constant operation, make a spec-constant.
159 if (specConstantPropagates(*node->getLeft(), *node->getRight()) && isSpecializationOperation(*node))
160 node->getWritableType().getQualifier().makeSpecConstant();
161
162 // If must propagate nonuniform, make a nonuniform.
163 if ((node->getLeft()->getQualifier().nonUniform || node->getRight()->getQualifier().nonUniform) &&
164 isNonuniformPropagating(node->getOp()))
165 node->getWritableType().getQualifier().nonUniform = true;
166
167 return node;
168 }
169
170 //
171 // Low level: add binary node (no promotions or other argument modifications)
172 //
addBinaryNode(TOperator op,TIntermTyped * left,TIntermTyped * right,TSourceLoc loc) const173 TIntermBinary* TIntermediate::addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc loc) const
174 {
175 // build the node
176 TIntermBinary* node = new TIntermBinary(op);
177 if (loc.line == 0)
178 loc = left->getLoc();
179 node->setLoc(loc);
180 node->setLeft(left);
181 node->setRight(right);
182
183 return node;
184 }
185
186 //
187 // like non-type form, but sets node's type.
188 //
addBinaryNode(TOperator op,TIntermTyped * left,TIntermTyped * right,TSourceLoc loc,const TType & type) const189 TIntermBinary* TIntermediate::addBinaryNode(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc loc, const TType& type) const
190 {
191 TIntermBinary* node = addBinaryNode(op, left, right, loc);
192 node->setType(type);
193 return node;
194 }
195
196 //
197 // Low level: add unary node (no promotions or other argument modifications)
198 //
addUnaryNode(TOperator op,TIntermTyped * child,TSourceLoc loc) const199 TIntermUnary* TIntermediate::addUnaryNode(TOperator op, TIntermTyped* child, TSourceLoc loc) const
200 {
201 TIntermUnary* node = new TIntermUnary(op);
202 if (loc.line == 0)
203 loc = child->getLoc();
204 node->setLoc(loc);
205 node->setOperand(child);
206
207 return node;
208 }
209
210 //
211 // like non-type form, but sets node's type.
212 //
addUnaryNode(TOperator op,TIntermTyped * child,TSourceLoc loc,const TType & type) const213 TIntermUnary* TIntermediate::addUnaryNode(TOperator op, TIntermTyped* child, TSourceLoc loc, const TType& type) const
214 {
215 TIntermUnary* node = addUnaryNode(op, child, loc);
216 node->setType(type);
217 return node;
218 }
219
220 //
221 // Connect two nodes through an assignment.
222 //
223 // Returns the added node.
224 //
225 // Returns nullptr if the 'right' type could not be converted to match the 'left' type,
226 // or the resulting operation cannot be properly promoted.
227 //
addAssign(TOperator op,TIntermTyped * left,TIntermTyped * right,TSourceLoc loc)228 TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc loc)
229 {
230 // No block assignment
231 if (left->getType().getBasicType() == EbtBlock || right->getType().getBasicType() == EbtBlock)
232 return nullptr;
233
234 //
235 // Like adding binary math, except the conversion can only go
236 // from right to left.
237 //
238
239 // convert base types, nullptr return means not possible
240 right = addConversion(op, left->getType(), right);
241 if (right == nullptr)
242 return nullptr;
243
244 // convert shape
245 right = addUniShapeConversion(op, left->getType(), right);
246
247 // build the node
248 TIntermBinary* node = addBinaryNode(op, left, right, loc);
249
250 if (! promote(node))
251 return nullptr;
252
253 node->updatePrecision();
254
255 return node;
256 }
257
258 //
259 // Connect two nodes through an index operator, where the left node is the base
260 // of an array or struct, and the right node is a direct or indirect offset.
261 //
262 // Returns the added node.
263 // The caller should set the type of the returned node.
264 //
addIndex(TOperator op,TIntermTyped * base,TIntermTyped * index,TSourceLoc loc)265 TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc loc)
266 {
267 // caller should set the type
268 return addBinaryNode(op, base, index, loc);
269 }
270
271 //
272 // Add one node as the parent of another that it operates on.
273 //
274 // Returns the added node.
275 //
addUnaryMath(TOperator op,TIntermTyped * child,TSourceLoc loc)276 TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermTyped* child, TSourceLoc loc)
277 {
278 if (child == 0)
279 return nullptr;
280
281 if (child->getType().getBasicType() == EbtBlock)
282 return nullptr;
283
284 switch (op) {
285 case EOpLogicalNot:
286 if (source == EShSourceHlsl) {
287 break; // HLSL can promote logical not
288 }
289
290 if (child->getType().getBasicType() != EbtBool || child->getType().isMatrix() || child->getType().isArray() || child->getType().isVector()) {
291 return nullptr;
292 }
293 break;
294
295 case EOpPostIncrement:
296 case EOpPreIncrement:
297 case EOpPostDecrement:
298 case EOpPreDecrement:
299 case EOpNegative:
300 if (child->getType().getBasicType() == EbtStruct || child->getType().isArray())
301 return nullptr;
302 default: break; // some compilers want this
303 }
304
305 //
306 // Do we need to promote the operand?
307 //
308 TBasicType newType = EbtVoid;
309 switch (op) {
310 case EOpConstructInt8: newType = EbtInt8; break;
311 case EOpConstructUint8: newType = EbtUint8; break;
312 case EOpConstructInt16: newType = EbtInt16; break;
313 case EOpConstructUint16: newType = EbtUint16; break;
314 case EOpConstructInt: newType = EbtInt; break;
315 case EOpConstructUint: newType = EbtUint; break;
316 case EOpConstructInt64: newType = EbtInt64; break;
317 case EOpConstructUint64: newType = EbtUint64; break;
318 case EOpConstructBool: newType = EbtBool; break;
319 case EOpConstructFloat: newType = EbtFloat; break;
320 case EOpConstructDouble: newType = EbtDouble; break;
321 case EOpConstructFloat16: newType = EbtFloat16; break;
322 default: break; // some compilers want this
323 }
324
325 if (newType != EbtVoid) {
326 child = addConversion(op, TType(newType, EvqTemporary, child->getVectorSize(),
327 child->getMatrixCols(),
328 child->getMatrixRows(),
329 child->isVector()),
330 child);
331 if (child == nullptr)
332 return nullptr;
333 }
334
335 //
336 // For constructors, we are now done, it was all in the conversion.
337 // TODO: but, did this bypass constant folding?
338 //
339 switch (op) {
340 case EOpConstructInt8:
341 case EOpConstructUint8:
342 case EOpConstructInt16:
343 case EOpConstructUint16:
344 case EOpConstructInt:
345 case EOpConstructUint:
346 case EOpConstructInt64:
347 case EOpConstructUint64:
348 case EOpConstructBool:
349 case EOpConstructFloat:
350 case EOpConstructDouble:
351 case EOpConstructFloat16:
352 return child;
353 default: break; // some compilers want this
354 }
355
356 //
357 // Make a new node for the operator.
358 //
359 TIntermUnary* node = addUnaryNode(op, child, loc);
360
361 if (! promote(node))
362 return nullptr;
363
364 node->updatePrecision();
365
366 // If it's a (non-specialization) constant, it must be folded.
367 if (node->getOperand()->getAsConstantUnion())
368 return node->getOperand()->getAsConstantUnion()->fold(op, node->getType());
369
370 // If it's a specialization constant, the result is too,
371 // if the operation is allowed for specialization constants.
372 if (node->getOperand()->getType().getQualifier().isSpecConstant() && isSpecializationOperation(*node))
373 node->getWritableType().getQualifier().makeSpecConstant();
374
375 // If must propagate nonuniform, make a nonuniform.
376 if (node->getOperand()->getQualifier().nonUniform && isNonuniformPropagating(node->getOp()))
377 node->getWritableType().getQualifier().nonUniform = true;
378
379 return node;
380 }
381
addBuiltInFunctionCall(const TSourceLoc & loc,TOperator op,bool unary,TIntermNode * childNode,const TType & returnType)382 TIntermTyped* TIntermediate::addBuiltInFunctionCall(const TSourceLoc& loc, TOperator op, bool unary,
383 TIntermNode* childNode, const TType& returnType)
384 {
385 if (unary) {
386 //
387 // Treat it like a unary operator.
388 // addUnaryMath() should get the type correct on its own;
389 // including constness (which would differ from the prototype).
390 //
391 TIntermTyped* child = childNode->getAsTyped();
392 if (child == nullptr)
393 return nullptr;
394
395 if (child->getAsConstantUnion()) {
396 TIntermTyped* folded = child->getAsConstantUnion()->fold(op, returnType);
397 if (folded)
398 return folded;
399 }
400
401 return addUnaryNode(op, child, child->getLoc(), returnType);
402 } else {
403 // setAggregateOperater() calls fold() for constant folding
404 TIntermTyped* node = setAggregateOperator(childNode, op, returnType, loc);
405
406 return node;
407 }
408 }
409
410 //
411 // This is the safe way to change the operator on an aggregate, as it
412 // does lots of error checking and fixing. Especially for establishing
413 // a function call's operation on it's set of parameters. Sequences
414 // of instructions are also aggregates, but they just directly set
415 // their operator to EOpSequence.
416 //
417 // Returns an aggregate node, which could be the one passed in if
418 // it was already an aggregate.
419 //
setAggregateOperator(TIntermNode * node,TOperator op,const TType & type,TSourceLoc loc)420 TIntermTyped* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator op, const TType& type, TSourceLoc loc)
421 {
422 TIntermAggregate* aggNode;
423
424 //
425 // Make sure we have an aggregate. If not turn it into one.
426 //
427 if (node != nullptr) {
428 aggNode = node->getAsAggregate();
429 if (aggNode == nullptr || aggNode->getOp() != EOpNull) {
430 //
431 // Make an aggregate containing this node.
432 //
433 aggNode = new TIntermAggregate();
434 aggNode->getSequence().push_back(node);
435 if (loc.line == 0)
436 loc = node->getLoc();
437 }
438 } else
439 aggNode = new TIntermAggregate();
440
441 //
442 // Set the operator.
443 //
444 aggNode->setOperator(op);
445 if (loc.line != 0)
446 aggNode->setLoc(loc);
447
448 aggNode->setType(type);
449
450 return fold(aggNode);
451 }
452
isConversionAllowed(TOperator op,TIntermTyped * node) const453 bool TIntermediate::isConversionAllowed(TOperator op, TIntermTyped* node) const
454 {
455 //
456 // Does the base type even allow the operation?
457 //
458 switch (node->getBasicType()) {
459 case EbtVoid:
460 return false;
461 case EbtAtomicUint:
462 case EbtSampler:
463 #ifdef NV_EXTENSIONS
464 case EbtAccStructNV:
465 #endif
466 // opaque types can be passed to functions
467 if (op == EOpFunction)
468 break;
469
470 // HLSL can assign samplers directly (no constructor)
471 if (source == EShSourceHlsl && node->getBasicType() == EbtSampler)
472 break;
473
474 // samplers can get assigned via a sampler constructor
475 // (well, not yet, but code in the rest of this function is ready for it)
476 if (node->getBasicType() == EbtSampler && op == EOpAssign &&
477 node->getAsOperator() != nullptr && node->getAsOperator()->getOp() == EOpConstructTextureSampler)
478 break;
479
480 // otherwise, opaque types can't even be operated on, let alone converted
481 return false;
482 default:
483 break;
484 }
485
486 return true;
487 }
488
489 // This is 'mechanism' here, it does any conversion told.
490 // It is about basic type, not about shape.
491 // The policy comes from the shader or the calling code.
createConversion(TBasicType convertTo,TIntermTyped * node) const492 TIntermTyped* TIntermediate::createConversion(TBasicType convertTo, TIntermTyped* node) const
493 {
494 //
495 // Add a new newNode for the conversion.
496 //
497 TIntermUnary* newNode = nullptr;
498
499 TOperator newOp = EOpNull;
500
501 switch (convertTo) {
502 case EbtDouble:
503 switch (node->getBasicType()) {
504 case EbtInt8: newOp = EOpConvInt8ToDouble; break;
505 case EbtUint8: newOp = EOpConvUint8ToDouble; break;
506 case EbtInt16: newOp = EOpConvInt16ToDouble; break;
507 case EbtUint16: newOp = EOpConvUint16ToDouble; break;
508 case EbtInt: newOp = EOpConvIntToDouble; break;
509 case EbtUint: newOp = EOpConvUintToDouble; break;
510 case EbtBool: newOp = EOpConvBoolToDouble; break;
511 case EbtFloat: newOp = EOpConvFloatToDouble; break;
512 case EbtFloat16: newOp = EOpConvFloat16ToDouble; break;
513 case EbtInt64: newOp = EOpConvInt64ToDouble; break;
514 case EbtUint64: newOp = EOpConvUint64ToDouble; break;
515 default:
516 return nullptr;
517 }
518 break;
519 case EbtFloat:
520 switch (node->getBasicType()) {
521 case EbtInt8: newOp = EOpConvInt8ToFloat; break;
522 case EbtUint8: newOp = EOpConvUint8ToFloat; break;
523 case EbtInt16: newOp = EOpConvInt16ToFloat; break;
524 case EbtUint16: newOp = EOpConvUint16ToFloat; break;
525 case EbtInt: newOp = EOpConvIntToFloat; break;
526 case EbtUint: newOp = EOpConvUintToFloat; break;
527 case EbtBool: newOp = EOpConvBoolToFloat; break;
528 case EbtDouble: newOp = EOpConvDoubleToFloat; break;
529 case EbtFloat16: newOp = EOpConvFloat16ToFloat; break;
530 case EbtInt64: newOp = EOpConvInt64ToFloat; break;
531 case EbtUint64: newOp = EOpConvUint64ToFloat; break;
532 default:
533 return nullptr;
534 }
535 break;
536 case EbtFloat16:
537 switch (node->getBasicType()) {
538 case EbtInt8: newOp = EOpConvInt8ToFloat16; break;
539 case EbtUint8: newOp = EOpConvUint8ToFloat16; break;
540 case EbtInt16: newOp = EOpConvInt16ToFloat16; break;
541 case EbtUint16: newOp = EOpConvUint16ToFloat16; break;
542 case EbtInt: newOp = EOpConvIntToFloat16; break;
543 case EbtUint: newOp = EOpConvUintToFloat16; break;
544 case EbtBool: newOp = EOpConvBoolToFloat16; break;
545 case EbtFloat: newOp = EOpConvFloatToFloat16; break;
546 case EbtDouble: newOp = EOpConvDoubleToFloat16; break;
547 case EbtInt64: newOp = EOpConvInt64ToFloat16; break;
548 case EbtUint64: newOp = EOpConvUint64ToFloat16; break;
549 default:
550 return nullptr;
551 }
552 break;
553 case EbtBool:
554 switch (node->getBasicType()) {
555 case EbtInt8: newOp = EOpConvInt8ToBool; break;
556 case EbtUint8: newOp = EOpConvUint8ToBool; break;
557 case EbtInt16: newOp = EOpConvInt16ToBool; break;
558 case EbtUint16: newOp = EOpConvUint16ToBool; break;
559 case EbtInt: newOp = EOpConvIntToBool; break;
560 case EbtUint: newOp = EOpConvUintToBool; break;
561 case EbtFloat: newOp = EOpConvFloatToBool; break;
562 case EbtDouble: newOp = EOpConvDoubleToBool; break;
563 case EbtFloat16: newOp = EOpConvFloat16ToBool; break;
564 case EbtInt64: newOp = EOpConvInt64ToBool; break;
565 case EbtUint64: newOp = EOpConvUint64ToBool; break;
566 default:
567 return nullptr;
568 }
569 break;
570 case EbtInt8:
571 switch (node->getBasicType()) {
572 case EbtUint8: newOp = EOpConvUint8ToInt8; break;
573 case EbtInt16: newOp = EOpConvInt16ToInt8; break;
574 case EbtUint16: newOp = EOpConvUint16ToInt8; break;
575 case EbtInt: newOp = EOpConvIntToInt8; break;
576 case EbtUint: newOp = EOpConvUintToInt8; break;
577 case EbtInt64: newOp = EOpConvInt64ToInt8; break;
578 case EbtUint64: newOp = EOpConvUint64ToInt8; break;
579 case EbtBool: newOp = EOpConvBoolToInt8; break;
580 case EbtFloat: newOp = EOpConvFloatToInt8; break;
581 case EbtDouble: newOp = EOpConvDoubleToInt8; break;
582 case EbtFloat16: newOp = EOpConvFloat16ToInt8; break;
583 default:
584 return nullptr;
585 }
586 break;
587 case EbtUint8:
588 switch (node->getBasicType()) {
589 case EbtInt8: newOp = EOpConvInt8ToUint8; break;
590 case EbtInt16: newOp = EOpConvInt16ToUint8; break;
591 case EbtUint16: newOp = EOpConvUint16ToUint8; break;
592 case EbtInt: newOp = EOpConvIntToUint8; break;
593 case EbtUint: newOp = EOpConvUintToUint8; break;
594 case EbtInt64: newOp = EOpConvInt64ToUint8; break;
595 case EbtUint64: newOp = EOpConvUint64ToUint8; break;
596 case EbtBool: newOp = EOpConvBoolToUint8; break;
597 case EbtFloat: newOp = EOpConvFloatToUint8; break;
598 case EbtDouble: newOp = EOpConvDoubleToUint8; break;
599 case EbtFloat16: newOp = EOpConvFloat16ToUint8; break;
600 default:
601 return nullptr;
602 }
603 break;
604
605 case EbtInt16:
606 switch (node->getBasicType()) {
607 case EbtUint8: newOp = EOpConvUint8ToInt16; break;
608 case EbtInt8: newOp = EOpConvInt8ToInt16; break;
609 case EbtUint16: newOp = EOpConvUint16ToInt16; break;
610 case EbtInt: newOp = EOpConvIntToInt16; break;
611 case EbtUint: newOp = EOpConvUintToInt16; break;
612 case EbtInt64: newOp = EOpConvInt64ToInt16; break;
613 case EbtUint64: newOp = EOpConvUint64ToInt16; break;
614 case EbtBool: newOp = EOpConvBoolToInt16; break;
615 case EbtFloat: newOp = EOpConvFloatToInt16; break;
616 case EbtDouble: newOp = EOpConvDoubleToInt16; break;
617 case EbtFloat16: newOp = EOpConvFloat16ToInt16; break;
618 default:
619 return nullptr;
620 }
621 break;
622 case EbtUint16:
623 switch (node->getBasicType()) {
624 case EbtInt8: newOp = EOpConvInt8ToUint16; break;
625 case EbtUint8: newOp = EOpConvUint8ToUint16; break;
626 case EbtInt16: newOp = EOpConvInt16ToUint16; break;
627 case EbtInt: newOp = EOpConvIntToUint16; break;
628 case EbtUint: newOp = EOpConvUintToUint16; break;
629 case EbtInt64: newOp = EOpConvInt64ToUint16; break;
630 case EbtUint64: newOp = EOpConvUint64ToUint16; break;
631 case EbtBool: newOp = EOpConvBoolToUint16; break;
632 case EbtFloat: newOp = EOpConvFloatToUint16; break;
633 case EbtDouble: newOp = EOpConvDoubleToUint16; break;
634 case EbtFloat16: newOp = EOpConvFloat16ToUint16; break;
635 default:
636 return nullptr;
637 }
638 break;
639
640 case EbtInt:
641 switch (node->getBasicType()) {
642 case EbtInt8: newOp = EOpConvInt8ToInt; break;
643 case EbtUint8: newOp = EOpConvUint8ToInt; break;
644 case EbtInt16: newOp = EOpConvInt16ToInt; break;
645 case EbtUint16: newOp = EOpConvUint16ToInt; break;
646 case EbtUint: newOp = EOpConvUintToInt; break;
647 case EbtBool: newOp = EOpConvBoolToInt; break;
648 case EbtFloat: newOp = EOpConvFloatToInt; break;
649 case EbtDouble: newOp = EOpConvDoubleToInt; break;
650 case EbtFloat16: newOp = EOpConvFloat16ToInt; break;
651 case EbtInt64: newOp = EOpConvInt64ToInt; break;
652 case EbtUint64: newOp = EOpConvUint64ToInt; break;
653 default:
654 return nullptr;
655 }
656 break;
657 case EbtUint:
658 switch (node->getBasicType()) {
659 case EbtInt8: newOp = EOpConvInt8ToUint; break;
660 case EbtUint8: newOp = EOpConvUint8ToUint; break;
661 case EbtInt16: newOp = EOpConvInt16ToUint; break;
662 case EbtUint16: newOp = EOpConvUint16ToUint; break;
663 case EbtInt: newOp = EOpConvIntToUint; break;
664 case EbtBool: newOp = EOpConvBoolToUint; break;
665 case EbtFloat: newOp = EOpConvFloatToUint; break;
666 case EbtDouble: newOp = EOpConvDoubleToUint; break;
667 case EbtFloat16: newOp = EOpConvFloat16ToUint; break;
668 case EbtInt64: newOp = EOpConvInt64ToUint; break;
669 case EbtUint64: newOp = EOpConvUint64ToUint; break;
670 default:
671 return nullptr;
672 }
673 break;
674 case EbtInt64:
675 switch (node->getBasicType()) {
676 case EbtInt8: newOp = EOpConvInt8ToInt64; break;
677 case EbtUint8: newOp = EOpConvUint8ToInt64; break;
678 case EbtInt16: newOp = EOpConvInt16ToInt64; break;
679 case EbtUint16: newOp = EOpConvUint16ToInt64; break;
680 case EbtInt: newOp = EOpConvIntToInt64; break;
681 case EbtUint: newOp = EOpConvUintToInt64; break;
682 case EbtBool: newOp = EOpConvBoolToInt64; break;
683 case EbtFloat: newOp = EOpConvFloatToInt64; break;
684 case EbtDouble: newOp = EOpConvDoubleToInt64; break;
685 case EbtFloat16: newOp = EOpConvFloat16ToInt64; break;
686 case EbtUint64: newOp = EOpConvUint64ToInt64; break;
687 default:
688 return nullptr;
689 }
690 break;
691 case EbtUint64:
692 switch (node->getBasicType()) {
693 case EbtInt8: newOp = EOpConvInt8ToUint64; break;
694 case EbtUint8: newOp = EOpConvUint8ToUint64; break;
695 case EbtInt16: newOp = EOpConvInt16ToUint64; break;
696 case EbtUint16: newOp = EOpConvUint16ToUint64; break;
697 case EbtInt: newOp = EOpConvIntToUint64; break;
698 case EbtUint: newOp = EOpConvUintToUint64; break;
699 case EbtBool: newOp = EOpConvBoolToUint64; break;
700 case EbtFloat: newOp = EOpConvFloatToUint64; break;
701 case EbtDouble: newOp = EOpConvDoubleToUint64; break;
702 case EbtFloat16: newOp = EOpConvFloat16ToUint64; break;
703 case EbtInt64: newOp = EOpConvInt64ToUint64; break;
704 default:
705 return nullptr;
706 }
707 break;
708 default:
709 return nullptr;
710 }
711
712 TType newType(convertTo, EvqTemporary, node->getVectorSize(), node->getMatrixCols(), node->getMatrixRows());
713 newNode = addUnaryNode(newOp, node, node->getLoc(), newType);
714
715 if (node->getAsConstantUnion()) {
716 TIntermTyped* folded = node->getAsConstantUnion()->fold(newOp, newType);
717 if (folded)
718 return folded;
719 }
720
721 // Propagate specialization-constant-ness, if allowed
722 if (node->getType().getQualifier().isSpecConstant() && isSpecializationOperation(*newNode))
723 newNode->getWritableType().getQualifier().makeSpecConstant();
724
725 return newNode;
726 }
727
728 // For converting a pair of operands to a binary operation to compatible
729 // types with each other, relative to the operation in 'op'.
730 // This does not cover assignment operations, which is asymmetric in that the
731 // left type is not changeable.
732 // See addConversion(op, type, node) for assignments and unary operation
733 // conversions.
734 //
735 // Generally, this is focused on basic type conversion, not shape conversion.
736 // See addShapeConversion() for shape conversions.
737 //
738 // Returns the converted pair of nodes.
739 // Returns <nullptr, nullptr> when there is no conversion.
740 std::tuple<TIntermTyped*, TIntermTyped*>
addConversion(TOperator op,TIntermTyped * node0,TIntermTyped * node1) const741 TIntermediate::addConversion(TOperator op, TIntermTyped* node0, TIntermTyped* node1) const
742 {
743 if (!isConversionAllowed(op, node0) || !isConversionAllowed(op, node1))
744 return std::make_tuple(nullptr, nullptr);
745
746 if (node0->getType() != node1->getType()) {
747 // If differing structure, then no conversions.
748 if (node0->isStruct() || node1->isStruct())
749 return std::make_tuple(nullptr, nullptr);
750
751 // If differing arrays, then no conversions.
752 if (node0->getType().isArray() || node1->getType().isArray())
753 return std::make_tuple(nullptr, nullptr);
754 }
755
756 auto promoteTo = std::make_tuple(EbtNumTypes, EbtNumTypes);
757
758 switch (op) {
759 //
760 // List all the binary ops that can implicitly convert one operand to the other's type;
761 // This implements the 'policy' for implicit type conversion.
762 //
763 case EOpLessThan:
764 case EOpGreaterThan:
765 case EOpLessThanEqual:
766 case EOpGreaterThanEqual:
767 case EOpEqual:
768 case EOpNotEqual:
769
770 case EOpAdd:
771 case EOpSub:
772 case EOpMul:
773 case EOpDiv:
774 case EOpMod:
775
776 case EOpVectorTimesScalar:
777 case EOpVectorTimesMatrix:
778 case EOpMatrixTimesVector:
779 case EOpMatrixTimesScalar:
780
781 case EOpAnd:
782 case EOpInclusiveOr:
783 case EOpExclusiveOr:
784
785 case EOpSequence: // used by ?:
786
787 if (node0->getBasicType() == node1->getBasicType())
788 return std::make_tuple(node0, node1);
789
790 promoteTo = getConversionDestinatonType(node0->getBasicType(), node1->getBasicType(), op);
791 if (std::get<0>(promoteTo) == EbtNumTypes || std::get<1>(promoteTo) == EbtNumTypes)
792 return std::make_tuple(nullptr, nullptr);
793
794 break;
795
796 case EOpLogicalAnd:
797 case EOpLogicalOr:
798 case EOpLogicalXor:
799 if (source == EShSourceHlsl)
800 promoteTo = std::make_tuple(EbtBool, EbtBool);
801 else
802 return std::make_tuple(node0, node1);
803 break;
804
805 // There are no conversions needed for GLSL; the shift amount just needs to be an
806 // integer type, as does the base.
807 // HLSL can promote bools to ints to make this work.
808 case EOpLeftShift:
809 case EOpRightShift:
810 if (source == EShSourceHlsl) {
811 TBasicType node0BasicType = node0->getBasicType();
812 if (node0BasicType == EbtBool)
813 node0BasicType = EbtInt;
814 if (node1->getBasicType() == EbtBool)
815 promoteTo = std::make_tuple(node0BasicType, EbtInt);
816 else
817 promoteTo = std::make_tuple(node0BasicType, node1->getBasicType());
818 } else {
819 if (isTypeInt(node0->getBasicType()) && isTypeInt(node1->getBasicType()))
820 return std::make_tuple(node0, node1);
821 else
822 return std::make_tuple(nullptr, nullptr);
823 }
824 break;
825
826 default:
827 if (node0->getType() == node1->getType())
828 return std::make_tuple(node0, node1);
829
830 return std::make_tuple(nullptr, nullptr);
831 }
832
833 TIntermTyped* newNode0;
834 TIntermTyped* newNode1;
835
836 if (std::get<0>(promoteTo) != node0->getType().getBasicType()) {
837 if (node0->getAsConstantUnion())
838 newNode0 = promoteConstantUnion(std::get<0>(promoteTo), node0->getAsConstantUnion());
839 else
840 newNode0 = createConversion(std::get<0>(promoteTo), node0);
841 } else
842 newNode0 = node0;
843
844 if (std::get<1>(promoteTo) != node1->getType().getBasicType()) {
845 if (node1->getAsConstantUnion())
846 newNode1 = promoteConstantUnion(std::get<1>(promoteTo), node1->getAsConstantUnion());
847 else
848 newNode1 = createConversion(std::get<1>(promoteTo), node1);
849 } else
850 newNode1 = node1;
851
852 return std::make_tuple(newNode0, newNode1);
853 }
854
855 //
856 // Convert the node's type to the given type, as allowed by the operation involved: 'op'.
857 // For implicit conversions, 'op' is not the requested conversion, it is the explicit
858 // operation requiring the implicit conversion.
859 //
860 // Binary operation conversions should be handled by addConversion(op, node, node), not here.
861 //
862 // Returns a node representing the conversion, which could be the same
863 // node passed in if no conversion was needed.
864 //
865 // Generally, this is focused on basic type conversion, not shape conversion.
866 // See addShapeConversion() for shape conversions.
867 //
868 // Return nullptr if a conversion can't be done.
869 //
addConversion(TOperator op,const TType & type,TIntermTyped * node) const870 TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TIntermTyped* node) const
871 {
872 if (!isConversionAllowed(op, node))
873 return nullptr;
874
875 // Otherwise, if types are identical, no problem
876 if (type == node->getType())
877 return node;
878
879 // If one's a structure, then no conversions.
880 if (type.isStruct() || node->isStruct())
881 return nullptr;
882
883 // If one's an array, then no conversions.
884 if (type.isArray() || node->getType().isArray())
885 return nullptr;
886
887 // Note: callers are responsible for other aspects of shape,
888 // like vector and matrix sizes.
889
890 TBasicType promoteTo;
891 // GL_EXT_shader_16bit_storage can't do OpConstantComposite with
892 // 16-bit types, so disable promotion for those types.
893 bool canPromoteConstant = true;
894
895 switch (op) {
896 //
897 // Explicit conversions (unary operations)
898 //
899 case EOpConstructBool:
900 promoteTo = EbtBool;
901 break;
902 case EOpConstructFloat:
903 promoteTo = EbtFloat;
904 break;
905 case EOpConstructDouble:
906 promoteTo = EbtDouble;
907 break;
908 case EOpConstructFloat16:
909 promoteTo = EbtFloat16;
910 canPromoteConstant = extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) ||
911 extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_float16);
912 break;
913 case EOpConstructInt8:
914 promoteTo = EbtInt8;
915 canPromoteConstant = extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) ||
916 extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int8);
917 break;
918 case EOpConstructUint8:
919 promoteTo = EbtUint8;
920 canPromoteConstant = extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) ||
921 extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int8);
922 break;
923 case EOpConstructInt16:
924 promoteTo = EbtInt16;
925 canPromoteConstant = extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) ||
926 extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int16);
927 break;
928 case EOpConstructUint16:
929 promoteTo = EbtUint16;
930 canPromoteConstant = extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) ||
931 extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int16);
932 break;
933 case EOpConstructInt:
934 promoteTo = EbtInt;
935 break;
936 case EOpConstructUint:
937 promoteTo = EbtUint;
938 break;
939 case EOpConstructInt64:
940 promoteTo = EbtInt64;
941 break;
942 case EOpConstructUint64:
943 promoteTo = EbtUint64;
944 break;
945
946 case EOpLogicalNot:
947
948 case EOpFunctionCall:
949
950 case EOpReturn:
951 case EOpAssign:
952 case EOpAddAssign:
953 case EOpSubAssign:
954 case EOpMulAssign:
955 case EOpVectorTimesScalarAssign:
956 case EOpMatrixTimesScalarAssign:
957 case EOpDivAssign:
958 case EOpModAssign:
959 case EOpAndAssign:
960 case EOpInclusiveOrAssign:
961 case EOpExclusiveOrAssign:
962
963 case EOpAtan:
964 case EOpClamp:
965 case EOpCross:
966 case EOpDistance:
967 case EOpDot:
968 case EOpDst:
969 case EOpFaceForward:
970 case EOpFma:
971 case EOpFrexp:
972 case EOpLdexp:
973 case EOpMix:
974 case EOpLit:
975 case EOpMax:
976 case EOpMin:
977 case EOpModf:
978 case EOpPow:
979 case EOpReflect:
980 case EOpRefract:
981 case EOpSmoothStep:
982 case EOpStep:
983
984 case EOpSequence:
985 case EOpConstructStruct:
986
987 if (type.getBasicType() == EbtReference || node->getType().getBasicType() == EbtReference) {
988 // types must match to assign a reference
989 if (type == node->getType())
990 return node;
991 else
992 return nullptr;
993 }
994
995 if (type.getBasicType() == node->getType().getBasicType())
996 return node;
997
998 if (canImplicitlyPromote(node->getBasicType(), type.getBasicType(), op))
999 promoteTo = type.getBasicType();
1000 else
1001 return nullptr;
1002 break;
1003
1004 // For GLSL, there are no conversions needed; the shift amount just needs to be an
1005 // integer type, as do the base/result.
1006 // HLSL can convert the shift from a bool to an int.
1007 case EOpLeftShiftAssign:
1008 case EOpRightShiftAssign:
1009 {
1010 if (source == EShSourceHlsl && node->getType().getBasicType() == EbtBool)
1011 promoteTo = type.getBasicType();
1012 else {
1013 if (isTypeInt(type.getBasicType()) && isTypeInt(node->getBasicType()))
1014 return node;
1015 else
1016 return nullptr;
1017 }
1018 break;
1019 }
1020
1021 default:
1022 // default is to require a match; all exceptions should have case statements above
1023
1024 if (type.getBasicType() == node->getType().getBasicType())
1025 return node;
1026 else
1027 return nullptr;
1028 }
1029
1030 if (canPromoteConstant && node->getAsConstantUnion())
1031 return promoteConstantUnion(promoteTo, node->getAsConstantUnion());
1032
1033 //
1034 // Add a new newNode for the conversion.
1035 //
1036 TIntermTyped* newNode = createConversion(promoteTo, node);
1037
1038 return newNode;
1039 }
1040
1041 // Convert the node's shape of type for the given type, as allowed by the
1042 // operation involved: 'op'. This is for situations where there is only one
1043 // direction to consider doing the shape conversion.
1044 //
1045 // This implements policy, it call addShapeConversion() for the mechanism.
1046 //
1047 // Generally, the AST represents allowed GLSL shapes, so this isn't needed
1048 // for GLSL. Bad shapes are caught in conversion or promotion.
1049 //
1050 // Return 'node' if no conversion was done. Promotion handles final shape
1051 // checking.
1052 //
addUniShapeConversion(TOperator op,const TType & type,TIntermTyped * node)1053 TIntermTyped* TIntermediate::addUniShapeConversion(TOperator op, const TType& type, TIntermTyped* node)
1054 {
1055 // some source languages don't do this
1056 switch (source) {
1057 case EShSourceHlsl:
1058 break;
1059 case EShSourceGlsl:
1060 default:
1061 return node;
1062 }
1063
1064 // some operations don't do this
1065 switch (op) {
1066 case EOpFunctionCall:
1067 case EOpReturn:
1068 break;
1069
1070 case EOpMulAssign:
1071 // want to support vector *= scalar native ops in AST and lower, not smear, similarly for
1072 // matrix *= scalar, etc.
1073
1074 case EOpAddAssign:
1075 case EOpSubAssign:
1076 case EOpDivAssign:
1077 case EOpAndAssign:
1078 case EOpInclusiveOrAssign:
1079 case EOpExclusiveOrAssign:
1080 case EOpRightShiftAssign:
1081 case EOpLeftShiftAssign:
1082 if (node->getVectorSize() == 1)
1083 return node;
1084 break;
1085
1086 case EOpAssign:
1087 break;
1088
1089 case EOpMix:
1090 break;
1091
1092 default:
1093 return node;
1094 }
1095
1096 return addShapeConversion(type, node);
1097 }
1098
1099 // Convert the nodes' shapes to be compatible for the operation 'op'.
1100 //
1101 // This implements policy, it call addShapeConversion() for the mechanism.
1102 //
1103 // Generally, the AST represents allowed GLSL shapes, so this isn't needed
1104 // for GLSL. Bad shapes are caught in conversion or promotion.
1105 //
addBiShapeConversion(TOperator op,TIntermTyped * & lhsNode,TIntermTyped * & rhsNode)1106 void TIntermediate::addBiShapeConversion(TOperator op, TIntermTyped*& lhsNode, TIntermTyped*& rhsNode)
1107 {
1108 // some source languages don't do this
1109 switch (source) {
1110 case EShSourceHlsl:
1111 break;
1112 case EShSourceGlsl:
1113 default:
1114 return;
1115 }
1116
1117 // some operations don't do this
1118 // 'break' will mean attempt bidirectional conversion
1119 switch (op) {
1120 case EOpMulAssign:
1121 case EOpAssign:
1122 case EOpAddAssign:
1123 case EOpSubAssign:
1124 case EOpDivAssign:
1125 case EOpAndAssign:
1126 case EOpInclusiveOrAssign:
1127 case EOpExclusiveOrAssign:
1128 case EOpRightShiftAssign:
1129 case EOpLeftShiftAssign:
1130 // switch to unidirectional conversion (the lhs can't change)
1131 rhsNode = addUniShapeConversion(op, lhsNode->getType(), rhsNode);
1132 return;
1133
1134 case EOpMul:
1135 // matrix multiply does not change shapes
1136 if (lhsNode->isMatrix() && rhsNode->isMatrix())
1137 return;
1138 case EOpAdd:
1139 case EOpSub:
1140 case EOpDiv:
1141 // want to support vector * scalar native ops in AST and lower, not smear, similarly for
1142 // matrix * vector, etc.
1143 if (lhsNode->getVectorSize() == 1 || rhsNode->getVectorSize() == 1)
1144 return;
1145 break;
1146
1147 case EOpRightShift:
1148 case EOpLeftShift:
1149 // can natively support the right operand being a scalar and the left a vector,
1150 // but not the reverse
1151 if (rhsNode->getVectorSize() == 1)
1152 return;
1153 break;
1154
1155 case EOpLessThan:
1156 case EOpGreaterThan:
1157 case EOpLessThanEqual:
1158 case EOpGreaterThanEqual:
1159
1160 case EOpEqual:
1161 case EOpNotEqual:
1162
1163 case EOpLogicalAnd:
1164 case EOpLogicalOr:
1165 case EOpLogicalXor:
1166
1167 case EOpAnd:
1168 case EOpInclusiveOr:
1169 case EOpExclusiveOr:
1170
1171 case EOpMix:
1172 break;
1173
1174 default:
1175 return;
1176 }
1177
1178 // Do bidirectional conversions
1179 if (lhsNode->getType().isScalarOrVec1() || rhsNode->getType().isScalarOrVec1()) {
1180 if (lhsNode->getType().isScalarOrVec1())
1181 lhsNode = addShapeConversion(rhsNode->getType(), lhsNode);
1182 else
1183 rhsNode = addShapeConversion(lhsNode->getType(), rhsNode);
1184 }
1185 lhsNode = addShapeConversion(rhsNode->getType(), lhsNode);
1186 rhsNode = addShapeConversion(lhsNode->getType(), rhsNode);
1187 }
1188
1189 // Convert the node's shape of type for the given type, as allowed by the
1190 // operation involved: 'op'.
1191 //
1192 // Generally, the AST represents allowed GLSL shapes, so this isn't needed
1193 // for GLSL. Bad shapes are caught in conversion or promotion.
1194 //
1195 // Return 'node' if no conversion was done. Promotion handles final shape
1196 // checking.
1197 //
addShapeConversion(const TType & type,TIntermTyped * node)1198 TIntermTyped* TIntermediate::addShapeConversion(const TType& type, TIntermTyped* node)
1199 {
1200 // no conversion needed
1201 if (node->getType() == type)
1202 return node;
1203
1204 // structures and arrays don't change shape, either to or from
1205 if (node->getType().isStruct() || node->getType().isArray() ||
1206 type.isStruct() || type.isArray())
1207 return node;
1208
1209 // The new node that handles the conversion
1210 TOperator constructorOp = mapTypeToConstructorOp(type);
1211
1212 if (source == EShSourceHlsl) {
1213 // HLSL rules for scalar, vector and matrix conversions:
1214 // 1) scalar can become anything, initializing every component with its value
1215 // 2) vector and matrix can become scalar, first element is used (warning: truncation)
1216 // 3) matrix can become matrix with less rows and/or columns (warning: truncation)
1217 // 4) vector can become vector with less rows size (warning: truncation)
1218 // 5a) vector 4 can become 2x2 matrix (special case) (same packing layout, its a reinterpret)
1219 // 5b) 2x2 matrix can become vector 4 (special case) (same packing layout, its a reinterpret)
1220
1221 const TType &sourceType = node->getType();
1222
1223 // rule 1 for scalar to matrix is special
1224 if (sourceType.isScalarOrVec1() && type.isMatrix()) {
1225
1226 // HLSL semantics: the scalar (or vec1) is replicated to every component of the matrix. Left to its
1227 // own devices, the constructor from a scalar would populate the diagonal. This forces replication
1228 // to every matrix element.
1229
1230 // Note that if the node is complex (e.g, a function call), we don't want to duplicate it here
1231 // repeatedly, so we copy it to a temp, then use the temp.
1232 const int matSize = type.computeNumComponents();
1233 TIntermAggregate* rhsAggregate = new TIntermAggregate();
1234
1235 const bool isSimple = (node->getAsSymbolNode() != nullptr) || (node->getAsConstantUnion() != nullptr);
1236
1237 if (!isSimple) {
1238 assert(0); // TODO: use node replicator service when available.
1239 }
1240
1241 for (int x = 0; x < matSize; ++x)
1242 rhsAggregate->getSequence().push_back(node);
1243
1244 return setAggregateOperator(rhsAggregate, constructorOp, type, node->getLoc());
1245 }
1246
1247 // rule 1 and 2
1248 if ((sourceType.isScalar() && !type.isScalar()) || (!sourceType.isScalar() && type.isScalar()))
1249 return setAggregateOperator(makeAggregate(node), constructorOp, type, node->getLoc());
1250
1251 // rule 3 and 5b
1252 if (sourceType.isMatrix()) {
1253 // rule 3
1254 if (type.isMatrix()) {
1255 if ((sourceType.getMatrixCols() != type.getMatrixCols() || sourceType.getMatrixRows() != type.getMatrixRows()) &&
1256 sourceType.getMatrixCols() >= type.getMatrixCols() && sourceType.getMatrixRows() >= type.getMatrixRows())
1257 return setAggregateOperator(makeAggregate(node), constructorOp, type, node->getLoc());
1258 // rule 5b
1259 } else if (type.isVector()) {
1260 if (type.getVectorSize() == 4 && sourceType.getMatrixCols() == 2 && sourceType.getMatrixRows() == 2)
1261 return setAggregateOperator(makeAggregate(node), constructorOp, type, node->getLoc());
1262 }
1263 }
1264
1265 // rule 4 and 5a
1266 if (sourceType.isVector()) {
1267 // rule 4
1268 if (type.isVector())
1269 {
1270 if (sourceType.getVectorSize() > type.getVectorSize())
1271 return setAggregateOperator(makeAggregate(node), constructorOp, type, node->getLoc());
1272 // rule 5a
1273 } else if (type.isMatrix()) {
1274 if (sourceType.getVectorSize() == 4 && type.getMatrixCols() == 2 && type.getMatrixRows() == 2)
1275 return setAggregateOperator(makeAggregate(node), constructorOp, type, node->getLoc());
1276 }
1277 }
1278 }
1279
1280 // scalar -> vector or vec1 -> vector or
1281 // vector -> scalar or
1282 // bigger vector -> smaller vector
1283 if ((node->getType().isScalarOrVec1() && type.isVector()) ||
1284 (node->getType().isVector() && type.isScalar()) ||
1285 (node->isVector() && type.isVector() && node->getVectorSize() > type.getVectorSize()))
1286 return setAggregateOperator(makeAggregate(node), constructorOp, type, node->getLoc());
1287
1288 return node;
1289 }
1290
isIntegralPromotion(TBasicType from,TBasicType to) const1291 bool TIntermediate::isIntegralPromotion(TBasicType from, TBasicType to) const
1292 {
1293 // integral promotions
1294 if (to == EbtInt) {
1295 switch(from) {
1296 case EbtInt8:
1297 case EbtInt16:
1298 case EbtUint8:
1299 case EbtUint16:
1300 return true;
1301 default:
1302 break;
1303 }
1304 }
1305 return false;
1306 }
1307
isFPPromotion(TBasicType from,TBasicType to) const1308 bool TIntermediate::isFPPromotion(TBasicType from, TBasicType to) const
1309 {
1310 // floating-point promotions
1311 if (to == EbtDouble) {
1312 switch(from) {
1313 case EbtFloat16:
1314 case EbtFloat:
1315 return true;
1316 default:
1317 break;
1318 }
1319 }
1320 return false;
1321 }
1322
isIntegralConversion(TBasicType from,TBasicType to) const1323 bool TIntermediate::isIntegralConversion(TBasicType from, TBasicType to) const
1324 {
1325 switch (from) {
1326 case EbtInt8:
1327 switch (to) {
1328 case EbtUint8:
1329 case EbtInt16:
1330 case EbtUint16:
1331 case EbtUint:
1332 case EbtInt64:
1333 case EbtUint64:
1334 return true;
1335 default:
1336 break;
1337 }
1338 break;
1339 case EbtUint8:
1340 switch (to) {
1341 case EbtInt16:
1342 case EbtUint16:
1343 case EbtUint:
1344 case EbtInt64:
1345 case EbtUint64:
1346 return true;
1347 default:
1348 break;
1349 }
1350 break;
1351 case EbtInt16:
1352 switch(to) {
1353 case EbtUint16:
1354 case EbtUint:
1355 case EbtInt64:
1356 case EbtUint64:
1357 return true;
1358 default:
1359 break;
1360 }
1361 break;
1362 case EbtUint16:
1363 switch(to) {
1364 case EbtUint:
1365 case EbtInt64:
1366 case EbtUint64:
1367 return true;
1368 default:
1369 break;
1370 }
1371 break;
1372 case EbtInt:
1373 switch(to) {
1374 case EbtUint:
1375 return version >= 400 || (source == EShSourceHlsl);
1376 case EbtInt64:
1377 case EbtUint64:
1378 return true;
1379 default:
1380 break;
1381 }
1382 break;
1383 case EbtUint:
1384 switch(to) {
1385 case EbtInt64:
1386 case EbtUint64:
1387 return true;
1388 default:
1389 break;
1390 }
1391 break;
1392 case EbtInt64:
1393 if (to == EbtUint64) {
1394 return true;
1395 }
1396 break;
1397 default:
1398 break;
1399 }
1400 return false;
1401 }
1402
isFPConversion(TBasicType from,TBasicType to) const1403 bool TIntermediate::isFPConversion(TBasicType from, TBasicType to) const
1404 {
1405 if (to == EbtFloat && from == EbtFloat16) {
1406 return true;
1407 } else {
1408 return false;
1409 }
1410 }
1411
isFPIntegralConversion(TBasicType from,TBasicType to) const1412 bool TIntermediate::isFPIntegralConversion(TBasicType from, TBasicType to) const
1413 {
1414 switch (from) {
1415 case EbtInt8:
1416 case EbtUint8:
1417 case EbtInt16:
1418 case EbtUint16:
1419 switch (to) {
1420 case EbtFloat16:
1421 case EbtFloat:
1422 case EbtDouble:
1423 return true;
1424 default:
1425 break;
1426 }
1427 break;
1428 case EbtInt:
1429 case EbtUint:
1430 switch(to) {
1431 case EbtFloat:
1432 case EbtDouble:
1433 return true;
1434 default:
1435 break;
1436 }
1437 break;
1438 case EbtInt64:
1439 case EbtUint64:
1440 if (to == EbtDouble) {
1441 return true;
1442 }
1443 break;
1444
1445 default:
1446 break;
1447 }
1448 return false;
1449 }
1450
1451 //
1452 // See if the 'from' type is allowed to be implicitly converted to the
1453 // 'to' type. This is not about vector/array/struct, only about basic type.
1454 //
canImplicitlyPromote(TBasicType from,TBasicType to,TOperator op) const1455 bool TIntermediate::canImplicitlyPromote(TBasicType from, TBasicType to, TOperator op) const
1456 {
1457 if (profile == EEsProfile || version == 110)
1458 return false;
1459
1460 if (from == to)
1461 return true;
1462
1463 // TODO: Move more policies into language-specific handlers.
1464 // Some languages allow more general (or potentially, more specific) conversions under some conditions.
1465 if (source == EShSourceHlsl) {
1466 const bool fromConvertable = (from == EbtFloat || from == EbtDouble || from == EbtInt || from == EbtUint || from == EbtBool);
1467 const bool toConvertable = (to == EbtFloat || to == EbtDouble || to == EbtInt || to == EbtUint || to == EbtBool);
1468
1469 if (fromConvertable && toConvertable) {
1470 switch (op) {
1471 case EOpAndAssign: // assignments can perform arbitrary conversions
1472 case EOpInclusiveOrAssign: // ...
1473 case EOpExclusiveOrAssign: // ...
1474 case EOpAssign: // ...
1475 case EOpAddAssign: // ...
1476 case EOpSubAssign: // ...
1477 case EOpMulAssign: // ...
1478 case EOpVectorTimesScalarAssign: // ...
1479 case EOpMatrixTimesScalarAssign: // ...
1480 case EOpDivAssign: // ...
1481 case EOpModAssign: // ...
1482 case EOpReturn: // function returns can also perform arbitrary conversions
1483 case EOpFunctionCall: // conversion of a calling parameter
1484 case EOpLogicalNot:
1485 case EOpLogicalAnd:
1486 case EOpLogicalOr:
1487 case EOpLogicalXor:
1488 case EOpConstructStruct:
1489 return true;
1490 default:
1491 break;
1492 }
1493 }
1494 }
1495
1496 bool explicitTypesEnabled = extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types) ||
1497 extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int8) ||
1498 extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int16) ||
1499 extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int32) ||
1500 extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_int64) ||
1501 extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_float16) ||
1502 extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_float32) ||
1503 extensionRequested(E_GL_EXT_shader_explicit_arithmetic_types_float64);
1504
1505 if (explicitTypesEnabled) {
1506 // integral promotions
1507 if (isIntegralPromotion(from, to)) {
1508 return true;
1509 }
1510
1511 // floating-point promotions
1512 if (isFPPromotion(from, to)) {
1513 return true;
1514 }
1515
1516 // integral conversions
1517 if (isIntegralConversion(from, to)) {
1518 return true;
1519 }
1520
1521 // floating-point conversions
1522 if (isFPConversion(from, to)) {
1523 return true;
1524 }
1525
1526 // floating-integral conversions
1527 if (isFPIntegralConversion(from, to)) {
1528 return true;
1529 }
1530
1531 // hlsl supported conversions
1532 if (source == EShSourceHlsl) {
1533 if (from == EbtBool && (to == EbtInt || to == EbtUint || to == EbtFloat))
1534 return true;
1535 }
1536 } else {
1537 switch (to) {
1538 case EbtDouble:
1539 switch (from) {
1540 case EbtInt:
1541 case EbtUint:
1542 case EbtInt64:
1543 case EbtUint64:
1544 case EbtFloat:
1545 case EbtDouble:
1546 return true;
1547 #ifdef AMD_EXTENSIONS
1548 case EbtInt16:
1549 case EbtUint16:
1550 return extensionRequested(E_GL_AMD_gpu_shader_int16);
1551 case EbtFloat16:
1552 return extensionRequested(E_GL_AMD_gpu_shader_half_float);
1553 #endif
1554 default:
1555 return false;
1556 }
1557 case EbtFloat:
1558 switch (from) {
1559 case EbtInt:
1560 case EbtUint:
1561 case EbtFloat:
1562 return true;
1563 case EbtBool:
1564 return (source == EShSourceHlsl);
1565 #ifdef AMD_EXTENSIONS
1566 case EbtInt16:
1567 case EbtUint16:
1568 return extensionRequested(E_GL_AMD_gpu_shader_int16);
1569 #endif
1570 case EbtFloat16:
1571 return
1572 #ifdef AMD_EXTENSIONS
1573 extensionRequested(E_GL_AMD_gpu_shader_half_float) ||
1574 #endif
1575 (source == EShSourceHlsl);
1576 default:
1577 return false;
1578 }
1579 case EbtUint:
1580 switch (from) {
1581 case EbtInt:
1582 return version >= 400 || (source == EShSourceHlsl);
1583 case EbtUint:
1584 return true;
1585 case EbtBool:
1586 return (source == EShSourceHlsl);
1587 #ifdef AMD_EXTENSIONS
1588 case EbtInt16:
1589 case EbtUint16:
1590 return extensionRequested(E_GL_AMD_gpu_shader_int16);
1591 #endif
1592 default:
1593 return false;
1594 }
1595 case EbtInt:
1596 switch (from) {
1597 case EbtInt:
1598 return true;
1599 case EbtBool:
1600 return (source == EShSourceHlsl);
1601 #ifdef AMD_EXTENSIONS
1602 case EbtInt16:
1603 return extensionRequested(E_GL_AMD_gpu_shader_int16);
1604 #endif
1605 default:
1606 return false;
1607 }
1608 case EbtUint64:
1609 switch (from) {
1610 case EbtInt:
1611 case EbtUint:
1612 case EbtInt64:
1613 case EbtUint64:
1614 return true;
1615 #ifdef AMD_EXTENSIONS
1616 case EbtInt16:
1617 case EbtUint16:
1618 return extensionRequested(E_GL_AMD_gpu_shader_int16);
1619 #endif
1620 default:
1621 return false;
1622 }
1623 case EbtInt64:
1624 switch (from) {
1625 case EbtInt:
1626 case EbtInt64:
1627 return true;
1628 #ifdef AMD_EXTENSIONS
1629 case EbtInt16:
1630 return extensionRequested(E_GL_AMD_gpu_shader_int16);
1631 #endif
1632 default:
1633 return false;
1634 }
1635 case EbtFloat16:
1636 #ifdef AMD_EXTENSIONS
1637 switch (from) {
1638 case EbtInt16:
1639 case EbtUint16:
1640 return extensionRequested(E_GL_AMD_gpu_shader_int16);
1641 case EbtFloat16:
1642 return extensionRequested(E_GL_AMD_gpu_shader_half_float);
1643 default:
1644 break;
1645 }
1646 #endif
1647 return false;
1648 case EbtUint16:
1649 #ifdef AMD_EXTENSIONS
1650 switch (from) {
1651 case EbtInt16:
1652 case EbtUint16:
1653 return extensionRequested(E_GL_AMD_gpu_shader_int16);
1654 default:
1655 break;
1656 }
1657 #endif
1658 return false;
1659 default:
1660 return false;
1661 }
1662 }
1663
1664 return false;
1665 }
1666
canSignedIntTypeRepresentAllUnsignedValues(TBasicType sintType,TBasicType uintType)1667 static bool canSignedIntTypeRepresentAllUnsignedValues(TBasicType sintType, TBasicType uintType) {
1668 switch(sintType) {
1669 case EbtInt8:
1670 switch(uintType) {
1671 case EbtUint8:
1672 case EbtUint16:
1673 case EbtUint:
1674 case EbtUint64:
1675 return false;
1676 default:
1677 assert(false);
1678 return false;
1679 }
1680 break;
1681 case EbtInt16:
1682 switch(uintType) {
1683 case EbtUint8:
1684 return true;
1685 case EbtUint16:
1686 case EbtUint:
1687 case EbtUint64:
1688 return false;
1689 default:
1690 assert(false);
1691 return false;
1692 }
1693 break;
1694 case EbtInt:
1695 switch(uintType) {
1696 case EbtUint8:
1697 case EbtUint16:
1698 return true;
1699 case EbtUint:
1700 return false;
1701 default:
1702 assert(false);
1703 return false;
1704 }
1705 break;
1706 case EbtInt64:
1707 switch(uintType) {
1708 case EbtUint8:
1709 case EbtUint16:
1710 case EbtUint:
1711 return true;
1712 case EbtUint64:
1713 return false;
1714 default:
1715 assert(false);
1716 return false;
1717 }
1718 break;
1719 default:
1720 assert(false);
1721 return false;
1722 }
1723 }
1724
1725
getCorrespondingUnsignedType(TBasicType type)1726 static TBasicType getCorrespondingUnsignedType(TBasicType type) {
1727 switch(type) {
1728 case EbtInt8:
1729 return EbtUint8;
1730 case EbtInt16:
1731 return EbtUint16;
1732 case EbtInt:
1733 return EbtUint;
1734 case EbtInt64:
1735 return EbtUint64;
1736 default:
1737 assert(false);
1738 return EbtNumTypes;
1739 }
1740 }
1741
1742 // Implements the following rules
1743 // - If either operand has type float64_t or derived from float64_t,
1744 // the other shall be converted to float64_t or derived type.
1745 // - Otherwise, if either operand has type float32_t or derived from
1746 // float32_t, the other shall be converted to float32_t or derived type.
1747 // - Otherwise, if either operand has type float16_t or derived from
1748 // float16_t, the other shall be converted to float16_t or derived type.
1749 // - Otherwise, if both operands have integer types the following rules
1750 // shall be applied to the operands:
1751 // - If both operands have the same type, no further conversion
1752 // is needed.
1753 // - Otherwise, if both operands have signed integer types or both
1754 // have unsigned integer types, the operand with the type of lesser
1755 // integer conversion rank shall be converted to the type of the
1756 // operand with greater rank.
1757 // - Otherwise, if the operand that has unsigned integer type has rank
1758 // greater than or equal to the rank of the type of the other
1759 // operand, the operand with signed integer type shall be converted
1760 // to the type of the operand with unsigned integer type.
1761 // - Otherwise, if the type of the operand with signed integer type can
1762 // represent all of the values of the type of the operand with
1763 // unsigned integer type, the operand with unsigned integer type
1764 // shall be converted to the type of the operand with signed
1765 // integer type.
1766 // - Otherwise, both operands shall be converted to the unsigned
1767 // integer type corresponding to the type of the operand with signed
1768 // integer type.
1769
getConversionDestinatonType(TBasicType type0,TBasicType type1,TOperator op) const1770 std::tuple<TBasicType, TBasicType> TIntermediate::getConversionDestinatonType(TBasicType type0, TBasicType type1, TOperator op) const
1771 {
1772 TBasicType res0 = EbtNumTypes;
1773 TBasicType res1 = EbtNumTypes;
1774
1775 if (profile == EEsProfile || version == 110)
1776 return std::make_tuple(res0, res1);;
1777
1778 if (source == EShSourceHlsl) {
1779 if (canImplicitlyPromote(type1, type0, op)) {
1780 res0 = type0;
1781 res1 = type0;
1782 } else if (canImplicitlyPromote(type0, type1, op)) {
1783 res0 = type1;
1784 res1 = type1;
1785 }
1786 return std::make_tuple(res0, res1);
1787 }
1788
1789 if ((type0 == EbtDouble && canImplicitlyPromote(type1, EbtDouble, op)) ||
1790 (type1 == EbtDouble && canImplicitlyPromote(type0, EbtDouble, op)) ) {
1791 res0 = EbtDouble;
1792 res1 = EbtDouble;
1793 } else if ((type0 == EbtFloat && canImplicitlyPromote(type1, EbtFloat, op)) ||
1794 (type1 == EbtFloat && canImplicitlyPromote(type0, EbtFloat, op)) ) {
1795 res0 = EbtFloat;
1796 res1 = EbtFloat;
1797 } else if ((type0 == EbtFloat16 && canImplicitlyPromote(type1, EbtFloat16, op)) ||
1798 (type1 == EbtFloat16 && canImplicitlyPromote(type0, EbtFloat16, op)) ) {
1799 res0 = EbtFloat16;
1800 res1 = EbtFloat16;
1801 } else if (isTypeInt(type0) && isTypeInt(type1) &&
1802 (canImplicitlyPromote(type0, type1, op) || canImplicitlyPromote(type1, type0, op))) {
1803 if ((isTypeSignedInt(type0) && isTypeSignedInt(type1)) ||
1804 (isTypeUnsignedInt(type0) && isTypeUnsignedInt(type1))) {
1805 if (getTypeRank(type0) < getTypeRank(type1)) {
1806 res0 = type1;
1807 res1 = type1;
1808 } else {
1809 res0 = type0;
1810 res1 = type0;
1811 }
1812 } else if (isTypeUnsignedInt(type0) && (getTypeRank(type0) > getTypeRank(type1))) {
1813 res0 = type0;
1814 res1 = type0;
1815 } else if (isTypeUnsignedInt(type1) && (getTypeRank(type1) > getTypeRank(type0))) {
1816 res0 = type1;
1817 res1 = type1;
1818 } else if (isTypeSignedInt(type0)) {
1819 if (canSignedIntTypeRepresentAllUnsignedValues(type0, type1)) {
1820 res0 = type0;
1821 res1 = type0;
1822 } else {
1823 res0 = getCorrespondingUnsignedType(type0);
1824 res1 = getCorrespondingUnsignedType(type0);
1825 }
1826 } else if (isTypeSignedInt(type1)) {
1827 if (canSignedIntTypeRepresentAllUnsignedValues(type1, type0)) {
1828 res0 = type1;
1829 res1 = type1;
1830 } else {
1831 res0 = getCorrespondingUnsignedType(type1);
1832 res1 = getCorrespondingUnsignedType(type1);
1833 }
1834 }
1835 }
1836
1837 return std::make_tuple(res0, res1);
1838 }
1839
1840 //
1841 // Given a type, find what operation would fully construct it.
1842 //
mapTypeToConstructorOp(const TType & type) const1843 TOperator TIntermediate::mapTypeToConstructorOp(const TType& type) const
1844 {
1845 TOperator op = EOpNull;
1846
1847 if (type.getQualifier().nonUniform)
1848 return EOpConstructNonuniform;
1849
1850 switch (type.getBasicType()) {
1851 case EbtStruct:
1852 op = EOpConstructStruct;
1853 break;
1854 case EbtSampler:
1855 if (type.getSampler().combined)
1856 op = EOpConstructTextureSampler;
1857 break;
1858 case EbtFloat:
1859 if (type.isMatrix()) {
1860 switch (type.getMatrixCols()) {
1861 case 2:
1862 switch (type.getMatrixRows()) {
1863 case 2: op = EOpConstructMat2x2; break;
1864 case 3: op = EOpConstructMat2x3; break;
1865 case 4: op = EOpConstructMat2x4; break;
1866 default: break; // some compilers want this
1867 }
1868 break;
1869 case 3:
1870 switch (type.getMatrixRows()) {
1871 case 2: op = EOpConstructMat3x2; break;
1872 case 3: op = EOpConstructMat3x3; break;
1873 case 4: op = EOpConstructMat3x4; break;
1874 default: break; // some compilers want this
1875 }
1876 break;
1877 case 4:
1878 switch (type.getMatrixRows()) {
1879 case 2: op = EOpConstructMat4x2; break;
1880 case 3: op = EOpConstructMat4x3; break;
1881 case 4: op = EOpConstructMat4x4; break;
1882 default: break; // some compilers want this
1883 }
1884 break;
1885 default: break; // some compilers want this
1886 }
1887 } else {
1888 switch(type.getVectorSize()) {
1889 case 1: op = EOpConstructFloat; break;
1890 case 2: op = EOpConstructVec2; break;
1891 case 3: op = EOpConstructVec3; break;
1892 case 4: op = EOpConstructVec4; break;
1893 default: break; // some compilers want this
1894 }
1895 }
1896 break;
1897 case EbtDouble:
1898 if (type.getMatrixCols()) {
1899 switch (type.getMatrixCols()) {
1900 case 2:
1901 switch (type.getMatrixRows()) {
1902 case 2: op = EOpConstructDMat2x2; break;
1903 case 3: op = EOpConstructDMat2x3; break;
1904 case 4: op = EOpConstructDMat2x4; break;
1905 default: break; // some compilers want this
1906 }
1907 break;
1908 case 3:
1909 switch (type.getMatrixRows()) {
1910 case 2: op = EOpConstructDMat3x2; break;
1911 case 3: op = EOpConstructDMat3x3; break;
1912 case 4: op = EOpConstructDMat3x4; break;
1913 default: break; // some compilers want this
1914 }
1915 break;
1916 case 4:
1917 switch (type.getMatrixRows()) {
1918 case 2: op = EOpConstructDMat4x2; break;
1919 case 3: op = EOpConstructDMat4x3; break;
1920 case 4: op = EOpConstructDMat4x4; break;
1921 default: break; // some compilers want this
1922 }
1923 break;
1924 }
1925 } else {
1926 switch(type.getVectorSize()) {
1927 case 1: op = EOpConstructDouble; break;
1928 case 2: op = EOpConstructDVec2; break;
1929 case 3: op = EOpConstructDVec3; break;
1930 case 4: op = EOpConstructDVec4; break;
1931 default: break; // some compilers want this
1932 }
1933 }
1934 break;
1935 case EbtFloat16:
1936 if (type.getMatrixCols()) {
1937 switch (type.getMatrixCols()) {
1938 case 2:
1939 switch (type.getMatrixRows()) {
1940 case 2: op = EOpConstructF16Mat2x2; break;
1941 case 3: op = EOpConstructF16Mat2x3; break;
1942 case 4: op = EOpConstructF16Mat2x4; break;
1943 default: break; // some compilers want this
1944 }
1945 break;
1946 case 3:
1947 switch (type.getMatrixRows()) {
1948 case 2: op = EOpConstructF16Mat3x2; break;
1949 case 3: op = EOpConstructF16Mat3x3; break;
1950 case 4: op = EOpConstructF16Mat3x4; break;
1951 default: break; // some compilers want this
1952 }
1953 break;
1954 case 4:
1955 switch (type.getMatrixRows()) {
1956 case 2: op = EOpConstructF16Mat4x2; break;
1957 case 3: op = EOpConstructF16Mat4x3; break;
1958 case 4: op = EOpConstructF16Mat4x4; break;
1959 default: break; // some compilers want this
1960 }
1961 break;
1962 }
1963 }
1964 else {
1965 switch (type.getVectorSize()) {
1966 case 1: op = EOpConstructFloat16; break;
1967 case 2: op = EOpConstructF16Vec2; break;
1968 case 3: op = EOpConstructF16Vec3; break;
1969 case 4: op = EOpConstructF16Vec4; break;
1970 default: break; // some compilers want this
1971 }
1972 }
1973 break;
1974 case EbtInt8:
1975 switch(type.getVectorSize()) {
1976 case 1: op = EOpConstructInt8; break;
1977 case 2: op = EOpConstructI8Vec2; break;
1978 case 3: op = EOpConstructI8Vec3; break;
1979 case 4: op = EOpConstructI8Vec4; break;
1980 default: break; // some compilers want this
1981 }
1982 break;
1983 case EbtUint8:
1984 switch(type.getVectorSize()) {
1985 case 1: op = EOpConstructUint8; break;
1986 case 2: op = EOpConstructU8Vec2; break;
1987 case 3: op = EOpConstructU8Vec3; break;
1988 case 4: op = EOpConstructU8Vec4; break;
1989 default: break; // some compilers want this
1990 }
1991 break;
1992 case EbtInt16:
1993 switch(type.getVectorSize()) {
1994 case 1: op = EOpConstructInt16; break;
1995 case 2: op = EOpConstructI16Vec2; break;
1996 case 3: op = EOpConstructI16Vec3; break;
1997 case 4: op = EOpConstructI16Vec4; break;
1998 default: break; // some compilers want this
1999 }
2000 break;
2001 case EbtUint16:
2002 switch(type.getVectorSize()) {
2003 case 1: op = EOpConstructUint16; break;
2004 case 2: op = EOpConstructU16Vec2; break;
2005 case 3: op = EOpConstructU16Vec3; break;
2006 case 4: op = EOpConstructU16Vec4; break;
2007 default: break; // some compilers want this
2008 }
2009 break;
2010 case EbtInt:
2011 if (type.getMatrixCols()) {
2012 switch (type.getMatrixCols()) {
2013 case 2:
2014 switch (type.getMatrixRows()) {
2015 case 2: op = EOpConstructIMat2x2; break;
2016 case 3: op = EOpConstructIMat2x3; break;
2017 case 4: op = EOpConstructIMat2x4; break;
2018 default: break; // some compilers want this
2019 }
2020 break;
2021 case 3:
2022 switch (type.getMatrixRows()) {
2023 case 2: op = EOpConstructIMat3x2; break;
2024 case 3: op = EOpConstructIMat3x3; break;
2025 case 4: op = EOpConstructIMat3x4; break;
2026 default: break; // some compilers want this
2027 }
2028 break;
2029 case 4:
2030 switch (type.getMatrixRows()) {
2031 case 2: op = EOpConstructIMat4x2; break;
2032 case 3: op = EOpConstructIMat4x3; break;
2033 case 4: op = EOpConstructIMat4x4; break;
2034 default: break; // some compilers want this
2035 }
2036 break;
2037 }
2038 } else {
2039 switch(type.getVectorSize()) {
2040 case 1: op = EOpConstructInt; break;
2041 case 2: op = EOpConstructIVec2; break;
2042 case 3: op = EOpConstructIVec3; break;
2043 case 4: op = EOpConstructIVec4; break;
2044 default: break; // some compilers want this
2045 }
2046 }
2047 break;
2048 case EbtUint:
2049 if (type.getMatrixCols()) {
2050 switch (type.getMatrixCols()) {
2051 case 2:
2052 switch (type.getMatrixRows()) {
2053 case 2: op = EOpConstructUMat2x2; break;
2054 case 3: op = EOpConstructUMat2x3; break;
2055 case 4: op = EOpConstructUMat2x4; break;
2056 default: break; // some compilers want this
2057 }
2058 break;
2059 case 3:
2060 switch (type.getMatrixRows()) {
2061 case 2: op = EOpConstructUMat3x2; break;
2062 case 3: op = EOpConstructUMat3x3; break;
2063 case 4: op = EOpConstructUMat3x4; break;
2064 default: break; // some compilers want this
2065 }
2066 break;
2067 case 4:
2068 switch (type.getMatrixRows()) {
2069 case 2: op = EOpConstructUMat4x2; break;
2070 case 3: op = EOpConstructUMat4x3; break;
2071 case 4: op = EOpConstructUMat4x4; break;
2072 default: break; // some compilers want this
2073 }
2074 break;
2075 }
2076 } else {
2077 switch(type.getVectorSize()) {
2078 case 1: op = EOpConstructUint; break;
2079 case 2: op = EOpConstructUVec2; break;
2080 case 3: op = EOpConstructUVec3; break;
2081 case 4: op = EOpConstructUVec4; break;
2082 default: break; // some compilers want this
2083 }
2084 }
2085 break;
2086 case EbtInt64:
2087 switch(type.getVectorSize()) {
2088 case 1: op = EOpConstructInt64; break;
2089 case 2: op = EOpConstructI64Vec2; break;
2090 case 3: op = EOpConstructI64Vec3; break;
2091 case 4: op = EOpConstructI64Vec4; break;
2092 default: break; // some compilers want this
2093 }
2094 break;
2095 case EbtUint64:
2096 switch(type.getVectorSize()) {
2097 case 1: op = EOpConstructUint64; break;
2098 case 2: op = EOpConstructU64Vec2; break;
2099 case 3: op = EOpConstructU64Vec3; break;
2100 case 4: op = EOpConstructU64Vec4; break;
2101 default: break; // some compilers want this
2102 }
2103 break;
2104 case EbtBool:
2105 if (type.getMatrixCols()) {
2106 switch (type.getMatrixCols()) {
2107 case 2:
2108 switch (type.getMatrixRows()) {
2109 case 2: op = EOpConstructBMat2x2; break;
2110 case 3: op = EOpConstructBMat2x3; break;
2111 case 4: op = EOpConstructBMat2x4; break;
2112 default: break; // some compilers want this
2113 }
2114 break;
2115 case 3:
2116 switch (type.getMatrixRows()) {
2117 case 2: op = EOpConstructBMat3x2; break;
2118 case 3: op = EOpConstructBMat3x3; break;
2119 case 4: op = EOpConstructBMat3x4; break;
2120 default: break; // some compilers want this
2121 }
2122 break;
2123 case 4:
2124 switch (type.getMatrixRows()) {
2125 case 2: op = EOpConstructBMat4x2; break;
2126 case 3: op = EOpConstructBMat4x3; break;
2127 case 4: op = EOpConstructBMat4x4; break;
2128 default: break; // some compilers want this
2129 }
2130 break;
2131 }
2132 } else {
2133 switch(type.getVectorSize()) {
2134 case 1: op = EOpConstructBool; break;
2135 case 2: op = EOpConstructBVec2; break;
2136 case 3: op = EOpConstructBVec3; break;
2137 case 4: op = EOpConstructBVec4; break;
2138 default: break; // some compilers want this
2139 }
2140 }
2141 break;
2142 case EbtReference:
2143 op = EOpConstructReference;
2144 break;
2145 default:
2146 break;
2147 }
2148
2149 return op;
2150 }
2151
2152 //
2153 // Safe way to combine two nodes into an aggregate. Works with null pointers,
2154 // a node that's not a aggregate yet, etc.
2155 //
2156 // Returns the resulting aggregate, unless nullptr was passed in for
2157 // both existing nodes.
2158 //
growAggregate(TIntermNode * left,TIntermNode * right)2159 TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* right)
2160 {
2161 if (left == nullptr && right == nullptr)
2162 return nullptr;
2163
2164 TIntermAggregate* aggNode = nullptr;
2165 if (left != nullptr)
2166 aggNode = left->getAsAggregate();
2167 if (aggNode == nullptr || aggNode->getOp() != EOpNull) {
2168 aggNode = new TIntermAggregate;
2169 if (left != nullptr)
2170 aggNode->getSequence().push_back(left);
2171 }
2172
2173 if (right != nullptr)
2174 aggNode->getSequence().push_back(right);
2175
2176 return aggNode;
2177 }
2178
growAggregate(TIntermNode * left,TIntermNode * right,const TSourceLoc & loc)2179 TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc& loc)
2180 {
2181 TIntermAggregate* aggNode = growAggregate(left, right);
2182 if (aggNode)
2183 aggNode->setLoc(loc);
2184
2185 return aggNode;
2186 }
2187
2188 //
2189 // Turn an existing node into an aggregate.
2190 //
2191 // Returns an aggregate, unless nullptr was passed in for the existing node.
2192 //
makeAggregate(TIntermNode * node)2193 TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node)
2194 {
2195 if (node == nullptr)
2196 return nullptr;
2197
2198 TIntermAggregate* aggNode = new TIntermAggregate;
2199 aggNode->getSequence().push_back(node);
2200 aggNode->setLoc(node->getLoc());
2201
2202 return aggNode;
2203 }
2204
makeAggregate(TIntermNode * node,const TSourceLoc & loc)2205 TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, const TSourceLoc& loc)
2206 {
2207 if (node == nullptr)
2208 return nullptr;
2209
2210 TIntermAggregate* aggNode = new TIntermAggregate;
2211 aggNode->getSequence().push_back(node);
2212 aggNode->setLoc(loc);
2213
2214 return aggNode;
2215 }
2216
2217 //
2218 // Make an aggregate with an empty sequence.
2219 //
makeAggregate(const TSourceLoc & loc)2220 TIntermAggregate* TIntermediate::makeAggregate(const TSourceLoc& loc)
2221 {
2222 TIntermAggregate* aggNode = new TIntermAggregate;
2223 aggNode->setLoc(loc);
2224
2225 return aggNode;
2226 }
2227
2228 //
2229 // For "if" test nodes. There are three children; a condition,
2230 // a true path, and a false path. The two paths are in the
2231 // nodePair.
2232 //
2233 // Returns the selection node created.
2234 //
addSelection(TIntermTyped * cond,TIntermNodePair nodePair,const TSourceLoc & loc)2235 TIntermSelection* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nodePair, const TSourceLoc& loc)
2236 {
2237 //
2238 // Don't prune the false path for compile-time constants; it's needed
2239 // for static access analysis.
2240 //
2241
2242 TIntermSelection* node = new TIntermSelection(cond, nodePair.node1, nodePair.node2);
2243 node->setLoc(loc);
2244
2245 return node;
2246 }
2247
addComma(TIntermTyped * left,TIntermTyped * right,const TSourceLoc & loc)2248 TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc& loc)
2249 {
2250 // However, the lowest precedence operators of the sequence operator ( , ) and the assignment operators
2251 // ... are not included in the operators that can create a constant expression.
2252 //
2253 // if (left->getType().getQualifier().storage == EvqConst &&
2254 // right->getType().getQualifier().storage == EvqConst) {
2255
2256 // return right;
2257 //}
2258
2259 TIntermTyped *commaAggregate = growAggregate(left, right, loc);
2260 commaAggregate->getAsAggregate()->setOperator(EOpComma);
2261 commaAggregate->setType(right->getType());
2262 commaAggregate->getWritableType().getQualifier().makeTemporary();
2263
2264 return commaAggregate;
2265 }
2266
addMethod(TIntermTyped * object,const TType & type,const TString * name,const TSourceLoc & loc)2267 TIntermTyped* TIntermediate::addMethod(TIntermTyped* object, const TType& type, const TString* name, const TSourceLoc& loc)
2268 {
2269 TIntermMethod* method = new TIntermMethod(object, type, *name);
2270 method->setLoc(loc);
2271
2272 return method;
2273 }
2274
2275 //
2276 // For "?:" test nodes. There are three children; a condition,
2277 // a true path, and a false path. The two paths are specified
2278 // as separate parameters. For vector 'cond', the true and false
2279 // are not paths, but vectors to mix.
2280 //
2281 // Specialization constant operations include
2282 // - The ternary operator ( ? : )
2283 //
2284 // Returns the selection node created, or nullptr if one could not be.
2285 //
addSelection(TIntermTyped * cond,TIntermTyped * trueBlock,TIntermTyped * falseBlock,const TSourceLoc & loc)2286 TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock,
2287 const TSourceLoc& loc)
2288 {
2289 // If it's void, go to the if-then-else selection()
2290 if (trueBlock->getBasicType() == EbtVoid && falseBlock->getBasicType() == EbtVoid) {
2291 TIntermNodePair pair = { trueBlock, falseBlock };
2292 TIntermSelection* selection = addSelection(cond, pair, loc);
2293 if (getSource() == EShSourceHlsl)
2294 selection->setNoShortCircuit();
2295
2296 return selection;
2297 }
2298
2299 //
2300 // Get compatible types.
2301 //
2302 auto children = addConversion(EOpSequence, trueBlock, falseBlock);
2303 trueBlock = std::get<0>(children);
2304 falseBlock = std::get<1>(children);
2305
2306 if (trueBlock == nullptr || falseBlock == nullptr)
2307 return nullptr;
2308
2309 // Handle a vector condition as a mix
2310 if (!cond->getType().isScalarOrVec1()) {
2311 TType targetVectorType(trueBlock->getType().getBasicType(), EvqTemporary,
2312 cond->getType().getVectorSize());
2313 // smear true/false operands as needed
2314 trueBlock = addUniShapeConversion(EOpMix, targetVectorType, trueBlock);
2315 falseBlock = addUniShapeConversion(EOpMix, targetVectorType, falseBlock);
2316
2317 // After conversion, types have to match.
2318 if (falseBlock->getType() != trueBlock->getType())
2319 return nullptr;
2320
2321 // make the mix operation
2322 TIntermAggregate* mix = makeAggregate(loc);
2323 mix = growAggregate(mix, falseBlock);
2324 mix = growAggregate(mix, trueBlock);
2325 mix = growAggregate(mix, cond);
2326 mix->setType(targetVectorType);
2327 mix->setOp(EOpMix);
2328
2329 return mix;
2330 }
2331
2332 // Now have a scalar condition...
2333
2334 // Convert true and false expressions to matching types
2335 addBiShapeConversion(EOpMix, trueBlock, falseBlock);
2336
2337 // After conversion, types have to match.
2338 if (falseBlock->getType() != trueBlock->getType())
2339 return nullptr;
2340
2341 // Eliminate the selection when the condition is a scalar and all operands are constant.
2342 if (cond->getAsConstantUnion() && trueBlock->getAsConstantUnion() && falseBlock->getAsConstantUnion()) {
2343 if (cond->getAsConstantUnion()->getConstArray()[0].getBConst())
2344 return trueBlock;
2345 else
2346 return falseBlock;
2347 }
2348
2349 //
2350 // Make a selection node.
2351 //
2352 TIntermSelection* node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType());
2353 node->setLoc(loc);
2354 node->getQualifier().precision = std::max(trueBlock->getQualifier().precision, falseBlock->getQualifier().precision);
2355
2356 if ((cond->getQualifier().isConstant() && specConstantPropagates(*trueBlock, *falseBlock)) ||
2357 (cond->getQualifier().isSpecConstant() && trueBlock->getQualifier().isConstant() &&
2358 falseBlock->getQualifier().isConstant()))
2359 node->getQualifier().makeSpecConstant();
2360 else
2361 node->getQualifier().makeTemporary();
2362
2363 if (getSource() == EShSourceHlsl)
2364 node->setNoShortCircuit();
2365
2366 return node;
2367 }
2368
2369 //
2370 // Constant terminal nodes. Has a union that contains bool, float or int constants
2371 //
2372 // Returns the constant union node created.
2373 //
2374
addConstantUnion(const TConstUnionArray & unionArray,const TType & t,const TSourceLoc & loc,bool literal) const2375 TIntermConstantUnion* TIntermediate::addConstantUnion(const TConstUnionArray& unionArray, const TType& t, const TSourceLoc& loc, bool literal) const
2376 {
2377 TIntermConstantUnion* node = new TIntermConstantUnion(unionArray, t);
2378 node->getQualifier().storage = EvqConst;
2379 node->setLoc(loc);
2380 if (literal)
2381 node->setLiteral();
2382
2383 return node;
2384 }
addConstantUnion(signed char i8,const TSourceLoc & loc,bool literal) const2385 TIntermConstantUnion* TIntermediate::addConstantUnion(signed char i8, const TSourceLoc& loc, bool literal) const
2386 {
2387 TConstUnionArray unionArray(1);
2388 unionArray[0].setI8Const(i8);
2389
2390 return addConstantUnion(unionArray, TType(EbtInt8, EvqConst), loc, literal);
2391 }
2392
addConstantUnion(unsigned char u8,const TSourceLoc & loc,bool literal) const2393 TIntermConstantUnion* TIntermediate::addConstantUnion(unsigned char u8, const TSourceLoc& loc, bool literal) const
2394 {
2395 TConstUnionArray unionArray(1);
2396 unionArray[0].setUConst(u8);
2397
2398 return addConstantUnion(unionArray, TType(EbtUint8, EvqConst), loc, literal);
2399 }
2400
addConstantUnion(signed short i16,const TSourceLoc & loc,bool literal) const2401 TIntermConstantUnion* TIntermediate::addConstantUnion(signed short i16, const TSourceLoc& loc, bool literal) const
2402 {
2403 TConstUnionArray unionArray(1);
2404 unionArray[0].setI16Const(i16);
2405
2406 return addConstantUnion(unionArray, TType(EbtInt16, EvqConst), loc, literal);
2407 }
2408
addConstantUnion(unsigned short u16,const TSourceLoc & loc,bool literal) const2409 TIntermConstantUnion* TIntermediate::addConstantUnion(unsigned short u16, const TSourceLoc& loc, bool literal) const
2410 {
2411 TConstUnionArray unionArray(1);
2412 unionArray[0].setU16Const(u16);
2413
2414 return addConstantUnion(unionArray, TType(EbtUint16, EvqConst), loc, literal);
2415 }
2416
addConstantUnion(int i,const TSourceLoc & loc,bool literal) const2417 TIntermConstantUnion* TIntermediate::addConstantUnion(int i, const TSourceLoc& loc, bool literal) const
2418 {
2419 TConstUnionArray unionArray(1);
2420 unionArray[0].setIConst(i);
2421
2422 return addConstantUnion(unionArray, TType(EbtInt, EvqConst), loc, literal);
2423 }
2424
addConstantUnion(unsigned int u,const TSourceLoc & loc,bool literal) const2425 TIntermConstantUnion* TIntermediate::addConstantUnion(unsigned int u, const TSourceLoc& loc, bool literal) const
2426 {
2427 TConstUnionArray unionArray(1);
2428 unionArray[0].setUConst(u);
2429
2430 return addConstantUnion(unionArray, TType(EbtUint, EvqConst), loc, literal);
2431 }
2432
addConstantUnion(long long i64,const TSourceLoc & loc,bool literal) const2433 TIntermConstantUnion* TIntermediate::addConstantUnion(long long i64, const TSourceLoc& loc, bool literal) const
2434 {
2435 TConstUnionArray unionArray(1);
2436 unionArray[0].setI64Const(i64);
2437
2438 return addConstantUnion(unionArray, TType(EbtInt64, EvqConst), loc, literal);
2439 }
2440
addConstantUnion(unsigned long long u64,const TSourceLoc & loc,bool literal) const2441 TIntermConstantUnion* TIntermediate::addConstantUnion(unsigned long long u64, const TSourceLoc& loc, bool literal) const
2442 {
2443 TConstUnionArray unionArray(1);
2444 unionArray[0].setU64Const(u64);
2445
2446 return addConstantUnion(unionArray, TType(EbtUint64, EvqConst), loc, literal);
2447 }
2448
addConstantUnion(bool b,const TSourceLoc & loc,bool literal) const2449 TIntermConstantUnion* TIntermediate::addConstantUnion(bool b, const TSourceLoc& loc, bool literal) const
2450 {
2451 TConstUnionArray unionArray(1);
2452 unionArray[0].setBConst(b);
2453
2454 return addConstantUnion(unionArray, TType(EbtBool, EvqConst), loc, literal);
2455 }
2456
addConstantUnion(double d,TBasicType baseType,const TSourceLoc & loc,bool literal) const2457 TIntermConstantUnion* TIntermediate::addConstantUnion(double d, TBasicType baseType, const TSourceLoc& loc, bool literal) const
2458 {
2459 assert(baseType == EbtFloat || baseType == EbtDouble || baseType == EbtFloat16);
2460
2461 TConstUnionArray unionArray(1);
2462 unionArray[0].setDConst(d);
2463
2464 return addConstantUnion(unionArray, TType(baseType, EvqConst), loc, literal);
2465 }
2466
addConstantUnion(const TString * s,const TSourceLoc & loc,bool literal) const2467 TIntermConstantUnion* TIntermediate::addConstantUnion(const TString* s, const TSourceLoc& loc, bool literal) const
2468 {
2469 TConstUnionArray unionArray(1);
2470 unionArray[0].setSConst(s);
2471
2472 return addConstantUnion(unionArray, TType(EbtString, EvqConst), loc, literal);
2473 }
2474
2475 // Put vector swizzle selectors onto the given sequence
pushSelector(TIntermSequence & sequence,const TVectorSelector & selector,const TSourceLoc & loc)2476 void TIntermediate::pushSelector(TIntermSequence& sequence, const TVectorSelector& selector, const TSourceLoc& loc)
2477 {
2478 TIntermConstantUnion* constIntNode = addConstantUnion(selector, loc);
2479 sequence.push_back(constIntNode);
2480 }
2481
2482 // Put matrix swizzle selectors onto the given sequence
pushSelector(TIntermSequence & sequence,const TMatrixSelector & selector,const TSourceLoc & loc)2483 void TIntermediate::pushSelector(TIntermSequence& sequence, const TMatrixSelector& selector, const TSourceLoc& loc)
2484 {
2485 TIntermConstantUnion* constIntNode = addConstantUnion(selector.coord1, loc);
2486 sequence.push_back(constIntNode);
2487 constIntNode = addConstantUnion(selector.coord2, loc);
2488 sequence.push_back(constIntNode);
2489 }
2490
2491 // Make an aggregate node that has a sequence of all selectors.
2492 template TIntermTyped* TIntermediate::addSwizzle<TVectorSelector>(TSwizzleSelectors<TVectorSelector>& selector, const TSourceLoc& loc);
2493 template TIntermTyped* TIntermediate::addSwizzle<TMatrixSelector>(TSwizzleSelectors<TMatrixSelector>& selector, const TSourceLoc& loc);
2494 template<typename selectorType>
addSwizzle(TSwizzleSelectors<selectorType> & selector,const TSourceLoc & loc)2495 TIntermTyped* TIntermediate::addSwizzle(TSwizzleSelectors<selectorType>& selector, const TSourceLoc& loc)
2496 {
2497 TIntermAggregate* node = new TIntermAggregate(EOpSequence);
2498
2499 node->setLoc(loc);
2500 TIntermSequence &sequenceVector = node->getSequence();
2501
2502 for (int i = 0; i < selector.size(); i++)
2503 pushSelector(sequenceVector, selector[i], loc);
2504
2505 return node;
2506 }
2507
2508 //
2509 // Follow the left branches down to the root of an l-value
2510 // expression (just "." and []).
2511 //
2512 // Return the base of the l-value (where following indexing quits working).
2513 // Return nullptr if a chain following dereferences cannot be followed.
2514 //
2515 // 'swizzleOkay' says whether or not it is okay to consider a swizzle
2516 // a valid part of the dereference chain.
2517 //
findLValueBase(const TIntermTyped * node,bool swizzleOkay)2518 const TIntermTyped* TIntermediate::findLValueBase(const TIntermTyped* node, bool swizzleOkay)
2519 {
2520 do {
2521 const TIntermBinary* binary = node->getAsBinaryNode();
2522 if (binary == nullptr)
2523 return node;
2524 TOperator op = binary->getOp();
2525 if (op != EOpIndexDirect && op != EOpIndexIndirect && op != EOpIndexDirectStruct && op != EOpVectorSwizzle && op != EOpMatrixSwizzle)
2526 return nullptr;
2527 if (! swizzleOkay) {
2528 if (op == EOpVectorSwizzle || op == EOpMatrixSwizzle)
2529 return nullptr;
2530 if ((op == EOpIndexDirect || op == EOpIndexIndirect) &&
2531 (binary->getLeft()->getType().isVector() || binary->getLeft()->getType().isScalar()) &&
2532 ! binary->getLeft()->getType().isArray())
2533 return nullptr;
2534 }
2535 node = node->getAsBinaryNode()->getLeft();
2536 } while (true);
2537 }
2538
2539 //
2540 // Create while and do-while loop nodes.
2541 //
addLoop(TIntermNode * body,TIntermTyped * test,TIntermTyped * terminal,bool testFirst,const TSourceLoc & loc)2542 TIntermLoop* TIntermediate::addLoop(TIntermNode* body, TIntermTyped* test, TIntermTyped* terminal, bool testFirst,
2543 const TSourceLoc& loc)
2544 {
2545 TIntermLoop* node = new TIntermLoop(body, test, terminal, testFirst);
2546 node->setLoc(loc);
2547
2548 return node;
2549 }
2550
2551 //
2552 // Create a for-loop sequence.
2553 //
addForLoop(TIntermNode * body,TIntermNode * initializer,TIntermTyped * test,TIntermTyped * terminal,bool testFirst,const TSourceLoc & loc,TIntermLoop * & node)2554 TIntermAggregate* TIntermediate::addForLoop(TIntermNode* body, TIntermNode* initializer, TIntermTyped* test,
2555 TIntermTyped* terminal, bool testFirst, const TSourceLoc& loc, TIntermLoop*& node)
2556 {
2557 node = new TIntermLoop(body, test, terminal, testFirst);
2558 node->setLoc(loc);
2559
2560 // make a sequence of the initializer and statement, but try to reuse the
2561 // aggregate already created for whatever is in the initializer, if there is one
2562 TIntermAggregate* loopSequence = (initializer == nullptr ||
2563 initializer->getAsAggregate() == nullptr) ? makeAggregate(initializer, loc)
2564 : initializer->getAsAggregate();
2565 if (loopSequence != nullptr && loopSequence->getOp() == EOpSequence)
2566 loopSequence->setOp(EOpNull);
2567 loopSequence = growAggregate(loopSequence, node);
2568 loopSequence->setOperator(EOpSequence);
2569
2570 return loopSequence;
2571 }
2572
2573 //
2574 // Add branches.
2575 //
addBranch(TOperator branchOp,const TSourceLoc & loc)2576 TIntermBranch* TIntermediate::addBranch(TOperator branchOp, const TSourceLoc& loc)
2577 {
2578 return addBranch(branchOp, nullptr, loc);
2579 }
2580
addBranch(TOperator branchOp,TIntermTyped * expression,const TSourceLoc & loc)2581 TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expression, const TSourceLoc& loc)
2582 {
2583 TIntermBranch* node = new TIntermBranch(branchOp, expression);
2584 node->setLoc(loc);
2585
2586 return node;
2587 }
2588
2589 //
2590 // This is to be executed after the final root is put on top by the parsing
2591 // process.
2592 //
postProcess(TIntermNode * root,EShLanguage)2593 bool TIntermediate::postProcess(TIntermNode* root, EShLanguage /*language*/)
2594 {
2595 if (root == nullptr)
2596 return true;
2597
2598 // Finish off the top-level sequence
2599 TIntermAggregate* aggRoot = root->getAsAggregate();
2600 if (aggRoot && aggRoot->getOp() == EOpNull)
2601 aggRoot->setOperator(EOpSequence);
2602
2603 // Propagate 'noContraction' label in backward from 'precise' variables.
2604 glslang::PropagateNoContraction(*this);
2605
2606 switch (textureSamplerTransformMode) {
2607 case EShTexSampTransKeep:
2608 break;
2609 case EShTexSampTransUpgradeTextureRemoveSampler:
2610 performTextureUpgradeAndSamplerRemovalTransformation(root);
2611 break;
2612 }
2613
2614 return true;
2615 }
2616
addSymbolLinkageNodes(TIntermAggregate * & linkage,EShLanguage language,TSymbolTable & symbolTable)2617 void TIntermediate::addSymbolLinkageNodes(TIntermAggregate*& linkage, EShLanguage language, TSymbolTable& symbolTable)
2618 {
2619 // Add top-level nodes for declarations that must be checked cross
2620 // compilation unit by a linker, yet might not have been referenced
2621 // by the AST.
2622 //
2623 // Almost entirely, translation of symbols is driven by what's present
2624 // in the AST traversal, not by translating the symbol table.
2625 //
2626 // However, there are some special cases:
2627 // - From the specification: "Special built-in inputs gl_VertexID and
2628 // gl_InstanceID are also considered active vertex attributes."
2629 // - Linker-based type mismatch error reporting needs to see all
2630 // uniforms/ins/outs variables and blocks.
2631 // - ftransform() can make gl_Vertex and gl_ModelViewProjectionMatrix active.
2632 //
2633
2634 // if (ftransformUsed) {
2635 // TODO: 1.1 lowering functionality: track ftransform() usage
2636 // addSymbolLinkageNode(root, symbolTable, "gl_Vertex");
2637 // addSymbolLinkageNode(root, symbolTable, "gl_ModelViewProjectionMatrix");
2638 //}
2639
2640 if (language == EShLangVertex) {
2641 // the names won't be found in the symbol table unless the versions are right,
2642 // so version logic does not need to be repeated here
2643 addSymbolLinkageNode(linkage, symbolTable, "gl_VertexID");
2644 addSymbolLinkageNode(linkage, symbolTable, "gl_InstanceID");
2645 }
2646
2647 // Add a child to the root node for the linker objects
2648 linkage->setOperator(EOpLinkerObjects);
2649 treeRoot = growAggregate(treeRoot, linkage);
2650 }
2651
2652 //
2653 // Add the given name or symbol to the list of nodes at the end of the tree used
2654 // for link-time checking and external linkage.
2655 //
2656
addSymbolLinkageNode(TIntermAggregate * & linkage,TSymbolTable & symbolTable,const TString & name)2657 void TIntermediate::addSymbolLinkageNode(TIntermAggregate*& linkage, TSymbolTable& symbolTable, const TString& name)
2658 {
2659 TSymbol* symbol = symbolTable.find(name);
2660 if (symbol)
2661 addSymbolLinkageNode(linkage, *symbol->getAsVariable());
2662 }
2663
addSymbolLinkageNode(TIntermAggregate * & linkage,const TSymbol & symbol)2664 void TIntermediate::addSymbolLinkageNode(TIntermAggregate*& linkage, const TSymbol& symbol)
2665 {
2666 const TVariable* variable = symbol.getAsVariable();
2667 if (! variable) {
2668 // This must be a member of an anonymous block, and we need to add the whole block
2669 const TAnonMember* anon = symbol.getAsAnonMember();
2670 variable = &anon->getAnonContainer();
2671 }
2672 TIntermSymbol* node = addSymbol(*variable);
2673 linkage = growAggregate(linkage, node);
2674 }
2675
2676 //
2677 // Add a caller->callee relationship to the call graph.
2678 // Assumes the strings are unique per signature.
2679 //
addToCallGraph(TInfoSink &,const TString & caller,const TString & callee)2680 void TIntermediate::addToCallGraph(TInfoSink& /*infoSink*/, const TString& caller, const TString& callee)
2681 {
2682 // Duplicates are okay, but faster to not keep them, and they come grouped by caller,
2683 // as long as new ones are push on the same end we check on for duplicates
2684 for (TGraph::const_iterator call = callGraph.begin(); call != callGraph.end(); ++call) {
2685 if (call->caller != caller)
2686 break;
2687 if (call->callee == callee)
2688 return;
2689 }
2690
2691 callGraph.push_front(TCall(caller, callee));
2692 }
2693
2694 //
2695 // This deletes the tree.
2696 //
removeTree()2697 void TIntermediate::removeTree()
2698 {
2699 if (treeRoot)
2700 RemoveAllTreeNodes(treeRoot);
2701 }
2702
2703 //
2704 // Implement the part of KHR_vulkan_glsl that lists the set of operations
2705 // that can result in a specialization constant operation.
2706 //
2707 // "5.x Specialization Constant Operations"
2708 //
2709 // Only some operations discussed in this section may be applied to a
2710 // specialization constant and still yield a result that is as
2711 // specialization constant. The operations allowed are listed below.
2712 // When a specialization constant is operated on with one of these
2713 // operators and with another constant or specialization constant, the
2714 // result is implicitly a specialization constant.
2715 //
2716 // - int(), uint(), and bool() constructors for type conversions
2717 // from any of the following types to any of the following types:
2718 // * int
2719 // * uint
2720 // * bool
2721 // - vector versions of the above conversion constructors
2722 // - allowed implicit conversions of the above
2723 // - swizzles (e.g., foo.yx)
2724 // - The following when applied to integer or unsigned integer types:
2725 // * unary negative ( - )
2726 // * binary operations ( + , - , * , / , % )
2727 // * shift ( <<, >> )
2728 // * bitwise operations ( & , | , ^ )
2729 // - The following when applied to integer or unsigned integer scalar types:
2730 // * comparison ( == , != , > , >= , < , <= )
2731 // - The following when applied to the Boolean scalar type:
2732 // * not ( ! )
2733 // * logical operations ( && , || , ^^ )
2734 // * comparison ( == , != )"
2735 //
2736 // This function just handles binary and unary nodes. Construction
2737 // rules are handled in construction paths that are not covered by the unary
2738 // and binary paths, while required conversions will still show up here
2739 // as unary converters in the from a construction operator.
2740 //
isSpecializationOperation(const TIntermOperator & node) const2741 bool TIntermediate::isSpecializationOperation(const TIntermOperator& node) const
2742 {
2743 // The operations resulting in floating point are quite limited
2744 // (However, some floating-point operations result in bool, like ">",
2745 // so are handled later.)
2746 if (node.getType().isFloatingDomain()) {
2747 switch (node.getOp()) {
2748 case EOpIndexDirect:
2749 case EOpIndexIndirect:
2750 case EOpIndexDirectStruct:
2751 case EOpVectorSwizzle:
2752 case EOpConvFloatToDouble:
2753 case EOpConvDoubleToFloat:
2754 case EOpConvFloat16ToFloat:
2755 case EOpConvFloatToFloat16:
2756 case EOpConvFloat16ToDouble:
2757 case EOpConvDoubleToFloat16:
2758 return true;
2759 default:
2760 return false;
2761 }
2762 }
2763
2764 // Check for floating-point arguments
2765 if (const TIntermBinary* bin = node.getAsBinaryNode())
2766 if (bin->getLeft() ->getType().isFloatingDomain() ||
2767 bin->getRight()->getType().isFloatingDomain())
2768 return false;
2769
2770 // So, for now, we can assume everything left is non-floating-point...
2771
2772 // Now check for integer/bool-based operations
2773 switch (node.getOp()) {
2774
2775 // dereference/swizzle
2776 case EOpIndexDirect:
2777 case EOpIndexIndirect:
2778 case EOpIndexDirectStruct:
2779 case EOpVectorSwizzle:
2780
2781 // (u)int* -> bool
2782 case EOpConvInt8ToBool:
2783 case EOpConvInt16ToBool:
2784 case EOpConvIntToBool:
2785 case EOpConvInt64ToBool:
2786 case EOpConvUint8ToBool:
2787 case EOpConvUint16ToBool:
2788 case EOpConvUintToBool:
2789 case EOpConvUint64ToBool:
2790
2791 // bool -> (u)int*
2792 case EOpConvBoolToInt8:
2793 case EOpConvBoolToInt16:
2794 case EOpConvBoolToInt:
2795 case EOpConvBoolToInt64:
2796 case EOpConvBoolToUint8:
2797 case EOpConvBoolToUint16:
2798 case EOpConvBoolToUint:
2799 case EOpConvBoolToUint64:
2800
2801 // int8_t -> (u)int*
2802 case EOpConvInt8ToInt16:
2803 case EOpConvInt8ToInt:
2804 case EOpConvInt8ToInt64:
2805 case EOpConvInt8ToUint8:
2806 case EOpConvInt8ToUint16:
2807 case EOpConvInt8ToUint:
2808 case EOpConvInt8ToUint64:
2809
2810 // int16_t -> (u)int*
2811 case EOpConvInt16ToInt8:
2812 case EOpConvInt16ToInt:
2813 case EOpConvInt16ToInt64:
2814 case EOpConvInt16ToUint8:
2815 case EOpConvInt16ToUint16:
2816 case EOpConvInt16ToUint:
2817 case EOpConvInt16ToUint64:
2818
2819 // int32_t -> (u)int*
2820 case EOpConvIntToInt8:
2821 case EOpConvIntToInt16:
2822 case EOpConvIntToInt64:
2823 case EOpConvIntToUint8:
2824 case EOpConvIntToUint16:
2825 case EOpConvIntToUint:
2826 case EOpConvIntToUint64:
2827
2828 // int64_t -> (u)int*
2829 case EOpConvInt64ToInt8:
2830 case EOpConvInt64ToInt16:
2831 case EOpConvInt64ToInt:
2832 case EOpConvInt64ToUint8:
2833 case EOpConvInt64ToUint16:
2834 case EOpConvInt64ToUint:
2835 case EOpConvInt64ToUint64:
2836
2837 // uint8_t -> (u)int*
2838 case EOpConvUint8ToInt8:
2839 case EOpConvUint8ToInt16:
2840 case EOpConvUint8ToInt:
2841 case EOpConvUint8ToInt64:
2842 case EOpConvUint8ToUint16:
2843 case EOpConvUint8ToUint:
2844 case EOpConvUint8ToUint64:
2845
2846 // uint16_t -> (u)int*
2847 case EOpConvUint16ToInt8:
2848 case EOpConvUint16ToInt16:
2849 case EOpConvUint16ToInt:
2850 case EOpConvUint16ToInt64:
2851 case EOpConvUint16ToUint8:
2852 case EOpConvUint16ToUint:
2853 case EOpConvUint16ToUint64:
2854
2855 // uint32_t -> (u)int*
2856 case EOpConvUintToInt8:
2857 case EOpConvUintToInt16:
2858 case EOpConvUintToInt:
2859 case EOpConvUintToInt64:
2860 case EOpConvUintToUint8:
2861 case EOpConvUintToUint16:
2862 case EOpConvUintToUint64:
2863
2864 // uint64_t -> (u)int*
2865 case EOpConvUint64ToInt8:
2866 case EOpConvUint64ToInt16:
2867 case EOpConvUint64ToInt:
2868 case EOpConvUint64ToInt64:
2869 case EOpConvUint64ToUint8:
2870 case EOpConvUint64ToUint16:
2871 case EOpConvUint64ToUint:
2872
2873 // unary operations
2874 case EOpNegative:
2875 case EOpLogicalNot:
2876 case EOpBitwiseNot:
2877
2878 // binary operations
2879 case EOpAdd:
2880 case EOpSub:
2881 case EOpMul:
2882 case EOpVectorTimesScalar:
2883 case EOpDiv:
2884 case EOpMod:
2885 case EOpRightShift:
2886 case EOpLeftShift:
2887 case EOpAnd:
2888 case EOpInclusiveOr:
2889 case EOpExclusiveOr:
2890 case EOpLogicalOr:
2891 case EOpLogicalXor:
2892 case EOpLogicalAnd:
2893 case EOpEqual:
2894 case EOpNotEqual:
2895 case EOpLessThan:
2896 case EOpGreaterThan:
2897 case EOpLessThanEqual:
2898 case EOpGreaterThanEqual:
2899 return true;
2900 default:
2901 return false;
2902 }
2903 }
2904
2905 // Is the operation one that must propagate nonuniform?
isNonuniformPropagating(TOperator op) const2906 bool TIntermediate::isNonuniformPropagating(TOperator op) const
2907 {
2908 // "* All Operators in Section 5.1 (Operators), except for assignment,
2909 // arithmetic assignment, and sequence
2910 // * Component selection in Section 5.5
2911 // * Matrix components in Section 5.6
2912 // * Structure and Array Operations in Section 5.7, except for the length
2913 // method."
2914 switch (op) {
2915 case EOpPostIncrement:
2916 case EOpPostDecrement:
2917 case EOpPreIncrement:
2918 case EOpPreDecrement:
2919
2920 case EOpNegative:
2921 case EOpLogicalNot:
2922 case EOpVectorLogicalNot:
2923 case EOpBitwiseNot:
2924
2925 case EOpAdd:
2926 case EOpSub:
2927 case EOpMul:
2928 case EOpDiv:
2929 case EOpMod:
2930 case EOpRightShift:
2931 case EOpLeftShift:
2932 case EOpAnd:
2933 case EOpInclusiveOr:
2934 case EOpExclusiveOr:
2935 case EOpEqual:
2936 case EOpNotEqual:
2937 case EOpLessThan:
2938 case EOpGreaterThan:
2939 case EOpLessThanEqual:
2940 case EOpGreaterThanEqual:
2941 case EOpVectorTimesScalar:
2942 case EOpVectorTimesMatrix:
2943 case EOpMatrixTimesVector:
2944 case EOpMatrixTimesScalar:
2945
2946 case EOpLogicalOr:
2947 case EOpLogicalXor:
2948 case EOpLogicalAnd:
2949
2950 case EOpIndexDirect:
2951 case EOpIndexIndirect:
2952 case EOpIndexDirectStruct:
2953 case EOpVectorSwizzle:
2954 return true;
2955
2956 default:
2957 break;
2958 }
2959
2960 return false;
2961 }
2962
2963 ////////////////////////////////////////////////////////////////
2964 //
2965 // Member functions of the nodes used for building the tree.
2966 //
2967 ////////////////////////////////////////////////////////////////
2968
2969 //
2970 // Say whether or not an operation node changes the value of a variable.
2971 //
2972 // Returns true if state is modified.
2973 //
modifiesState() const2974 bool TIntermOperator::modifiesState() const
2975 {
2976 switch (op) {
2977 case EOpPostIncrement:
2978 case EOpPostDecrement:
2979 case EOpPreIncrement:
2980 case EOpPreDecrement:
2981 case EOpAssign:
2982 case EOpAddAssign:
2983 case EOpSubAssign:
2984 case EOpMulAssign:
2985 case EOpVectorTimesMatrixAssign:
2986 case EOpVectorTimesScalarAssign:
2987 case EOpMatrixTimesScalarAssign:
2988 case EOpMatrixTimesMatrixAssign:
2989 case EOpDivAssign:
2990 case EOpModAssign:
2991 case EOpAndAssign:
2992 case EOpInclusiveOrAssign:
2993 case EOpExclusiveOrAssign:
2994 case EOpLeftShiftAssign:
2995 case EOpRightShiftAssign:
2996 return true;
2997 default:
2998 return false;
2999 }
3000 }
3001
3002 //
3003 // returns true if the operator is for one of the constructors
3004 //
isConstructor() const3005 bool TIntermOperator::isConstructor() const
3006 {
3007 return op > EOpConstructGuardStart && op < EOpConstructGuardEnd;
3008 }
3009
3010 //
3011 // Make sure the type of an operator is appropriate for its
3012 // combination of operation and operand type. This will invoke
3013 // promoteUnary, promoteBinary, etc as needed.
3014 //
3015 // Returns false if nothing makes sense.
3016 //
promote(TIntermOperator * node)3017 bool TIntermediate::promote(TIntermOperator* node)
3018 {
3019 if (node == nullptr)
3020 return false;
3021
3022 if (node->getAsUnaryNode())
3023 return promoteUnary(*node->getAsUnaryNode());
3024
3025 if (node->getAsBinaryNode())
3026 return promoteBinary(*node->getAsBinaryNode());
3027
3028 if (node->getAsAggregate())
3029 return promoteAggregate(*node->getAsAggregate());
3030
3031 return false;
3032 }
3033
3034 //
3035 // See TIntermediate::promote
3036 //
promoteUnary(TIntermUnary & node)3037 bool TIntermediate::promoteUnary(TIntermUnary& node)
3038 {
3039 const TOperator op = node.getOp();
3040 TIntermTyped* operand = node.getOperand();
3041
3042 switch (op) {
3043 case EOpLogicalNot:
3044 // Convert operand to a boolean type
3045 if (operand->getBasicType() != EbtBool) {
3046 // Add constructor to boolean type. If that fails, we can't do it, so return false.
3047 TIntermTyped* converted = addConversion(op, TType(EbtBool), operand);
3048 if (converted == nullptr)
3049 return false;
3050
3051 // Use the result of converting the node to a bool.
3052 node.setOperand(operand = converted); // also updates stack variable
3053 }
3054 break;
3055 case EOpBitwiseNot:
3056 if (!isTypeInt(operand->getBasicType()))
3057 return false;
3058 break;
3059 case EOpNegative:
3060 case EOpPostIncrement:
3061 case EOpPostDecrement:
3062 case EOpPreIncrement:
3063 case EOpPreDecrement:
3064 if (!isTypeInt(operand->getBasicType()) &&
3065 operand->getBasicType() != EbtFloat &&
3066 operand->getBasicType() != EbtFloat16 &&
3067 operand->getBasicType() != EbtDouble)
3068
3069 return false;
3070 break;
3071
3072 default:
3073 if (operand->getBasicType() != EbtFloat)
3074
3075 return false;
3076 }
3077
3078 node.setType(operand->getType());
3079 node.getWritableType().getQualifier().makeTemporary();
3080
3081 return true;
3082 }
3083
updatePrecision()3084 void TIntermUnary::updatePrecision()
3085 {
3086 if (getBasicType() == EbtInt || getBasicType() == EbtUint || getBasicType() == EbtFloat || getBasicType() == EbtFloat16) {
3087 if (operand->getQualifier().precision > getQualifier().precision)
3088 getQualifier().precision = operand->getQualifier().precision;
3089 }
3090 }
3091
3092 //
3093 // See TIntermediate::promote
3094 //
promoteBinary(TIntermBinary & node)3095 bool TIntermediate::promoteBinary(TIntermBinary& node)
3096 {
3097 TOperator op = node.getOp();
3098 TIntermTyped* left = node.getLeft();
3099 TIntermTyped* right = node.getRight();
3100
3101 // Arrays and structures have to be exact matches.
3102 if ((left->isArray() || right->isArray() || left->getBasicType() == EbtStruct || right->getBasicType() == EbtStruct)
3103 && left->getType() != right->getType())
3104 return false;
3105
3106 // Base assumption: just make the type the same as the left
3107 // operand. Only deviations from this will be coded.
3108 node.setType(left->getType());
3109 node.getWritableType().getQualifier().clear();
3110
3111 // Composite and opaque types don't having pending operator changes, e.g.,
3112 // array, structure, and samplers. Just establish final type and correctness.
3113 if (left->isArray() || left->getBasicType() == EbtStruct || left->getBasicType() == EbtSampler) {
3114 switch (op) {
3115 case EOpEqual:
3116 case EOpNotEqual:
3117 if (left->getBasicType() == EbtSampler) {
3118 // can't compare samplers
3119 return false;
3120 } else {
3121 // Promote to conditional
3122 node.setType(TType(EbtBool));
3123 }
3124
3125 return true;
3126
3127 case EOpAssign:
3128 // Keep type from above
3129
3130 return true;
3131
3132 default:
3133 return false;
3134 }
3135 }
3136
3137 //
3138 // We now have only scalars, vectors, and matrices to worry about.
3139 //
3140
3141 // HLSL implicitly promotes bool -> int for numeric operations.
3142 // (Implicit conversions to make the operands match each other's types were already done.)
3143 if (getSource() == EShSourceHlsl &&
3144 (left->getBasicType() == EbtBool || right->getBasicType() == EbtBool)) {
3145 switch (op) {
3146 case EOpLessThan:
3147 case EOpGreaterThan:
3148 case EOpLessThanEqual:
3149 case EOpGreaterThanEqual:
3150
3151 case EOpRightShift:
3152 case EOpLeftShift:
3153
3154 case EOpMod:
3155
3156 case EOpAnd:
3157 case EOpInclusiveOr:
3158 case EOpExclusiveOr:
3159
3160 case EOpAdd:
3161 case EOpSub:
3162 case EOpDiv:
3163 case EOpMul:
3164 if (left->getBasicType() == EbtBool)
3165 left = createConversion(EbtInt, left);
3166 if (right->getBasicType() == EbtBool)
3167 right = createConversion(EbtInt, right);
3168 if (left == nullptr || right == nullptr)
3169 return false;
3170 node.setLeft(left);
3171 node.setRight(right);
3172
3173 // Update the original base assumption on result type..
3174 node.setType(left->getType());
3175 node.getWritableType().getQualifier().clear();
3176
3177 break;
3178
3179 default:
3180 break;
3181 }
3182 }
3183
3184 // Do general type checks against individual operands (comparing left and right is coming up, checking mixed shapes after that)
3185 switch (op) {
3186 case EOpLessThan:
3187 case EOpGreaterThan:
3188 case EOpLessThanEqual:
3189 case EOpGreaterThanEqual:
3190 // Relational comparisons need numeric types and will promote to scalar Boolean.
3191 if (left->getBasicType() == EbtBool)
3192 return false;
3193
3194 node.setType(TType(EbtBool, EvqTemporary, left->getVectorSize()));
3195 break;
3196
3197 case EOpEqual:
3198 case EOpNotEqual:
3199 if (getSource() == EShSourceHlsl) {
3200 const int resultWidth = std::max(left->getVectorSize(), right->getVectorSize());
3201
3202 // In HLSL, == or != on vectors means component-wise comparison.
3203 if (resultWidth > 1) {
3204 op = (op == EOpEqual) ? EOpVectorEqual : EOpVectorNotEqual;
3205 node.setOp(op);
3206 }
3207
3208 node.setType(TType(EbtBool, EvqTemporary, resultWidth));
3209 } else {
3210 // All the above comparisons result in a bool (but not the vector compares)
3211 node.setType(TType(EbtBool));
3212 }
3213 break;
3214
3215 case EOpLogicalAnd:
3216 case EOpLogicalOr:
3217 case EOpLogicalXor:
3218 // logical ops operate only on Booleans or vectors of Booleans.
3219 if (left->getBasicType() != EbtBool || left->isMatrix())
3220 return false;
3221
3222 if (getSource() == EShSourceGlsl) {
3223 // logical ops operate only on scalar Booleans and will promote to scalar Boolean.
3224 if (left->isVector())
3225 return false;
3226 }
3227
3228 node.setType(TType(EbtBool, EvqTemporary, left->getVectorSize()));
3229 break;
3230
3231 case EOpRightShift:
3232 case EOpLeftShift:
3233 case EOpRightShiftAssign:
3234 case EOpLeftShiftAssign:
3235
3236 case EOpMod:
3237 case EOpModAssign:
3238
3239 case EOpAnd:
3240 case EOpInclusiveOr:
3241 case EOpExclusiveOr:
3242 case EOpAndAssign:
3243 case EOpInclusiveOrAssign:
3244 case EOpExclusiveOrAssign:
3245 if (getSource() == EShSourceHlsl)
3246 break;
3247
3248 // Check for integer-only operands.
3249 if (!isTypeInt(left->getBasicType()) && !isTypeInt(right->getBasicType()))
3250 return false;
3251 if (left->isMatrix() || right->isMatrix())
3252 return false;
3253
3254 break;
3255
3256 case EOpAdd:
3257 case EOpSub:
3258 case EOpDiv:
3259 case EOpMul:
3260 case EOpAddAssign:
3261 case EOpSubAssign:
3262 case EOpMulAssign:
3263 case EOpDivAssign:
3264 // check for non-Boolean operands
3265 if (left->getBasicType() == EbtBool || right->getBasicType() == EbtBool)
3266 return false;
3267
3268 default:
3269 break;
3270 }
3271
3272 // Compare left and right, and finish with the cases where the operand types must match
3273 switch (op) {
3274 case EOpLessThan:
3275 case EOpGreaterThan:
3276 case EOpLessThanEqual:
3277 case EOpGreaterThanEqual:
3278
3279 case EOpEqual:
3280 case EOpNotEqual:
3281 case EOpVectorEqual:
3282 case EOpVectorNotEqual:
3283
3284 case EOpLogicalAnd:
3285 case EOpLogicalOr:
3286 case EOpLogicalXor:
3287 return left->getType() == right->getType();
3288
3289 case EOpMod:
3290 case EOpModAssign:
3291
3292 case EOpAnd:
3293 case EOpInclusiveOr:
3294 case EOpExclusiveOr:
3295 case EOpAndAssign:
3296 case EOpInclusiveOrAssign:
3297 case EOpExclusiveOrAssign:
3298
3299 case EOpAdd:
3300 case EOpSub:
3301 case EOpDiv:
3302
3303 case EOpAddAssign:
3304 case EOpSubAssign:
3305 case EOpDivAssign:
3306 // Quick out in case the types do match
3307 if (left->getType() == right->getType())
3308 return true;
3309
3310 // Fall through
3311
3312 case EOpMul:
3313 case EOpMulAssign:
3314 // At least the basic type has to match
3315 if (left->getBasicType() != right->getBasicType())
3316 return false;
3317
3318 default:
3319 break;
3320 }
3321
3322 // Finish handling the case, for all ops, where both operands are scalars.
3323 if (left->isScalar() && right->isScalar())
3324 return true;
3325
3326 // Finish handling the case, for all ops, where there are two vectors of different sizes
3327 if (left->isVector() && right->isVector() && left->getVectorSize() != right->getVectorSize() && right->getVectorSize() > 1)
3328 return false;
3329
3330 //
3331 // We now have a mix of scalars, vectors, or matrices, for non-relational operations.
3332 //
3333
3334 // Can these two operands be combined, what is the resulting type?
3335 TBasicType basicType = left->getBasicType();
3336 switch (op) {
3337 case EOpMul:
3338 if (!left->isMatrix() && right->isMatrix()) {
3339 if (left->isVector()) {
3340 if (left->getVectorSize() != right->getMatrixRows())
3341 return false;
3342 node.setOp(op = EOpVectorTimesMatrix);
3343 node.setType(TType(basicType, EvqTemporary, right->getMatrixCols()));
3344 } else {
3345 node.setOp(op = EOpMatrixTimesScalar);
3346 node.setType(TType(basicType, EvqTemporary, 0, right->getMatrixCols(), right->getMatrixRows()));
3347 }
3348 } else if (left->isMatrix() && !right->isMatrix()) {
3349 if (right->isVector()) {
3350 if (left->getMatrixCols() != right->getVectorSize())
3351 return false;
3352 node.setOp(op = EOpMatrixTimesVector);
3353 node.setType(TType(basicType, EvqTemporary, left->getMatrixRows()));
3354 } else {
3355 node.setOp(op = EOpMatrixTimesScalar);
3356 }
3357 } else if (left->isMatrix() && right->isMatrix()) {
3358 if (left->getMatrixCols() != right->getMatrixRows())
3359 return false;
3360 node.setOp(op = EOpMatrixTimesMatrix);
3361 node.setType(TType(basicType, EvqTemporary, 0, right->getMatrixCols(), left->getMatrixRows()));
3362 } else if (! left->isMatrix() && ! right->isMatrix()) {
3363 if (left->isVector() && right->isVector()) {
3364 ; // leave as component product
3365 } else if (left->isVector() || right->isVector()) {
3366 node.setOp(op = EOpVectorTimesScalar);
3367 if (right->isVector())
3368 node.setType(TType(basicType, EvqTemporary, right->getVectorSize()));
3369 }
3370 } else {
3371 return false;
3372 }
3373 break;
3374 case EOpMulAssign:
3375 if (! left->isMatrix() && right->isMatrix()) {
3376 if (left->isVector()) {
3377 if (left->getVectorSize() != right->getMatrixRows() || left->getVectorSize() != right->getMatrixCols())
3378 return false;
3379 node.setOp(op = EOpVectorTimesMatrixAssign);
3380 } else {
3381 return false;
3382 }
3383 } else if (left->isMatrix() && !right->isMatrix()) {
3384 if (right->isVector()) {
3385 return false;
3386 } else {
3387 node.setOp(op = EOpMatrixTimesScalarAssign);
3388 }
3389 } else if (left->isMatrix() && right->isMatrix()) {
3390 if (left->getMatrixCols() != right->getMatrixCols() || left->getMatrixCols() != right->getMatrixRows())
3391 return false;
3392 node.setOp(op = EOpMatrixTimesMatrixAssign);
3393 } else if (!left->isMatrix() && !right->isMatrix()) {
3394 if (left->isVector() && right->isVector()) {
3395 // leave as component product
3396 } else if (left->isVector() || right->isVector()) {
3397 if (! left->isVector())
3398 return false;
3399 node.setOp(op = EOpVectorTimesScalarAssign);
3400 }
3401 } else {
3402 return false;
3403 }
3404 break;
3405
3406 case EOpRightShift:
3407 case EOpLeftShift:
3408 case EOpRightShiftAssign:
3409 case EOpLeftShiftAssign:
3410 if (right->isVector() && (! left->isVector() || right->getVectorSize() != left->getVectorSize()))
3411 return false;
3412 break;
3413
3414 case EOpAssign:
3415 if (left->getVectorSize() != right->getVectorSize() || left->getMatrixCols() != right->getMatrixCols() || left->getMatrixRows() != right->getMatrixRows())
3416 return false;
3417 // fall through
3418
3419 case EOpAdd:
3420 case EOpSub:
3421 case EOpDiv:
3422 case EOpMod:
3423 case EOpAnd:
3424 case EOpInclusiveOr:
3425 case EOpExclusiveOr:
3426 case EOpAddAssign:
3427 case EOpSubAssign:
3428 case EOpDivAssign:
3429 case EOpModAssign:
3430 case EOpAndAssign:
3431 case EOpInclusiveOrAssign:
3432 case EOpExclusiveOrAssign:
3433
3434 if ((left->isMatrix() && right->isVector()) ||
3435 (left->isVector() && right->isMatrix()) ||
3436 left->getBasicType() != right->getBasicType())
3437 return false;
3438 if (left->isMatrix() && right->isMatrix() && (left->getMatrixCols() != right->getMatrixCols() || left->getMatrixRows() != right->getMatrixRows()))
3439 return false;
3440 if (left->isVector() && right->isVector() && left->getVectorSize() != right->getVectorSize())
3441 return false;
3442 if (right->isVector() || right->isMatrix()) {
3443 node.getWritableType().shallowCopy(right->getType());
3444 node.getWritableType().getQualifier().makeTemporary();
3445 }
3446 break;
3447
3448 default:
3449 return false;
3450 }
3451
3452 //
3453 // One more check for assignment.
3454 //
3455 switch (op) {
3456 // The resulting type has to match the left operand.
3457 case EOpAssign:
3458 case EOpAddAssign:
3459 case EOpSubAssign:
3460 case EOpMulAssign:
3461 case EOpDivAssign:
3462 case EOpModAssign:
3463 case EOpAndAssign:
3464 case EOpInclusiveOrAssign:
3465 case EOpExclusiveOrAssign:
3466 case EOpLeftShiftAssign:
3467 case EOpRightShiftAssign:
3468 if (node.getType() != left->getType())
3469 return false;
3470 break;
3471 default:
3472 break;
3473 }
3474
3475 return true;
3476 }
3477
3478 //
3479 // See TIntermediate::promote
3480 //
promoteAggregate(TIntermAggregate & node)3481 bool TIntermediate::promoteAggregate(TIntermAggregate& node)
3482 {
3483 TOperator op = node.getOp();
3484 TIntermSequence& args = node.getSequence();
3485 const int numArgs = static_cast<int>(args.size());
3486
3487 // Presently, only hlsl does intrinsic promotions.
3488 if (getSource() != EShSourceHlsl)
3489 return true;
3490
3491 // set of opcodes that can be promoted in this manner.
3492 switch (op) {
3493 case EOpAtan:
3494 case EOpClamp:
3495 case EOpCross:
3496 case EOpDistance:
3497 case EOpDot:
3498 case EOpDst:
3499 case EOpFaceForward:
3500 // case EOpFindMSB: TODO:
3501 // case EOpFindLSB: TODO:
3502 case EOpFma:
3503 case EOpMod:
3504 case EOpFrexp:
3505 case EOpLdexp:
3506 case EOpMix:
3507 case EOpLit:
3508 case EOpMax:
3509 case EOpMin:
3510 case EOpModf:
3511 // case EOpGenMul: TODO:
3512 case EOpPow:
3513 case EOpReflect:
3514 case EOpRefract:
3515 // case EOpSinCos: TODO:
3516 case EOpSmoothStep:
3517 case EOpStep:
3518 break;
3519 default:
3520 return true;
3521 }
3522
3523 // TODO: array and struct behavior
3524
3525 // Try converting all nodes to the given node's type
3526 TIntermSequence convertedArgs(numArgs, nullptr);
3527
3528 // Try to convert all types to the nonConvArg type.
3529 for (int nonConvArg = 0; nonConvArg < numArgs; ++nonConvArg) {
3530 // Try converting all args to this arg's type
3531 for (int convArg = 0; convArg < numArgs; ++convArg) {
3532 convertedArgs[convArg] = addConversion(op, args[nonConvArg]->getAsTyped()->getType(),
3533 args[convArg]->getAsTyped());
3534 }
3535
3536 // If we successfully converted all the args, use the result.
3537 if (std::all_of(convertedArgs.begin(), convertedArgs.end(),
3538 [](const TIntermNode* node) { return node != nullptr; })) {
3539
3540 std::swap(args, convertedArgs);
3541 return true;
3542 }
3543 }
3544
3545 return false;
3546 }
3547
updatePrecision()3548 void TIntermBinary::updatePrecision()
3549 {
3550 if (getBasicType() == EbtInt || getBasicType() == EbtUint || getBasicType() == EbtFloat || getBasicType() == EbtFloat16) {
3551 getQualifier().precision = std::max(right->getQualifier().precision, left->getQualifier().precision);
3552 if (getQualifier().precision != EpqNone) {
3553 left->propagatePrecision(getQualifier().precision);
3554 right->propagatePrecision(getQualifier().precision);
3555 }
3556 }
3557 }
3558
propagatePrecision(TPrecisionQualifier newPrecision)3559 void TIntermTyped::propagatePrecision(TPrecisionQualifier newPrecision)
3560 {
3561 if (getQualifier().precision != EpqNone || (getBasicType() != EbtInt && getBasicType() != EbtUint && getBasicType() != EbtFloat && getBasicType() != EbtFloat16))
3562 return;
3563
3564 getQualifier().precision = newPrecision;
3565
3566 TIntermBinary* binaryNode = getAsBinaryNode();
3567 if (binaryNode) {
3568 binaryNode->getLeft()->propagatePrecision(newPrecision);
3569 binaryNode->getRight()->propagatePrecision(newPrecision);
3570
3571 return;
3572 }
3573
3574 TIntermUnary* unaryNode = getAsUnaryNode();
3575 if (unaryNode) {
3576 unaryNode->getOperand()->propagatePrecision(newPrecision);
3577
3578 return;
3579 }
3580
3581 TIntermAggregate* aggregateNode = getAsAggregate();
3582 if (aggregateNode) {
3583 TIntermSequence operands = aggregateNode->getSequence();
3584 for (unsigned int i = 0; i < operands.size(); ++i) {
3585 TIntermTyped* typedNode = operands[i]->getAsTyped();
3586 if (! typedNode)
3587 break;
3588 typedNode->propagatePrecision(newPrecision);
3589 }
3590
3591 return;
3592 }
3593
3594 TIntermSelection* selectionNode = getAsSelectionNode();
3595 if (selectionNode) {
3596 TIntermTyped* typedNode = selectionNode->getTrueBlock()->getAsTyped();
3597 if (typedNode) {
3598 typedNode->propagatePrecision(newPrecision);
3599 typedNode = selectionNode->getFalseBlock()->getAsTyped();
3600 if (typedNode)
3601 typedNode->propagatePrecision(newPrecision);
3602 }
3603
3604 return;
3605 }
3606 }
3607
promoteConstantUnion(TBasicType promoteTo,TIntermConstantUnion * node) const3608 TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermConstantUnion* node) const
3609 {
3610 const TConstUnionArray& rightUnionArray = node->getConstArray();
3611 int size = node->getType().computeNumComponents();
3612
3613 TConstUnionArray leftUnionArray(size);
3614
3615 for (int i=0; i < size; i++) {
3616 switch (promoteTo) {
3617 case EbtFloat:
3618 switch (node->getType().getBasicType()) {
3619 case EbtInt:
3620 leftUnionArray[i].setDConst(static_cast<double>(rightUnionArray[i].getIConst()));
3621 break;
3622 case EbtUint:
3623 leftUnionArray[i].setDConst(static_cast<double>(rightUnionArray[i].getUConst()));
3624 break;
3625 case EbtInt64:
3626 leftUnionArray[i].setDConst(static_cast<double>(rightUnionArray[i].getI64Const()));
3627 break;
3628 case EbtUint64:
3629 leftUnionArray[i].setDConst(static_cast<double>(rightUnionArray[i].getU64Const()));
3630 break;
3631 case EbtBool:
3632 leftUnionArray[i].setDConst(static_cast<double>(rightUnionArray[i].getBConst()));
3633 break;
3634 case EbtFloat:
3635 case EbtDouble:
3636 case EbtFloat16:
3637 leftUnionArray[i] = rightUnionArray[i];
3638 break;
3639 default:
3640 return node;
3641 }
3642 break;
3643 case EbtDouble:
3644 switch (node->getType().getBasicType()) {
3645 case EbtInt:
3646 leftUnionArray[i].setDConst(static_cast<double>(rightUnionArray[i].getIConst()));
3647 break;
3648 case EbtUint:
3649 leftUnionArray[i].setDConst(static_cast<double>(rightUnionArray[i].getUConst()));
3650 break;
3651 case EbtInt64:
3652 leftUnionArray[i].setDConst(static_cast<double>(rightUnionArray[i].getI64Const()));
3653 break;
3654 case EbtUint64:
3655 leftUnionArray[i].setDConst(static_cast<double>(rightUnionArray[i].getU64Const()));
3656 break;
3657 case EbtBool:
3658 leftUnionArray[i].setDConst(static_cast<double>(rightUnionArray[i].getBConst()));
3659 break;
3660 case EbtFloat:
3661 case EbtDouble:
3662 case EbtFloat16:
3663 leftUnionArray[i] = rightUnionArray[i];
3664 break;
3665 default:
3666 return node;
3667 }
3668 break;
3669 case EbtFloat16:
3670 switch (node->getType().getBasicType()) {
3671 case EbtInt:
3672 leftUnionArray[i].setDConst(static_cast<double>(rightUnionArray[i].getIConst()));
3673 break;
3674 case EbtUint:
3675 leftUnionArray[i].setDConst(static_cast<double>(rightUnionArray[i].getUConst()));
3676 break;
3677 case EbtInt64:
3678 leftUnionArray[i].setDConst(static_cast<double>(rightUnionArray[i].getI64Const()));
3679 break;
3680 case EbtUint64:
3681 leftUnionArray[i].setDConst(static_cast<double>(rightUnionArray[i].getU64Const()));
3682 break;
3683 case EbtBool:
3684 leftUnionArray[i].setDConst(static_cast<double>(rightUnionArray[i].getBConst()));
3685 break;
3686 case EbtFloat:
3687 case EbtDouble:
3688 case EbtFloat16:
3689 leftUnionArray[i] = rightUnionArray[i];
3690 break;
3691 default:
3692 return node;
3693 }
3694 break;
3695 case EbtInt:
3696 switch (node->getType().getBasicType()) {
3697 case EbtInt:
3698 leftUnionArray[i] = rightUnionArray[i];
3699 break;
3700 case EbtUint:
3701 leftUnionArray[i].setIConst(static_cast<int>(rightUnionArray[i].getUConst()));
3702 break;
3703 case EbtInt64:
3704 leftUnionArray[i].setIConst(static_cast<int>(rightUnionArray[i].getI64Const()));
3705 break;
3706 case EbtUint64:
3707 leftUnionArray[i].setIConst(static_cast<int>(rightUnionArray[i].getU64Const()));
3708 break;
3709 case EbtBool:
3710 leftUnionArray[i].setIConst(static_cast<int>(rightUnionArray[i].getBConst()));
3711 break;
3712 case EbtFloat:
3713 case EbtDouble:
3714 case EbtFloat16:
3715 leftUnionArray[i].setIConst(static_cast<int>(rightUnionArray[i].getDConst()));
3716 break;
3717 default:
3718 return node;
3719 }
3720 break;
3721 case EbtUint:
3722 switch (node->getType().getBasicType()) {
3723 case EbtInt:
3724 leftUnionArray[i].setUConst(static_cast<unsigned int>(rightUnionArray[i].getIConst()));
3725 break;
3726 case EbtUint:
3727 leftUnionArray[i] = rightUnionArray[i];
3728 break;
3729 case EbtInt64:
3730 leftUnionArray[i].setUConst(static_cast<unsigned int>(rightUnionArray[i].getI64Const()));
3731 break;
3732 case EbtUint64:
3733 leftUnionArray[i].setUConst(static_cast<unsigned int>(rightUnionArray[i].getU64Const()));
3734 break;
3735 case EbtBool:
3736 leftUnionArray[i].setUConst(static_cast<unsigned int>(rightUnionArray[i].getBConst()));
3737 break;
3738 case EbtFloat:
3739 case EbtDouble:
3740 case EbtFloat16:
3741 leftUnionArray[i].setUConst(static_cast<unsigned int>(rightUnionArray[i].getDConst()));
3742 break;
3743 default:
3744 return node;
3745 }
3746 break;
3747 case EbtBool:
3748 switch (node->getType().getBasicType()) {
3749 case EbtInt:
3750 leftUnionArray[i].setBConst(rightUnionArray[i].getIConst() != 0);
3751 break;
3752 case EbtUint:
3753 leftUnionArray[i].setBConst(rightUnionArray[i].getUConst() != 0);
3754 break;
3755 case EbtInt64:
3756 leftUnionArray[i].setBConst(rightUnionArray[i].getI64Const() != 0);
3757 break;
3758 case EbtUint64:
3759 leftUnionArray[i].setBConst(rightUnionArray[i].getU64Const() != 0);
3760 break;
3761 case EbtBool:
3762 leftUnionArray[i] = rightUnionArray[i];
3763 break;
3764 case EbtFloat:
3765 case EbtDouble:
3766 case EbtFloat16:
3767 leftUnionArray[i].setBConst(rightUnionArray[i].getDConst() != 0.0);
3768 break;
3769 default:
3770 return node;
3771 }
3772 break;
3773 case EbtInt64:
3774 switch (node->getType().getBasicType()) {
3775 case EbtInt:
3776 leftUnionArray[i].setI64Const(static_cast<long long>(rightUnionArray[i].getIConst()));
3777 break;
3778 case EbtUint:
3779 leftUnionArray[i].setI64Const(static_cast<long long>(rightUnionArray[i].getUConst()));
3780 break;
3781 case EbtInt64:
3782 leftUnionArray[i] = rightUnionArray[i];
3783 break;
3784 case EbtUint64:
3785 leftUnionArray[i].setI64Const(static_cast<long long>(rightUnionArray[i].getU64Const()));
3786 break;
3787 case EbtBool:
3788 leftUnionArray[i].setI64Const(static_cast<long long>(rightUnionArray[i].getBConst()));
3789 break;
3790 case EbtFloat:
3791 case EbtDouble:
3792 case EbtFloat16:
3793 leftUnionArray[i].setI64Const(static_cast<long long>(rightUnionArray[i].getDConst()));
3794 break;
3795 default:
3796 return node;
3797 }
3798 break;
3799 case EbtUint64:
3800 switch (node->getType().getBasicType()) {
3801 case EbtInt:
3802 leftUnionArray[i].setU64Const(static_cast<unsigned long long>(rightUnionArray[i].getIConst()));
3803 break;
3804 case EbtUint:
3805 leftUnionArray[i].setU64Const(static_cast<unsigned long long>(rightUnionArray[i].getUConst()));
3806 break;
3807 case EbtInt64:
3808 leftUnionArray[i].setU64Const(static_cast<unsigned long long>(rightUnionArray[i].getI64Const()));
3809 break;
3810 case EbtUint64:
3811 leftUnionArray[i] = rightUnionArray[i];
3812 break;
3813 case EbtBool:
3814 leftUnionArray[i].setU64Const(static_cast<unsigned long long>(rightUnionArray[i].getBConst()));
3815 break;
3816 case EbtFloat:
3817 case EbtDouble:
3818 case EbtFloat16:
3819 leftUnionArray[i].setU64Const(static_cast<unsigned long long>(rightUnionArray[i].getDConst()));
3820 break;
3821 default:
3822 return node;
3823 }
3824 break;
3825 default:
3826 return node;
3827 }
3828 }
3829
3830 const TType& t = node->getType();
3831
3832 return addConstantUnion(leftUnionArray, TType(promoteTo, t.getQualifier().storage, t.getVectorSize(), t.getMatrixCols(), t.getMatrixRows()),
3833 node->getLoc());
3834 }
3835
setPragmaTable(const TPragmaTable & pTable)3836 void TIntermAggregate::setPragmaTable(const TPragmaTable& pTable)
3837 {
3838 assert(pragmaTable == nullptr);
3839 pragmaTable = new TPragmaTable;
3840 *pragmaTable = pTable;
3841 }
3842
3843 // If either node is a specialization constant, while the other is
3844 // a constant (or specialization constant), the result is still
3845 // a specialization constant.
specConstantPropagates(const TIntermTyped & node1,const TIntermTyped & node2)3846 bool TIntermediate::specConstantPropagates(const TIntermTyped& node1, const TIntermTyped& node2)
3847 {
3848 return (node1.getType().getQualifier().isSpecConstant() && node2.getType().getQualifier().isConstant()) ||
3849 (node2.getType().getQualifier().isSpecConstant() && node1.getType().getQualifier().isConstant());
3850 }
3851
3852 struct TextureUpgradeAndSamplerRemovalTransform : public TIntermTraverser {
visitSymbolglslang::TextureUpgradeAndSamplerRemovalTransform3853 void visitSymbol(TIntermSymbol* symbol) override {
3854 if (symbol->getBasicType() == EbtSampler && symbol->getType().getSampler().isTexture()) {
3855 symbol->getWritableType().getSampler().combined = true;
3856 }
3857 }
visitAggregateglslang::TextureUpgradeAndSamplerRemovalTransform3858 bool visitAggregate(TVisit, TIntermAggregate* ag) override {
3859 using namespace std;
3860 TIntermSequence& seq = ag->getSequence();
3861 TQualifierList& qual = ag->getQualifierList();
3862
3863 // qual and seq are indexed using the same indices, so we have to modify both in lock-step
3864 assert(seq.size() == qual.size() || qual.empty());
3865
3866 size_t write = 0;
3867 for (size_t i = 0; i < seq.size(); ++i) {
3868 TIntermSymbol* symbol = seq[i]->getAsSymbolNode();
3869 if (symbol && symbol->getBasicType() == EbtSampler && symbol->getType().getSampler().isPureSampler()) {
3870 // remove pure sampler variables
3871 continue;
3872 }
3873
3874 TIntermNode* result = seq[i];
3875
3876 // replace constructors with sampler/textures
3877 TIntermAggregate *constructor = seq[i]->getAsAggregate();
3878 if (constructor && constructor->getOp() == EOpConstructTextureSampler) {
3879 if (!constructor->getSequence().empty())
3880 result = constructor->getSequence()[0];
3881 }
3882
3883 // write new node & qualifier
3884 seq[write] = result;
3885 if (!qual.empty())
3886 qual[write] = qual[i];
3887 write++;
3888 }
3889
3890 seq.resize(write);
3891 if (!qual.empty())
3892 qual.resize(write);
3893
3894 return true;
3895 }
3896 };
3897
performTextureUpgradeAndSamplerRemovalTransformation(TIntermNode * root)3898 void TIntermediate::performTextureUpgradeAndSamplerRemovalTransformation(TIntermNode* root)
3899 {
3900 TextureUpgradeAndSamplerRemovalTransform transform;
3901 root->traverse(&transform);
3902 }
3903
getResourceName(TResourceType res)3904 const char* TIntermediate::getResourceName(TResourceType res)
3905 {
3906 switch (res) {
3907 case EResSampler: return "shift-sampler-binding";
3908 case EResTexture: return "shift-texture-binding";
3909 case EResImage: return "shift-image-binding";
3910 case EResUbo: return "shift-UBO-binding";
3911 case EResSsbo: return "shift-ssbo-binding";
3912 case EResUav: return "shift-uav-binding";
3913 default:
3914 assert(0); // internal error: should only be called with valid resource types.
3915 return nullptr;
3916 }
3917 }
3918
3919
3920 } // end namespace glslang
3921