SPV: Generate OpArrayLength with no signedness.
[platform/upstream/glslang.git] / SPIRV / SpvBuilder.cpp
1 //
2 // Copyright (C) 2014-2015 LunarG, Inc.
3 // Copyright (C) 2015-2016 Google, Inc.
4 //
5 // All rights reserved.
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions
9 // are met:
10 //
11 //    Redistributions of source code must retain the above copyright
12 //    notice, this list of conditions and the following disclaimer.
13 //
14 //    Redistributions in binary form must reproduce the above
15 //    copyright notice, this list of conditions and the following
16 //    disclaimer in the documentation and/or other materials provided
17 //    with the distribution.
18 //
19 //    Neither the name of 3Dlabs Inc. Ltd. nor the names of its
20 //    contributors may be used to endorse or promote products derived
21 //    from this software without specific prior written permission.
22 //
23 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27 // COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29 // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 // POSSIBILITY OF SUCH DAMAGE.
35
36 //
37 // Helper for making SPIR-V IR.  Generally, this is documented in the header
38 // SpvBuilder.h.
39 //
40
41 #include <cassert>
42 #include <cstdlib>
43
44 #include <unordered_set>
45 #include <algorithm>
46
47 #include "SpvBuilder.h"
48
49 #include "hex_float.h"
50
51 #ifndef _WIN32
52     #include <cstdio>
53 #endif
54
55 namespace spv {
56
57 Builder::Builder(unsigned int spvVersion, unsigned int magicNumber, SpvBuildLogger* buildLogger) :
58     spvVersion(spvVersion),
59     source(SourceLanguageUnknown),
60     sourceVersion(0),
61     sourceFileStringId(NoResult),
62     currentLine(0),
63     emitOpLines(false),
64     addressModel(AddressingModelLogical),
65     memoryModel(MemoryModelGLSL450),
66     builderNumber(magicNumber),
67     buildPoint(0),
68     uniqueId(0),
69     entryPointFunction(0),
70     generatingOpCodeForSpecConst(false),
71     logger(buildLogger)
72 {
73     clearAccessChain();
74 }
75
76 Builder::~Builder()
77 {
78 }
79
80 Id Builder::import(const char* name)
81 {
82     Instruction* import = new Instruction(getUniqueId(), NoType, OpExtInstImport);
83     import->addStringOperand(name);
84     module.mapInstruction(import);
85
86     imports.push_back(std::unique_ptr<Instruction>(import));
87     return import->getResultId();
88 }
89
90 // Emit an OpLine if we've been asked to emit OpLines and the line number
91 // has changed since the last time, and is a valid line number.
92 void Builder::setLine(int lineNum)
93 {
94     if (lineNum != 0 && lineNum != currentLine) {
95         currentLine = lineNum;
96         if (emitOpLines)
97             addLine(sourceFileStringId, currentLine, 0);
98     }
99 }
100
101 void Builder::addLine(Id fileName, int lineNum, int column)
102 {
103     Instruction* line = new Instruction(OpLine);
104     line->addIdOperand(fileName);
105     line->addImmediateOperand(lineNum);
106     line->addImmediateOperand(column);
107     buildPoint->addInstruction(std::unique_ptr<Instruction>(line));
108 }
109
110 // For creating new groupedTypes (will return old type if the requested one was already made).
111 Id Builder::makeVoidType()
112 {
113     Instruction* type;
114     if (groupedTypes[OpTypeVoid].size() == 0) {
115         type = new Instruction(getUniqueId(), NoType, OpTypeVoid);
116         groupedTypes[OpTypeVoid].push_back(type);
117         constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
118         module.mapInstruction(type);
119     } else
120         type = groupedTypes[OpTypeVoid].back();
121
122     return type->getResultId();
123 }
124
125 Id Builder::makeBoolType()
126 {
127     Instruction* type;
128     if (groupedTypes[OpTypeBool].size() == 0) {
129         type = new Instruction(getUniqueId(), NoType, OpTypeBool);
130         groupedTypes[OpTypeBool].push_back(type);
131         constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
132         module.mapInstruction(type);
133     } else
134         type = groupedTypes[OpTypeBool].back();
135
136     return type->getResultId();
137 }
138
139 Id Builder::makeSamplerType()
140 {
141     Instruction* type;
142     if (groupedTypes[OpTypeSampler].size() == 0) {
143         type = new Instruction(getUniqueId(), NoType, OpTypeSampler);
144         groupedTypes[OpTypeSampler].push_back(type);
145         constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
146         module.mapInstruction(type);
147     } else
148         type = groupedTypes[OpTypeSampler].back();
149
150     return type->getResultId();
151 }
152
153 Id Builder::makePointer(StorageClass storageClass, Id pointee)
154 {
155     // try to find it
156     Instruction* type;
157     for (int t = 0; t < (int)groupedTypes[OpTypePointer].size(); ++t) {
158         type = groupedTypes[OpTypePointer][t];
159         if (type->getImmediateOperand(0) == (unsigned)storageClass &&
160             type->getIdOperand(1) == pointee)
161             return type->getResultId();
162     }
163
164     // not found, make it
165     type = new Instruction(getUniqueId(), NoType, OpTypePointer);
166     type->addImmediateOperand(storageClass);
167     type->addIdOperand(pointee);
168     groupedTypes[OpTypePointer].push_back(type);
169     constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
170     module.mapInstruction(type);
171
172     return type->getResultId();
173 }
174
175 Id Builder::makeIntegerType(int width, bool hasSign)
176 {
177     // try to find it
178     Instruction* type;
179     for (int t = 0; t < (int)groupedTypes[OpTypeInt].size(); ++t) {
180         type = groupedTypes[OpTypeInt][t];
181         if (type->getImmediateOperand(0) == (unsigned)width &&
182             type->getImmediateOperand(1) == (hasSign ? 1u : 0u))
183             return type->getResultId();
184     }
185
186     // not found, make it
187     type = new Instruction(getUniqueId(), NoType, OpTypeInt);
188     type->addImmediateOperand(width);
189     type->addImmediateOperand(hasSign ? 1 : 0);
190     groupedTypes[OpTypeInt].push_back(type);
191     constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
192     module.mapInstruction(type);
193
194     // deal with capabilities
195     switch (width) {
196     case 8:
197     case 16:
198         // these are currently handled by storage-type declarations and post processing
199         break;
200     case 64:
201         addCapability(CapabilityInt64);
202         break;
203     default:
204         break;
205     }
206
207     return type->getResultId();
208 }
209
210 Id Builder::makeFloatType(int width)
211 {
212     // try to find it
213     Instruction* type;
214     for (int t = 0; t < (int)groupedTypes[OpTypeFloat].size(); ++t) {
215         type = groupedTypes[OpTypeFloat][t];
216         if (type->getImmediateOperand(0) == (unsigned)width)
217             return type->getResultId();
218     }
219
220     // not found, make it
221     type = new Instruction(getUniqueId(), NoType, OpTypeFloat);
222     type->addImmediateOperand(width);
223     groupedTypes[OpTypeFloat].push_back(type);
224     constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
225     module.mapInstruction(type);
226
227     // deal with capabilities
228     switch (width) {
229     case 16:
230         // currently handled by storage-type declarations and post processing
231         break;
232     case 64:
233         addCapability(CapabilityFloat64);
234         break;
235     default:
236         break;
237     }
238
239     return type->getResultId();
240 }
241
242 // Make a struct without checking for duplication.
243 // See makeStructResultType() for non-decorated structs
244 // needed as the result of some instructions, which does
245 // check for duplicates.
246 Id Builder::makeStructType(const std::vector<Id>& members, const char* name)
247 {
248     // Don't look for previous one, because in the general case,
249     // structs can be duplicated except for decorations.
250
251     // not found, make it
252     Instruction* type = new Instruction(getUniqueId(), NoType, OpTypeStruct);
253     for (int op = 0; op < (int)members.size(); ++op)
254         type->addIdOperand(members[op]);
255     groupedTypes[OpTypeStruct].push_back(type);
256     constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
257     module.mapInstruction(type);
258     addName(type->getResultId(), name);
259
260     return type->getResultId();
261 }
262
263 // Make a struct for the simple results of several instructions,
264 // checking for duplication.
265 Id Builder::makeStructResultType(Id type0, Id type1)
266 {
267     // try to find it
268     Instruction* type;
269     for (int t = 0; t < (int)groupedTypes[OpTypeStruct].size(); ++t) {
270         type = groupedTypes[OpTypeStruct][t];
271         if (type->getNumOperands() != 2)
272             continue;
273         if (type->getIdOperand(0) != type0 ||
274             type->getIdOperand(1) != type1)
275             continue;
276         return type->getResultId();
277     }
278
279     // not found, make it
280     std::vector<spv::Id> members;
281     members.push_back(type0);
282     members.push_back(type1);
283
284     return makeStructType(members, "ResType");
285 }
286
287 Id Builder::makeVectorType(Id component, int size)
288 {
289     // try to find it
290     Instruction* type;
291     for (int t = 0; t < (int)groupedTypes[OpTypeVector].size(); ++t) {
292         type = groupedTypes[OpTypeVector][t];
293         if (type->getIdOperand(0) == component &&
294             type->getImmediateOperand(1) == (unsigned)size)
295             return type->getResultId();
296     }
297
298     // not found, make it
299     type = new Instruction(getUniqueId(), NoType, OpTypeVector);
300     type->addIdOperand(component);
301     type->addImmediateOperand(size);
302     groupedTypes[OpTypeVector].push_back(type);
303     constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
304     module.mapInstruction(type);
305
306     return type->getResultId();
307 }
308
309 Id Builder::makeMatrixType(Id component, int cols, int rows)
310 {
311     assert(cols <= maxMatrixSize && rows <= maxMatrixSize);
312
313     Id column = makeVectorType(component, rows);
314
315     // try to find it
316     Instruction* type;
317     for (int t = 0; t < (int)groupedTypes[OpTypeMatrix].size(); ++t) {
318         type = groupedTypes[OpTypeMatrix][t];
319         if (type->getIdOperand(0) == column &&
320             type->getImmediateOperand(1) == (unsigned)cols)
321             return type->getResultId();
322     }
323
324     // not found, make it
325     type = new Instruction(getUniqueId(), NoType, OpTypeMatrix);
326     type->addIdOperand(column);
327     type->addImmediateOperand(cols);
328     groupedTypes[OpTypeMatrix].push_back(type);
329     constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
330     module.mapInstruction(type);
331
332     return type->getResultId();
333 }
334
335 // TODO: performance: track arrays per stride
336 // If a stride is supplied (non-zero) make an array.
337 // If no stride (0), reuse previous array types.
338 // 'size' is an Id of a constant or specialization constant of the array size
339 Id Builder::makeArrayType(Id element, Id sizeId, int stride)
340 {
341     Instruction* type;
342     if (stride == 0) {
343         // try to find existing type
344         for (int t = 0; t < (int)groupedTypes[OpTypeArray].size(); ++t) {
345             type = groupedTypes[OpTypeArray][t];
346             if (type->getIdOperand(0) == element &&
347                 type->getIdOperand(1) == sizeId)
348                 return type->getResultId();
349         }
350     }
351
352     // not found, make it
353     type = new Instruction(getUniqueId(), NoType, OpTypeArray);
354     type->addIdOperand(element);
355     type->addIdOperand(sizeId);
356     groupedTypes[OpTypeArray].push_back(type);
357     constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
358     module.mapInstruction(type);
359
360     return type->getResultId();
361 }
362
363 Id Builder::makeRuntimeArray(Id element)
364 {
365     Instruction* type = new Instruction(getUniqueId(), NoType, OpTypeRuntimeArray);
366     type->addIdOperand(element);
367     constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
368     module.mapInstruction(type);
369
370     return type->getResultId();
371 }
372
373 Id Builder::makeFunctionType(Id returnType, const std::vector<Id>& paramTypes)
374 {
375     // try to find it
376     Instruction* type;
377     for (int t = 0; t < (int)groupedTypes[OpTypeFunction].size(); ++t) {
378         type = groupedTypes[OpTypeFunction][t];
379         if (type->getIdOperand(0) != returnType || (int)paramTypes.size() != type->getNumOperands() - 1)
380             continue;
381         bool mismatch = false;
382         for (int p = 0; p < (int)paramTypes.size(); ++p) {
383             if (paramTypes[p] != type->getIdOperand(p + 1)) {
384                 mismatch = true;
385                 break;
386             }
387         }
388         if (! mismatch)
389             return type->getResultId();
390     }
391
392     // not found, make it
393     type = new Instruction(getUniqueId(), NoType, OpTypeFunction);
394     type->addIdOperand(returnType);
395     for (int p = 0; p < (int)paramTypes.size(); ++p)
396         type->addIdOperand(paramTypes[p]);
397     groupedTypes[OpTypeFunction].push_back(type);
398     constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
399     module.mapInstruction(type);
400
401     return type->getResultId();
402 }
403
404 Id Builder::makeImageType(Id sampledType, Dim dim, bool depth, bool arrayed, bool ms, unsigned sampled, ImageFormat format)
405 {
406     assert(sampled == 1 || sampled == 2);
407
408     // try to find it
409     Instruction* type;
410     for (int t = 0; t < (int)groupedTypes[OpTypeImage].size(); ++t) {
411         type = groupedTypes[OpTypeImage][t];
412         if (type->getIdOperand(0) == sampledType &&
413             type->getImmediateOperand(1) == (unsigned int)dim &&
414             type->getImmediateOperand(2) == (  depth ? 1u : 0u) &&
415             type->getImmediateOperand(3) == (arrayed ? 1u : 0u) &&
416             type->getImmediateOperand(4) == (     ms ? 1u : 0u) &&
417             type->getImmediateOperand(5) == sampled &&
418             type->getImmediateOperand(6) == (unsigned int)format)
419             return type->getResultId();
420     }
421
422     // not found, make it
423     type = new Instruction(getUniqueId(), NoType, OpTypeImage);
424     type->addIdOperand(sampledType);
425     type->addImmediateOperand(   dim);
426     type->addImmediateOperand(  depth ? 1 : 0);
427     type->addImmediateOperand(arrayed ? 1 : 0);
428     type->addImmediateOperand(     ms ? 1 : 0);
429     type->addImmediateOperand(sampled);
430     type->addImmediateOperand((unsigned int)format);
431
432     groupedTypes[OpTypeImage].push_back(type);
433     constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
434     module.mapInstruction(type);
435
436     // deal with capabilities
437     switch (dim) {
438     case DimBuffer:
439         if (sampled == 1)
440             addCapability(CapabilitySampledBuffer);
441         else
442             addCapability(CapabilityImageBuffer);
443         break;
444     case Dim1D:
445         if (sampled == 1)
446             addCapability(CapabilitySampled1D);
447         else
448             addCapability(CapabilityImage1D);
449         break;
450     case DimCube:
451         if (arrayed) {
452             if (sampled == 1)
453                 addCapability(CapabilitySampledCubeArray);
454             else
455                 addCapability(CapabilityImageCubeArray);
456         }
457         break;
458     case DimRect:
459         if (sampled == 1)
460             addCapability(CapabilitySampledRect);
461         else
462             addCapability(CapabilityImageRect);
463         break;
464     case DimSubpassData:
465         addCapability(CapabilityInputAttachment);
466         break;
467     default:
468         break;
469     }
470
471     if (ms) {
472         if (sampled == 2) {
473             // Images used with subpass data are not storage
474             // images, so don't require the capability for them.
475             if (dim != Dim::DimSubpassData)
476                 addCapability(CapabilityStorageImageMultisample);
477             if (arrayed)
478                 addCapability(CapabilityImageMSArray);
479         }
480     }
481
482     return type->getResultId();
483 }
484
485 Id Builder::makeSampledImageType(Id imageType)
486 {
487     // try to find it
488     Instruction* type;
489     for (int t = 0; t < (int)groupedTypes[OpTypeSampledImage].size(); ++t) {
490         type = groupedTypes[OpTypeSampledImage][t];
491         if (type->getIdOperand(0) == imageType)
492             return type->getResultId();
493     }
494
495     // not found, make it
496     type = new Instruction(getUniqueId(), NoType, OpTypeSampledImage);
497     type->addIdOperand(imageType);
498
499     groupedTypes[OpTypeSampledImage].push_back(type);
500     constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
501     module.mapInstruction(type);
502
503     return type->getResultId();
504 }
505
506 #ifdef NV_EXTENSIONS
507 Id Builder::makeAccelerationStructureNVType()
508 {
509     Instruction *type;
510     if (groupedTypes[OpTypeAccelerationStructureNV].size() == 0) {
511         type = new Instruction(getUniqueId(), NoType, OpTypeAccelerationStructureNV);
512         constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
513         module.mapInstruction(type);
514     } else {
515         type = groupedTypes[OpTypeAccelerationStructureNV].back();
516     }
517
518     return type->getResultId();
519 }
520 #endif
521 Id Builder::getDerefTypeId(Id resultId) const
522 {
523     Id typeId = getTypeId(resultId);
524     assert(isPointerType(typeId));
525
526     return module.getInstruction(typeId)->getIdOperand(1);
527 }
528
529 Op Builder::getMostBasicTypeClass(Id typeId) const
530 {
531     Instruction* instr = module.getInstruction(typeId);
532
533     Op typeClass = instr->getOpCode();
534     switch (typeClass)
535     {
536     case OpTypeVector:
537     case OpTypeMatrix:
538     case OpTypeArray:
539     case OpTypeRuntimeArray:
540         return getMostBasicTypeClass(instr->getIdOperand(0));
541     case OpTypePointer:
542         return getMostBasicTypeClass(instr->getIdOperand(1));
543     default:
544         return typeClass;
545     }
546 }
547
548 int Builder::getNumTypeConstituents(Id typeId) const
549 {
550     Instruction* instr = module.getInstruction(typeId);
551
552     switch (instr->getOpCode())
553     {
554     case OpTypeBool:
555     case OpTypeInt:
556     case OpTypeFloat:
557         return 1;
558     case OpTypeVector:
559     case OpTypeMatrix:
560         return instr->getImmediateOperand(1);
561     case OpTypeArray:
562     {
563         Id lengthId = instr->getIdOperand(1);
564         return module.getInstruction(lengthId)->getImmediateOperand(0);
565     }
566     case OpTypeStruct:
567         return instr->getNumOperands();
568     default:
569         assert(0);
570         return 1;
571     }
572 }
573
574 // Return the lowest-level type of scalar that an homogeneous composite is made out of.
575 // Typically, this is just to find out if something is made out of ints or floats.
576 // However, it includes returning a structure, if say, it is an array of structure.
577 Id Builder::getScalarTypeId(Id typeId) const
578 {
579     Instruction* instr = module.getInstruction(typeId);
580
581     Op typeClass = instr->getOpCode();
582     switch (typeClass)
583     {
584     case OpTypeVoid:
585     case OpTypeBool:
586     case OpTypeInt:
587     case OpTypeFloat:
588     case OpTypeStruct:
589         return instr->getResultId();
590     case OpTypeVector:
591     case OpTypeMatrix:
592     case OpTypeArray:
593     case OpTypeRuntimeArray:
594     case OpTypePointer:
595         return getScalarTypeId(getContainedTypeId(typeId));
596     default:
597         assert(0);
598         return NoResult;
599     }
600 }
601
602 // Return the type of 'member' of a composite.
603 Id Builder::getContainedTypeId(Id typeId, int member) const
604 {
605     Instruction* instr = module.getInstruction(typeId);
606
607     Op typeClass = instr->getOpCode();
608     switch (typeClass)
609     {
610     case OpTypeVector:
611     case OpTypeMatrix:
612     case OpTypeArray:
613     case OpTypeRuntimeArray:
614         return instr->getIdOperand(0);
615     case OpTypePointer:
616         return instr->getIdOperand(1);
617     case OpTypeStruct:
618         return instr->getIdOperand(member);
619     default:
620         assert(0);
621         return NoResult;
622     }
623 }
624
625 // Return the immediately contained type of a given composite type.
626 Id Builder::getContainedTypeId(Id typeId) const
627 {
628     return getContainedTypeId(typeId, 0);
629 }
630
631 // Returns true if 'typeId' is or contains a scalar type declared with 'typeOp'
632 // of width 'width'. The 'width' is only consumed for int and float types.
633 // Returns false otherwise.
634 bool Builder::containsType(Id typeId, spv::Op typeOp, unsigned int width) const
635 {
636     const Instruction& instr = *module.getInstruction(typeId);
637
638     Op typeClass = instr.getOpCode();
639     switch (typeClass)
640     {
641     case OpTypeInt:
642     case OpTypeFloat:
643         return typeClass == typeOp && instr.getImmediateOperand(0) == width;
644     case OpTypeStruct:
645         for (int m = 0; m < instr.getNumOperands(); ++m) {
646             if (containsType(instr.getIdOperand(m), typeOp, width))
647                 return true;
648         }
649         return false;
650     case OpTypeVector:
651     case OpTypeMatrix:
652     case OpTypeArray:
653     case OpTypeRuntimeArray:
654     case OpTypePointer:
655         return containsType(getContainedTypeId(typeId), typeOp, width);
656     default:
657         return typeClass == typeOp;
658     }
659 }
660
661 // See if a scalar constant of this type has already been created, so it
662 // can be reused rather than duplicated.  (Required by the specification).
663 Id Builder::findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned value)
664 {
665     Instruction* constant;
666     for (int i = 0; i < (int)groupedConstants[typeClass].size(); ++i) {
667         constant = groupedConstants[typeClass][i];
668         if (constant->getOpCode() == opcode &&
669             constant->getTypeId() == typeId &&
670             constant->getImmediateOperand(0) == value)
671             return constant->getResultId();
672     }
673
674     return 0;
675 }
676
677 // Version of findScalarConstant (see above) for scalars that take two operands (e.g. a 'double' or 'int64').
678 Id Builder::findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned v1, unsigned v2)
679 {
680     Instruction* constant;
681     for (int i = 0; i < (int)groupedConstants[typeClass].size(); ++i) {
682         constant = groupedConstants[typeClass][i];
683         if (constant->getOpCode() == opcode &&
684             constant->getTypeId() == typeId &&
685             constant->getImmediateOperand(0) == v1 &&
686             constant->getImmediateOperand(1) == v2)
687             return constant->getResultId();
688     }
689
690     return 0;
691 }
692
693 // Return true if consuming 'opcode' means consuming a constant.
694 // "constant" here means after final transform to executable code,
695 // the value consumed will be a constant, so includes specialization.
696 bool Builder::isConstantOpCode(Op opcode) const
697 {
698     switch (opcode) {
699     case OpUndef:
700     case OpConstantTrue:
701     case OpConstantFalse:
702     case OpConstant:
703     case OpConstantComposite:
704     case OpConstantSampler:
705     case OpConstantNull:
706     case OpSpecConstantTrue:
707     case OpSpecConstantFalse:
708     case OpSpecConstant:
709     case OpSpecConstantComposite:
710     case OpSpecConstantOp:
711         return true;
712     default:
713         return false;
714     }
715 }
716
717 // Return true if consuming 'opcode' means consuming a specialization constant.
718 bool Builder::isSpecConstantOpCode(Op opcode) const
719 {
720     switch (opcode) {
721     case OpSpecConstantTrue:
722     case OpSpecConstantFalse:
723     case OpSpecConstant:
724     case OpSpecConstantComposite:
725     case OpSpecConstantOp:
726         return true;
727     default:
728         return false;
729     }
730 }
731
732 Id Builder::makeBoolConstant(bool b, bool specConstant)
733 {
734     Id typeId = makeBoolType();
735     Instruction* constant;
736     Op opcode = specConstant ? (b ? OpSpecConstantTrue : OpSpecConstantFalse) : (b ? OpConstantTrue : OpConstantFalse);
737
738     // See if we already made it. Applies only to regular constants, because specialization constants
739     // must remain distinct for the purpose of applying a SpecId decoration.
740     if (! specConstant) {
741         Id existing = 0;
742         for (int i = 0; i < (int)groupedConstants[OpTypeBool].size(); ++i) {
743             constant = groupedConstants[OpTypeBool][i];
744             if (constant->getTypeId() == typeId && constant->getOpCode() == opcode)
745                 existing = constant->getResultId();
746         }
747
748         if (existing)
749             return existing;
750     }
751
752     // Make it
753     Instruction* c = new Instruction(getUniqueId(), typeId, opcode);
754     constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(c));
755     groupedConstants[OpTypeBool].push_back(c);
756     module.mapInstruction(c);
757
758     return c->getResultId();
759 }
760
761 Id Builder::makeIntConstant(Id typeId, unsigned value, bool specConstant)
762 {
763     Op opcode = specConstant ? OpSpecConstant : OpConstant;
764
765     // See if we already made it. Applies only to regular constants, because specialization constants
766     // must remain distinct for the purpose of applying a SpecId decoration.
767     if (! specConstant) {
768         Id existing = findScalarConstant(OpTypeInt, opcode, typeId, value);
769         if (existing)
770             return existing;
771     }
772
773     Instruction* c = new Instruction(getUniqueId(), typeId, opcode);
774     c->addImmediateOperand(value);
775     constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(c));
776     groupedConstants[OpTypeInt].push_back(c);
777     module.mapInstruction(c);
778
779     return c->getResultId();
780 }
781
782 Id Builder::makeInt64Constant(Id typeId, unsigned long long value, bool specConstant)
783 {
784     Op opcode = specConstant ? OpSpecConstant : OpConstant;
785
786     unsigned op1 = value & 0xFFFFFFFF;
787     unsigned op2 = value >> 32;
788
789     // See if we already made it. Applies only to regular constants, because specialization constants
790     // must remain distinct for the purpose of applying a SpecId decoration.
791     if (! specConstant) {
792         Id existing = findScalarConstant(OpTypeInt, opcode, typeId, op1, op2);
793         if (existing)
794             return existing;
795     }
796
797     Instruction* c = new Instruction(getUniqueId(), typeId, opcode);
798     c->addImmediateOperand(op1);
799     c->addImmediateOperand(op2);
800     constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(c));
801     groupedConstants[OpTypeInt].push_back(c);
802     module.mapInstruction(c);
803
804     return c->getResultId();
805 }
806
807 Id Builder::makeFloatConstant(float f, bool specConstant)
808 {
809     Op opcode = specConstant ? OpSpecConstant : OpConstant;
810     Id typeId = makeFloatType(32);
811     union { float fl; unsigned int ui; } u;
812     u.fl = f;
813     unsigned value = u.ui;
814
815     // See if we already made it. Applies only to regular constants, because specialization constants
816     // must remain distinct for the purpose of applying a SpecId decoration.
817     if (! specConstant) {
818         Id existing = findScalarConstant(OpTypeFloat, opcode, typeId, value);
819         if (existing)
820             return existing;
821     }
822
823     Instruction* c = new Instruction(getUniqueId(), typeId, opcode);
824     c->addImmediateOperand(value);
825     constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(c));
826     groupedConstants[OpTypeFloat].push_back(c);
827     module.mapInstruction(c);
828
829     return c->getResultId();
830 }
831
832 Id Builder::makeDoubleConstant(double d, bool specConstant)
833 {
834     Op opcode = specConstant ? OpSpecConstant : OpConstant;
835     Id typeId = makeFloatType(64);
836     union { double db; unsigned long long ull; } u;
837     u.db = d;
838     unsigned long long value = u.ull;
839     unsigned op1 = value & 0xFFFFFFFF;
840     unsigned op2 = value >> 32;
841
842     // See if we already made it. Applies only to regular constants, because specialization constants
843     // must remain distinct for the purpose of applying a SpecId decoration.
844     if (! specConstant) {
845         Id existing = findScalarConstant(OpTypeFloat, opcode, typeId, op1, op2);
846         if (existing)
847             return existing;
848     }
849
850     Instruction* c = new Instruction(getUniqueId(), typeId, opcode);
851     c->addImmediateOperand(op1);
852     c->addImmediateOperand(op2);
853     constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(c));
854     groupedConstants[OpTypeFloat].push_back(c);
855     module.mapInstruction(c);
856
857     return c->getResultId();
858 }
859
860 Id Builder::makeFloat16Constant(float f16, bool specConstant)
861 {
862     Op opcode = specConstant ? OpSpecConstant : OpConstant;
863     Id typeId = makeFloatType(16);
864
865     spvutils::HexFloat<spvutils::FloatProxy<float>> fVal(f16);
866     spvutils::HexFloat<spvutils::FloatProxy<spvutils::Float16>> f16Val(0);
867     fVal.castTo(f16Val, spvutils::kRoundToZero);
868
869     unsigned value = f16Val.value().getAsFloat().get_value();
870
871     // See if we already made it. Applies only to regular constants, because specialization constants
872     // must remain distinct for the purpose of applying a SpecId decoration.
873     if (!specConstant) {
874         Id existing = findScalarConstant(OpTypeFloat, opcode, typeId, value);
875         if (existing)
876             return existing;
877     }
878
879     Instruction* c = new Instruction(getUniqueId(), typeId, opcode);
880     c->addImmediateOperand(value);
881     constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(c));
882     groupedConstants[OpTypeFloat].push_back(c);
883     module.mapInstruction(c);
884
885     return c->getResultId();
886 }
887
888 Id Builder::makeFpConstant(Id type, double d, bool specConstant)
889 {
890         assert(isFloatType(type));
891
892         switch (getScalarTypeWidth(type)) {
893         case 16:
894                 return makeFloat16Constant((float)d, specConstant);
895         case 32:
896                 return makeFloatConstant((float)d, specConstant);
897         case 64:
898                 return makeDoubleConstant(d, specConstant);
899         default:
900                 break;
901         }
902
903         assert(false);
904         return NoResult;
905 }
906
907 Id Builder::findCompositeConstant(Op typeClass, const std::vector<Id>& comps)
908 {
909     Instruction* constant = 0;
910     bool found = false;
911     for (int i = 0; i < (int)groupedConstants[typeClass].size(); ++i) {
912         constant = groupedConstants[typeClass][i];
913
914         // same shape?
915         if (constant->getNumOperands() != (int)comps.size())
916             continue;
917
918         // same contents?
919         bool mismatch = false;
920         for (int op = 0; op < constant->getNumOperands(); ++op) {
921             if (constant->getIdOperand(op) != comps[op]) {
922                 mismatch = true;
923                 break;
924             }
925         }
926         if (! mismatch) {
927             found = true;
928             break;
929         }
930     }
931
932     return found ? constant->getResultId() : NoResult;
933 }
934
935 Id Builder::findStructConstant(Id typeId, const std::vector<Id>& comps)
936 {
937     Instruction* constant = 0;
938     bool found = false;
939     for (int i = 0; i < (int)groupedStructConstants[typeId].size(); ++i) {
940         constant = groupedStructConstants[typeId][i];
941
942         // same contents?
943         bool mismatch = false;
944         for (int op = 0; op < constant->getNumOperands(); ++op) {
945             if (constant->getIdOperand(op) != comps[op]) {
946                 mismatch = true;
947                 break;
948             }
949         }
950         if (! mismatch) {
951             found = true;
952             break;
953         }
954     }
955
956     return found ? constant->getResultId() : NoResult;
957 }
958
959 // Comments in header
960 Id Builder::makeCompositeConstant(Id typeId, const std::vector<Id>& members, bool specConstant)
961 {
962     Op opcode = specConstant ? OpSpecConstantComposite : OpConstantComposite;
963     assert(typeId);
964     Op typeClass = getTypeClass(typeId);
965
966     switch (typeClass) {
967     case OpTypeVector:
968     case OpTypeArray:
969     case OpTypeMatrix:
970         if (! specConstant) {
971             Id existing = findCompositeConstant(typeClass, members);
972             if (existing)
973                 return existing;
974         }
975         break;
976     case OpTypeStruct:
977         if (! specConstant) {
978             Id existing = findStructConstant(typeId, members);
979             if (existing)
980                 return existing;
981         }
982         break;
983     default:
984         assert(0);
985         return makeFloatConstant(0.0);
986     }
987
988     Instruction* c = new Instruction(getUniqueId(), typeId, opcode);
989     for (int op = 0; op < (int)members.size(); ++op)
990         c->addIdOperand(members[op]);
991     constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(c));
992     if (typeClass == OpTypeStruct)
993         groupedStructConstants[typeId].push_back(c);
994     else
995         groupedConstants[typeClass].push_back(c);
996     module.mapInstruction(c);
997
998     return c->getResultId();
999 }
1000
1001 Instruction* Builder::addEntryPoint(ExecutionModel model, Function* function, const char* name)
1002 {
1003     Instruction* entryPoint = new Instruction(OpEntryPoint);
1004     entryPoint->addImmediateOperand(model);
1005     entryPoint->addIdOperand(function->getId());
1006     entryPoint->addStringOperand(name);
1007
1008     entryPoints.push_back(std::unique_ptr<Instruction>(entryPoint));
1009
1010     return entryPoint;
1011 }
1012
1013 // Currently relying on the fact that all 'value' of interest are small non-negative values.
1014 void Builder::addExecutionMode(Function* entryPoint, ExecutionMode mode, int value1, int value2, int value3)
1015 {
1016     Instruction* instr = new Instruction(OpExecutionMode);
1017     instr->addIdOperand(entryPoint->getId());
1018     instr->addImmediateOperand(mode);
1019     if (value1 >= 0)
1020         instr->addImmediateOperand(value1);
1021     if (value2 >= 0)
1022         instr->addImmediateOperand(value2);
1023     if (value3 >= 0)
1024         instr->addImmediateOperand(value3);
1025
1026     executionModes.push_back(std::unique_ptr<Instruction>(instr));
1027 }
1028
1029 void Builder::addName(Id id, const char* string)
1030 {
1031     Instruction* name = new Instruction(OpName);
1032     name->addIdOperand(id);
1033     name->addStringOperand(string);
1034
1035     names.push_back(std::unique_ptr<Instruction>(name));
1036 }
1037
1038 void Builder::addMemberName(Id id, int memberNumber, const char* string)
1039 {
1040     Instruction* name = new Instruction(OpMemberName);
1041     name->addIdOperand(id);
1042     name->addImmediateOperand(memberNumber);
1043     name->addStringOperand(string);
1044
1045     names.push_back(std::unique_ptr<Instruction>(name));
1046 }
1047
1048 void Builder::addDecoration(Id id, Decoration decoration, int num)
1049 {
1050     if (decoration == spv::DecorationMax)
1051         return;
1052
1053     Instruction* dec = new Instruction(OpDecorate);
1054     dec->addIdOperand(id);
1055     dec->addImmediateOperand(decoration);
1056     if (num >= 0)
1057         dec->addImmediateOperand(num);
1058
1059     decorations.push_back(std::unique_ptr<Instruction>(dec));
1060 }
1061
1062 void Builder::addDecoration(Id id, Decoration decoration, const char* s)
1063 {
1064     if (decoration == spv::DecorationMax)
1065         return;
1066
1067     Instruction* dec = new Instruction(OpDecorateStringGOOGLE);
1068     dec->addIdOperand(id);
1069     dec->addImmediateOperand(decoration);
1070     dec->addStringOperand(s);
1071
1072     decorations.push_back(std::unique_ptr<Instruction>(dec));
1073 }
1074
1075 void Builder::addDecorationId(Id id, Decoration decoration, Id idDecoration)
1076 {
1077     if (decoration == spv::DecorationMax)
1078         return;
1079
1080     Instruction* dec = new Instruction(OpDecorateId);
1081     dec->addIdOperand(id);
1082     dec->addImmediateOperand(decoration);
1083     dec->addIdOperand(idDecoration);
1084
1085     decorations.push_back(std::unique_ptr<Instruction>(dec));
1086 }
1087
1088 void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decoration, int num)
1089 {
1090     if (decoration == spv::DecorationMax)
1091         return;
1092
1093     Instruction* dec = new Instruction(OpMemberDecorate);
1094     dec->addIdOperand(id);
1095     dec->addImmediateOperand(member);
1096     dec->addImmediateOperand(decoration);
1097     if (num >= 0)
1098         dec->addImmediateOperand(num);
1099
1100     decorations.push_back(std::unique_ptr<Instruction>(dec));
1101 }
1102
1103 void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decoration, const char *s)
1104 {
1105     if (decoration == spv::DecorationMax)
1106         return;
1107
1108     Instruction* dec = new Instruction(OpMemberDecorateStringGOOGLE);
1109     dec->addIdOperand(id);
1110     dec->addImmediateOperand(member);
1111     dec->addImmediateOperand(decoration);
1112     dec->addStringOperand(s);
1113
1114     decorations.push_back(std::unique_ptr<Instruction>(dec));
1115 }
1116
1117 // Comments in header
1118 Function* Builder::makeEntryPoint(const char* entryPoint)
1119 {
1120     assert(! entryPointFunction);
1121
1122     Block* entry;
1123     std::vector<Id> params;
1124     std::vector<std::vector<Decoration>> decorations;
1125
1126     entryPointFunction = makeFunctionEntry(NoPrecision, makeVoidType(), entryPoint, params, decorations, &entry);
1127
1128     return entryPointFunction;
1129 }
1130
1131 // Comments in header
1132 Function* Builder::makeFunctionEntry(Decoration precision, Id returnType, const char* name,
1133                                      const std::vector<Id>& paramTypes, const std::vector<std::vector<Decoration>>& decorations, Block **entry)
1134 {
1135     // Make the function and initial instructions in it
1136     Id typeId = makeFunctionType(returnType, paramTypes);
1137     Id firstParamId = paramTypes.size() == 0 ? 0 : getUniqueIds((int)paramTypes.size());
1138     Function* function = new Function(getUniqueId(), returnType, typeId, firstParamId, module);
1139
1140     // Set up the precisions
1141     setPrecision(function->getId(), precision);
1142     for (unsigned p = 0; p < (unsigned)decorations.size(); ++p) {
1143         for (int d = 0; d < (int)decorations[p].size(); ++d)
1144             addDecoration(firstParamId + p, decorations[p][d]);
1145     }
1146
1147     // CFG
1148     if (entry) {
1149         *entry = new Block(getUniqueId(), *function);
1150         function->addBlock(*entry);
1151         setBuildPoint(*entry);
1152     }
1153
1154     if (name)
1155         addName(function->getId(), name);
1156
1157     functions.push_back(std::unique_ptr<Function>(function));
1158
1159     return function;
1160 }
1161
1162 // Comments in header
1163 void Builder::makeReturn(bool implicit, Id retVal)
1164 {
1165     if (retVal) {
1166         Instruction* inst = new Instruction(NoResult, NoType, OpReturnValue);
1167         inst->addIdOperand(retVal);
1168         buildPoint->addInstruction(std::unique_ptr<Instruction>(inst));
1169     } else
1170         buildPoint->addInstruction(std::unique_ptr<Instruction>(new Instruction(NoResult, NoType, OpReturn)));
1171
1172     if (! implicit)
1173         createAndSetNoPredecessorBlock("post-return");
1174 }
1175
1176 // Comments in header
1177 void Builder::leaveFunction()
1178 {
1179     Block* block = buildPoint;
1180     Function& function = buildPoint->getParent();
1181     assert(block);
1182
1183     // If our function did not contain a return, add a return void now.
1184     if (! block->isTerminated()) {
1185         if (function.getReturnType() == makeVoidType())
1186             makeReturn(true);
1187         else {
1188             makeReturn(true, createUndefined(function.getReturnType()));
1189         }
1190     }
1191 }
1192
1193 // Comments in header
1194 void Builder::makeDiscard()
1195 {
1196     buildPoint->addInstruction(std::unique_ptr<Instruction>(new Instruction(OpKill)));
1197     createAndSetNoPredecessorBlock("post-discard");
1198 }
1199
1200 // Comments in header
1201 Id Builder::createVariable(StorageClass storageClass, Id type, const char* name)
1202 {
1203     Id pointerType = makePointer(storageClass, type);
1204     Instruction* inst = new Instruction(getUniqueId(), pointerType, OpVariable);
1205     inst->addImmediateOperand(storageClass);
1206
1207     switch (storageClass) {
1208     case StorageClassFunction:
1209         // Validation rules require the declaration in the entry block
1210         buildPoint->getParent().addLocalVariable(std::unique_ptr<Instruction>(inst));
1211         break;
1212
1213     default:
1214         constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(inst));
1215         module.mapInstruction(inst);
1216         break;
1217     }
1218
1219     if (name)
1220         addName(inst->getResultId(), name);
1221
1222     return inst->getResultId();
1223 }
1224
1225 // Comments in header
1226 Id Builder::createUndefined(Id type)
1227 {
1228   Instruction* inst = new Instruction(getUniqueId(), type, OpUndef);
1229   buildPoint->addInstruction(std::unique_ptr<Instruction>(inst));
1230   return inst->getResultId();
1231 }
1232
1233 // Comments in header
1234 void Builder::createStore(Id rValue, Id lValue, spv::MemoryAccessMask memoryAccess, spv::Scope scope)
1235 {
1236     Instruction* store = new Instruction(OpStore);
1237     store->addIdOperand(lValue);
1238     store->addIdOperand(rValue);
1239
1240     if (memoryAccess != MemoryAccessMaskNone) {
1241         store->addImmediateOperand(memoryAccess);
1242         if (memoryAccess & spv::MemoryAccessMakePointerAvailableKHRMask) {
1243             store->addIdOperand(makeUintConstant(scope));
1244         }
1245     }
1246
1247     buildPoint->addInstruction(std::unique_ptr<Instruction>(store));
1248 }
1249
1250 // Comments in header
1251 Id Builder::createLoad(Id lValue, spv::MemoryAccessMask memoryAccess, spv::Scope scope)
1252 {
1253     Instruction* load = new Instruction(getUniqueId(), getDerefTypeId(lValue), OpLoad);
1254     load->addIdOperand(lValue);
1255
1256     if (memoryAccess != MemoryAccessMaskNone) {
1257         load->addImmediateOperand(memoryAccess);
1258         if (memoryAccess & spv::MemoryAccessMakePointerVisibleKHRMask) {
1259             load->addIdOperand(makeUintConstant(scope));
1260         }
1261     }
1262
1263     buildPoint->addInstruction(std::unique_ptr<Instruction>(load));
1264
1265     return load->getResultId();
1266 }
1267
1268 // Comments in header
1269 Id Builder::createAccessChain(StorageClass storageClass, Id base, const std::vector<Id>& offsets)
1270 {
1271     // Figure out the final resulting type.
1272     spv::Id typeId = getTypeId(base);
1273     assert(isPointerType(typeId) && offsets.size() > 0);
1274     typeId = getContainedTypeId(typeId);
1275     for (int i = 0; i < (int)offsets.size(); ++i) {
1276         if (isStructType(typeId)) {
1277             assert(isConstantScalar(offsets[i]));
1278             typeId = getContainedTypeId(typeId, getConstantScalar(offsets[i]));
1279         } else
1280             typeId = getContainedTypeId(typeId, offsets[i]);
1281     }
1282     typeId = makePointer(storageClass, typeId);
1283
1284     // Make the instruction
1285     Instruction* chain = new Instruction(getUniqueId(), typeId, OpAccessChain);
1286     chain->addIdOperand(base);
1287     for (int i = 0; i < (int)offsets.size(); ++i)
1288         chain->addIdOperand(offsets[i]);
1289     buildPoint->addInstruction(std::unique_ptr<Instruction>(chain));
1290
1291     return chain->getResultId();
1292 }
1293
1294 Id Builder::createArrayLength(Id base, unsigned int member)
1295 {
1296     spv::Id intType = makeUintType(32);
1297     Instruction* length = new Instruction(getUniqueId(), intType, OpArrayLength);
1298     length->addIdOperand(base);
1299     length->addImmediateOperand(member);
1300     buildPoint->addInstruction(std::unique_ptr<Instruction>(length));
1301
1302     return length->getResultId();
1303 }
1304
1305 Id Builder::createCompositeExtract(Id composite, Id typeId, unsigned index)
1306 {
1307     // Generate code for spec constants if in spec constant operation
1308     // generation mode.
1309     if (generatingOpCodeForSpecConst) {
1310         return createSpecConstantOp(OpCompositeExtract, typeId, std::vector<Id>(1, composite), std::vector<Id>(1, index));
1311     }
1312     Instruction* extract = new Instruction(getUniqueId(), typeId, OpCompositeExtract);
1313     extract->addIdOperand(composite);
1314     extract->addImmediateOperand(index);
1315     buildPoint->addInstruction(std::unique_ptr<Instruction>(extract));
1316
1317     return extract->getResultId();
1318 }
1319
1320 Id Builder::createCompositeExtract(Id composite, Id typeId, const std::vector<unsigned>& indexes)
1321 {
1322     // Generate code for spec constants if in spec constant operation
1323     // generation mode.
1324     if (generatingOpCodeForSpecConst) {
1325         return createSpecConstantOp(OpCompositeExtract, typeId, std::vector<Id>(1, composite), indexes);
1326     }
1327     Instruction* extract = new Instruction(getUniqueId(), typeId, OpCompositeExtract);
1328     extract->addIdOperand(composite);
1329     for (int i = 0; i < (int)indexes.size(); ++i)
1330         extract->addImmediateOperand(indexes[i]);
1331     buildPoint->addInstruction(std::unique_ptr<Instruction>(extract));
1332
1333     return extract->getResultId();
1334 }
1335
1336 Id Builder::createCompositeInsert(Id object, Id composite, Id typeId, unsigned index)
1337 {
1338     Instruction* insert = new Instruction(getUniqueId(), typeId, OpCompositeInsert);
1339     insert->addIdOperand(object);
1340     insert->addIdOperand(composite);
1341     insert->addImmediateOperand(index);
1342     buildPoint->addInstruction(std::unique_ptr<Instruction>(insert));
1343
1344     return insert->getResultId();
1345 }
1346
1347 Id Builder::createCompositeInsert(Id object, Id composite, Id typeId, const std::vector<unsigned>& indexes)
1348 {
1349     Instruction* insert = new Instruction(getUniqueId(), typeId, OpCompositeInsert);
1350     insert->addIdOperand(object);
1351     insert->addIdOperand(composite);
1352     for (int i = 0; i < (int)indexes.size(); ++i)
1353         insert->addImmediateOperand(indexes[i]);
1354     buildPoint->addInstruction(std::unique_ptr<Instruction>(insert));
1355
1356     return insert->getResultId();
1357 }
1358
1359 Id Builder::createVectorExtractDynamic(Id vector, Id typeId, Id componentIndex)
1360 {
1361     Instruction* extract = new Instruction(getUniqueId(), typeId, OpVectorExtractDynamic);
1362     extract->addIdOperand(vector);
1363     extract->addIdOperand(componentIndex);
1364     buildPoint->addInstruction(std::unique_ptr<Instruction>(extract));
1365
1366     return extract->getResultId();
1367 }
1368
1369 Id Builder::createVectorInsertDynamic(Id vector, Id typeId, Id component, Id componentIndex)
1370 {
1371     Instruction* insert = new Instruction(getUniqueId(), typeId, OpVectorInsertDynamic);
1372     insert->addIdOperand(vector);
1373     insert->addIdOperand(component);
1374     insert->addIdOperand(componentIndex);
1375     buildPoint->addInstruction(std::unique_ptr<Instruction>(insert));
1376
1377     return insert->getResultId();
1378 }
1379
1380 // An opcode that has no operands, no result id, and no type
1381 void Builder::createNoResultOp(Op opCode)
1382 {
1383     Instruction* op = new Instruction(opCode);
1384     buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
1385 }
1386
1387 // An opcode that has one id operand, no result id, and no type
1388 void Builder::createNoResultOp(Op opCode, Id operand)
1389 {
1390     Instruction* op = new Instruction(opCode);
1391     op->addIdOperand(operand);
1392     buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
1393 }
1394
1395 // An opcode that has one or more operands, no result id, and no type
1396 void Builder::createNoResultOp(Op opCode, const std::vector<Id>& operands)
1397 {
1398     Instruction* op = new Instruction(opCode);
1399     for (auto it = operands.cbegin(); it != operands.cend(); ++it) {
1400         op->addIdOperand(*it);
1401     }
1402     buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
1403 }
1404
1405 // An opcode that has multiple operands, no result id, and no type
1406 void Builder::createNoResultOp(Op opCode, const std::vector<IdImmediate>& operands)
1407 {
1408     Instruction* op = new Instruction(opCode);
1409     for (auto it = operands.cbegin(); it != operands.cend(); ++it) {
1410         if (it->isId)
1411             op->addIdOperand(it->word);
1412         else
1413             op->addImmediateOperand(it->word);
1414     }
1415     buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
1416 }
1417
1418 void Builder::createControlBarrier(Scope execution, Scope memory, MemorySemanticsMask semantics)
1419 {
1420     Instruction* op = new Instruction(OpControlBarrier);
1421     op->addIdOperand(makeUintConstant(execution));
1422     op->addIdOperand(makeUintConstant(memory));
1423     op->addIdOperand(makeUintConstant(semantics));
1424     buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
1425 }
1426
1427 void Builder::createMemoryBarrier(unsigned executionScope, unsigned memorySemantics)
1428 {
1429     Instruction* op = new Instruction(OpMemoryBarrier);
1430     op->addIdOperand(makeUintConstant(executionScope));
1431     op->addIdOperand(makeUintConstant(memorySemantics));
1432     buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
1433 }
1434
1435 // An opcode that has one operands, a result id, and a type
1436 Id Builder::createUnaryOp(Op opCode, Id typeId, Id operand)
1437 {
1438     // Generate code for spec constants if in spec constant operation
1439     // generation mode.
1440     if (generatingOpCodeForSpecConst) {
1441         return createSpecConstantOp(opCode, typeId, std::vector<Id>(1, operand), std::vector<Id>());
1442     }
1443     Instruction* op = new Instruction(getUniqueId(), typeId, opCode);
1444     op->addIdOperand(operand);
1445     buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
1446
1447     return op->getResultId();
1448 }
1449
1450 Id Builder::createBinOp(Op opCode, Id typeId, Id left, Id right)
1451 {
1452     // Generate code for spec constants if in spec constant operation
1453     // generation mode.
1454     if (generatingOpCodeForSpecConst) {
1455         std::vector<Id> operands(2);
1456         operands[0] = left; operands[1] = right;
1457         return createSpecConstantOp(opCode, typeId, operands, std::vector<Id>());
1458     }
1459     Instruction* op = new Instruction(getUniqueId(), typeId, opCode);
1460     op->addIdOperand(left);
1461     op->addIdOperand(right);
1462     buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
1463
1464     return op->getResultId();
1465 }
1466
1467 Id Builder::createTriOp(Op opCode, Id typeId, Id op1, Id op2, Id op3)
1468 {
1469     // Generate code for spec constants if in spec constant operation
1470     // generation mode.
1471     if (generatingOpCodeForSpecConst) {
1472         std::vector<Id> operands(3);
1473         operands[0] = op1;
1474         operands[1] = op2;
1475         operands[2] = op3;
1476         return createSpecConstantOp(
1477             opCode, typeId, operands, std::vector<Id>());
1478     }
1479     Instruction* op = new Instruction(getUniqueId(), typeId, opCode);
1480     op->addIdOperand(op1);
1481     op->addIdOperand(op2);
1482     op->addIdOperand(op3);
1483     buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
1484
1485     return op->getResultId();
1486 }
1487
1488 Id Builder::createOp(Op opCode, Id typeId, const std::vector<Id>& operands)
1489 {
1490     Instruction* op = new Instruction(getUniqueId(), typeId, opCode);
1491     for (auto it = operands.cbegin(); it != operands.cend(); ++it)
1492         op->addIdOperand(*it);
1493     buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
1494
1495     return op->getResultId();
1496 }
1497
1498 Id Builder::createOp(Op opCode, Id typeId, const std::vector<IdImmediate>& operands)
1499 {
1500     Instruction* op = new Instruction(getUniqueId(), typeId, opCode);
1501     for (auto it = operands.cbegin(); it != operands.cend(); ++it) {
1502         if (it->isId)
1503             op->addIdOperand(it->word);
1504         else
1505             op->addImmediateOperand(it->word);
1506     }
1507     buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
1508
1509     return op->getResultId();
1510 }
1511
1512 Id Builder::createSpecConstantOp(Op opCode, Id typeId, const std::vector<Id>& operands, const std::vector<unsigned>& literals)
1513 {
1514     Instruction* op = new Instruction(getUniqueId(), typeId, OpSpecConstantOp);
1515     op->addImmediateOperand((unsigned) opCode);
1516     for (auto it = operands.cbegin(); it != operands.cend(); ++it)
1517         op->addIdOperand(*it);
1518     for (auto it = literals.cbegin(); it != literals.cend(); ++it)
1519         op->addImmediateOperand(*it);
1520     module.mapInstruction(op);
1521     constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(op));
1522
1523     return op->getResultId();
1524 }
1525
1526 Id Builder::createFunctionCall(spv::Function* function, const std::vector<spv::Id>& args)
1527 {
1528     Instruction* op = new Instruction(getUniqueId(), function->getReturnType(), OpFunctionCall);
1529     op->addIdOperand(function->getId());
1530     for (int a = 0; a < (int)args.size(); ++a)
1531         op->addIdOperand(args[a]);
1532     buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
1533
1534     return op->getResultId();
1535 }
1536
1537 // Comments in header
1538 Id Builder::createRvalueSwizzle(Decoration precision, Id typeId, Id source, const std::vector<unsigned>& channels)
1539 {
1540     if (channels.size() == 1)
1541         return setPrecision(createCompositeExtract(source, typeId, channels.front()), precision);
1542
1543     if (generatingOpCodeForSpecConst) {
1544         std::vector<Id> operands(2);
1545         operands[0] = operands[1] = source;
1546         return setPrecision(createSpecConstantOp(OpVectorShuffle, typeId, operands, channels), precision);
1547     }
1548     Instruction* swizzle = new Instruction(getUniqueId(), typeId, OpVectorShuffle);
1549     assert(isVector(source));
1550     swizzle->addIdOperand(source);
1551     swizzle->addIdOperand(source);
1552     for (int i = 0; i < (int)channels.size(); ++i)
1553         swizzle->addImmediateOperand(channels[i]);
1554     buildPoint->addInstruction(std::unique_ptr<Instruction>(swizzle));
1555
1556     return setPrecision(swizzle->getResultId(), precision);
1557 }
1558
1559 // Comments in header
1560 Id Builder::createLvalueSwizzle(Id typeId, Id target, Id source, const std::vector<unsigned>& channels)
1561 {
1562     if (channels.size() == 1 && getNumComponents(source) == 1)
1563         return createCompositeInsert(source, target, typeId, channels.front());
1564
1565     Instruction* swizzle = new Instruction(getUniqueId(), typeId, OpVectorShuffle);
1566
1567     assert(isVector(target));
1568     swizzle->addIdOperand(target);
1569
1570     assert(getNumComponents(source) == (int)channels.size());
1571     assert(isVector(source));
1572     swizzle->addIdOperand(source);
1573
1574     // Set up an identity shuffle from the base value to the result value
1575     unsigned int components[4];
1576     int numTargetComponents = getNumComponents(target);
1577     for (int i = 0; i < numTargetComponents; ++i)
1578         components[i] = i;
1579
1580     // Punch in the l-value swizzle
1581     for (int i = 0; i < (int)channels.size(); ++i)
1582         components[channels[i]] = numTargetComponents + i;
1583
1584     // finish the instruction with these components selectors
1585     for (int i = 0; i < numTargetComponents; ++i)
1586         swizzle->addImmediateOperand(components[i]);
1587     buildPoint->addInstruction(std::unique_ptr<Instruction>(swizzle));
1588
1589     return swizzle->getResultId();
1590 }
1591
1592 // Comments in header
1593 void Builder::promoteScalar(Decoration precision, Id& left, Id& right)
1594 {
1595     int direction = getNumComponents(right) - getNumComponents(left);
1596
1597     if (direction > 0)
1598         left = smearScalar(precision, left, makeVectorType(getTypeId(left), getNumComponents(right)));
1599     else if (direction < 0)
1600         right = smearScalar(precision, right, makeVectorType(getTypeId(right), getNumComponents(left)));
1601
1602     return;
1603 }
1604
1605 // Comments in header
1606 Id Builder::smearScalar(Decoration precision, Id scalar, Id vectorType)
1607 {
1608     assert(getNumComponents(scalar) == 1);
1609     assert(getTypeId(scalar) == getScalarTypeId(vectorType));
1610
1611     int numComponents = getNumTypeComponents(vectorType);
1612     if (numComponents == 1)
1613         return scalar;
1614
1615     Instruction* smear = nullptr;
1616     if (generatingOpCodeForSpecConst) {
1617         auto members = std::vector<spv::Id>(numComponents, scalar);
1618         // Sometime even in spec-constant-op mode, the temporary vector created by
1619         // promoting a scalar might not be a spec constant. This should depend on
1620         // the scalar.
1621         // e.g.:
1622         //  const vec2 spec_const_result = a_spec_const_vec2 + a_front_end_const_scalar;
1623         // In such cases, the temporary vector created from a_front_end_const_scalar
1624         // is not a spec constant vector, even though the binary operation node is marked
1625         // as 'specConstant' and we are in spec-constant-op mode.
1626         auto result_id = makeCompositeConstant(vectorType, members, isSpecConstant(scalar));
1627         smear = module.getInstruction(result_id);
1628     } else {
1629         smear = new Instruction(getUniqueId(), vectorType, OpCompositeConstruct);
1630         for (int c = 0; c < numComponents; ++c)
1631             smear->addIdOperand(scalar);
1632         buildPoint->addInstruction(std::unique_ptr<Instruction>(smear));
1633     }
1634
1635     return setPrecision(smear->getResultId(), precision);
1636 }
1637
1638 // Comments in header
1639 Id Builder::createBuiltinCall(Id resultType, Id builtins, int entryPoint, const std::vector<Id>& args)
1640 {
1641     Instruction* inst = new Instruction(getUniqueId(), resultType, OpExtInst);
1642     inst->addIdOperand(builtins);
1643     inst->addImmediateOperand(entryPoint);
1644     for (int arg = 0; arg < (int)args.size(); ++arg)
1645         inst->addIdOperand(args[arg]);
1646
1647     buildPoint->addInstruction(std::unique_ptr<Instruction>(inst));
1648
1649     return inst->getResultId();
1650 }
1651
1652 // Accept all parameters needed to create a texture instruction.
1653 // Create the correct instruction based on the inputs, and make the call.
1654 Id Builder::createTextureCall(Decoration precision, Id resultType, bool sparse, bool fetch, bool proj, bool gather,
1655     bool noImplicitLod, const TextureParameters& parameters)
1656 {
1657     static const int maxTextureArgs = 10;
1658     Id texArgs[maxTextureArgs] = {};
1659
1660     //
1661     // Set up the fixed arguments
1662     //
1663     int numArgs = 0;
1664     bool explicitLod = false;
1665     texArgs[numArgs++] = parameters.sampler;
1666     texArgs[numArgs++] = parameters.coords;
1667     if (parameters.Dref != NoResult)
1668         texArgs[numArgs++] = parameters.Dref;
1669     if (parameters.component != NoResult)
1670         texArgs[numArgs++] = parameters.component;
1671
1672 #ifdef NV_EXTENSIONS
1673     if (parameters.granularity != NoResult)
1674         texArgs[numArgs++] = parameters.granularity;
1675     if (parameters.coarse != NoResult)
1676         texArgs[numArgs++] = parameters.coarse;
1677 #endif 
1678
1679     //
1680     // Set up the optional arguments
1681     //
1682     int optArgNum = numArgs;                        // track which operand, if it exists, is the mask of optional arguments
1683     ++numArgs;                                      // speculatively make room for the mask operand
1684     ImageOperandsMask mask = ImageOperandsMaskNone; // the mask operand
1685     if (parameters.bias) {
1686         mask = (ImageOperandsMask)(mask | ImageOperandsBiasMask);
1687         texArgs[numArgs++] = parameters.bias;
1688     }
1689     if (parameters.lod) {
1690         mask = (ImageOperandsMask)(mask | ImageOperandsLodMask);
1691         texArgs[numArgs++] = parameters.lod;
1692         explicitLod = true;
1693     } else if (parameters.gradX) {
1694         mask = (ImageOperandsMask)(mask | ImageOperandsGradMask);
1695         texArgs[numArgs++] = parameters.gradX;
1696         texArgs[numArgs++] = parameters.gradY;
1697         explicitLod = true;
1698     } else if (noImplicitLod && ! fetch && ! gather) {
1699         // have to explicitly use lod of 0 if not allowed to have them be implicit, and
1700         // we would otherwise be about to issue an implicit instruction
1701         mask = (ImageOperandsMask)(mask | ImageOperandsLodMask);
1702         texArgs[numArgs++] = makeFloatConstant(0.0);
1703         explicitLod = true;
1704     }
1705     if (parameters.offset) {
1706         if (isConstant(parameters.offset))
1707             mask = (ImageOperandsMask)(mask | ImageOperandsConstOffsetMask);
1708         else {
1709             addCapability(CapabilityImageGatherExtended);
1710             mask = (ImageOperandsMask)(mask | ImageOperandsOffsetMask);
1711         }
1712         texArgs[numArgs++] = parameters.offset;
1713     }
1714     if (parameters.offsets) {
1715         addCapability(CapabilityImageGatherExtended);
1716         mask = (ImageOperandsMask)(mask | ImageOperandsConstOffsetsMask);
1717         texArgs[numArgs++] = parameters.offsets;
1718     }
1719     if (parameters.sample) {
1720         mask = (ImageOperandsMask)(mask | ImageOperandsSampleMask);
1721         texArgs[numArgs++] = parameters.sample;
1722     }
1723     if (parameters.lodClamp) {
1724         // capability if this bit is used
1725         addCapability(CapabilityMinLod);
1726
1727         mask = (ImageOperandsMask)(mask | ImageOperandsMinLodMask);
1728         texArgs[numArgs++] = parameters.lodClamp;
1729     }
1730     if (parameters.nonprivate) {
1731         mask = mask | ImageOperandsNonPrivateTexelKHRMask;
1732     }
1733     if (parameters.volatil) {
1734         mask = mask | ImageOperandsVolatileTexelKHRMask;
1735     }
1736     if (mask == ImageOperandsMaskNone)
1737         --numArgs;  // undo speculative reservation for the mask argument
1738     else
1739         texArgs[optArgNum] = mask;
1740
1741     //
1742     // Set up the instruction
1743     //
1744     Op opCode = OpNop;  // All paths below need to set this
1745     if (fetch) {
1746         if (sparse)
1747             opCode = OpImageSparseFetch;
1748         else
1749             opCode = OpImageFetch;
1750 #ifdef NV_EXTENSIONS
1751     } else if (parameters.granularity && parameters.coarse) {
1752         opCode = OpImageSampleFootprintNV;
1753 #endif
1754     } else if (gather) {
1755         if (parameters.Dref)
1756             if (sparse)
1757                 opCode = OpImageSparseDrefGather;
1758             else
1759                 opCode = OpImageDrefGather;
1760         else
1761             if (sparse)
1762                 opCode = OpImageSparseGather;
1763             else
1764                 opCode = OpImageGather;
1765     } else if (explicitLod) {
1766         if (parameters.Dref) {
1767             if (proj)
1768                 if (sparse)
1769                     opCode = OpImageSparseSampleProjDrefExplicitLod;
1770                 else
1771                     opCode = OpImageSampleProjDrefExplicitLod;
1772             else
1773                 if (sparse)
1774                     opCode = OpImageSparseSampleDrefExplicitLod;
1775                 else
1776                     opCode = OpImageSampleDrefExplicitLod;
1777         } else {
1778             if (proj)
1779                 if (sparse)
1780                     opCode = OpImageSparseSampleProjExplicitLod;
1781                 else
1782                     opCode = OpImageSampleProjExplicitLod;
1783             else
1784                 if (sparse)
1785                     opCode = OpImageSparseSampleExplicitLod;
1786                 else
1787                     opCode = OpImageSampleExplicitLod;
1788         }
1789     } else {
1790         if (parameters.Dref) {
1791             if (proj)
1792                 if (sparse)
1793                     opCode = OpImageSparseSampleProjDrefImplicitLod;
1794                 else
1795                     opCode = OpImageSampleProjDrefImplicitLod;
1796             else
1797                 if (sparse)
1798                     opCode = OpImageSparseSampleDrefImplicitLod;
1799                 else
1800                     opCode = OpImageSampleDrefImplicitLod;
1801         } else {
1802             if (proj)
1803                 if (sparse)
1804                     opCode = OpImageSparseSampleProjImplicitLod;
1805                 else
1806                     opCode = OpImageSampleProjImplicitLod;
1807             else
1808                 if (sparse)
1809                     opCode = OpImageSparseSampleImplicitLod;
1810                 else
1811                     opCode = OpImageSampleImplicitLod;
1812         }
1813     }
1814
1815     // See if the result type is expecting a smeared result.
1816     // This happens when a legacy shadow*() call is made, which
1817     // gets a vec4 back instead of a float.
1818     Id smearedType = resultType;
1819     if (! isScalarType(resultType)) {
1820         switch (opCode) {
1821         case OpImageSampleDrefImplicitLod:
1822         case OpImageSampleDrefExplicitLod:
1823         case OpImageSampleProjDrefImplicitLod:
1824         case OpImageSampleProjDrefExplicitLod:
1825             resultType = getScalarTypeId(resultType);
1826             break;
1827         default:
1828             break;
1829         }
1830     }
1831
1832     Id typeId0 = 0;
1833     Id typeId1 = 0;
1834
1835     if (sparse) {
1836         typeId0 = resultType;
1837         typeId1 = getDerefTypeId(parameters.texelOut);
1838         resultType = makeStructResultType(typeId0, typeId1);
1839     }
1840
1841     // Build the SPIR-V instruction
1842     Instruction* textureInst = new Instruction(getUniqueId(), resultType, opCode);
1843     for (int op = 0; op < optArgNum; ++op)
1844         textureInst->addIdOperand(texArgs[op]);
1845     if (optArgNum < numArgs)
1846         textureInst->addImmediateOperand(texArgs[optArgNum]);
1847     for (int op = optArgNum + 1; op < numArgs; ++op)
1848         textureInst->addIdOperand(texArgs[op]);
1849     setPrecision(textureInst->getResultId(), precision);
1850     buildPoint->addInstruction(std::unique_ptr<Instruction>(textureInst));
1851
1852     Id resultId = textureInst->getResultId();
1853
1854     if (sparse) {
1855         // set capability
1856         addCapability(CapabilitySparseResidency);
1857
1858         // Decode the return type that was a special structure
1859         createStore(createCompositeExtract(resultId, typeId1, 1), parameters.texelOut);
1860         resultId = createCompositeExtract(resultId, typeId0, 0);
1861         setPrecision(resultId, precision);
1862     } else {
1863         // When a smear is needed, do it, as per what was computed
1864         // above when resultType was changed to a scalar type.
1865         if (resultType != smearedType)
1866             resultId = smearScalar(precision, resultId, smearedType);
1867     }
1868
1869     return resultId;
1870 }
1871
1872 // Comments in header
1873 Id Builder::createTextureQueryCall(Op opCode, const TextureParameters& parameters, bool isUnsignedResult)
1874 {
1875     // Figure out the result type
1876     Id resultType = 0;
1877     switch (opCode) {
1878     case OpImageQuerySize:
1879     case OpImageQuerySizeLod:
1880     {
1881         int numComponents = 0;
1882         switch (getTypeDimensionality(getImageType(parameters.sampler))) {
1883         case Dim1D:
1884         case DimBuffer:
1885             numComponents = 1;
1886             break;
1887         case Dim2D:
1888         case DimCube:
1889         case DimRect:
1890         case DimSubpassData:
1891             numComponents = 2;
1892             break;
1893         case Dim3D:
1894             numComponents = 3;
1895             break;
1896
1897         default:
1898             assert(0);
1899             break;
1900         }
1901         if (isArrayedImageType(getImageType(parameters.sampler)))
1902             ++numComponents;
1903
1904         Id intType = isUnsignedResult ? makeUintType(32) : makeIntType(32);
1905         if (numComponents == 1)
1906             resultType = intType;
1907         else
1908             resultType = makeVectorType(intType, numComponents);
1909
1910         break;
1911     }
1912     case OpImageQueryLod:
1913 #ifdef AMD_EXTENSIONS
1914         resultType = makeVectorType(getScalarTypeId(getTypeId(parameters.coords)), 2);
1915 #else
1916         resultType = makeVectorType(makeFloatType(32), 2);
1917 #endif
1918         break;
1919     case OpImageQueryLevels:
1920     case OpImageQuerySamples:
1921         resultType = isUnsignedResult ? makeUintType(32) : makeIntType(32);
1922         break;
1923     default:
1924         assert(0);
1925         break;
1926     }
1927
1928     Instruction* query = new Instruction(getUniqueId(), resultType, opCode);
1929     query->addIdOperand(parameters.sampler);
1930     if (parameters.coords)
1931         query->addIdOperand(parameters.coords);
1932     if (parameters.lod)
1933         query->addIdOperand(parameters.lod);
1934     buildPoint->addInstruction(std::unique_ptr<Instruction>(query));
1935
1936     return query->getResultId();
1937 }
1938
1939 // External comments in header.
1940 // Operates recursively to visit the composite's hierarchy.
1941 Id Builder::createCompositeCompare(Decoration precision, Id value1, Id value2, bool equal)
1942 {
1943     Id boolType = makeBoolType();
1944     Id valueType = getTypeId(value1);
1945
1946     Id resultId = NoResult;
1947
1948     int numConstituents = getNumTypeConstituents(valueType);
1949
1950     // Scalars and Vectors
1951
1952     if (isScalarType(valueType) || isVectorType(valueType)) {
1953         assert(valueType == getTypeId(value2));
1954         // These just need a single comparison, just have
1955         // to figure out what it is.
1956         Op op;
1957         switch (getMostBasicTypeClass(valueType)) {
1958         case OpTypeFloat:
1959             op = equal ? OpFOrdEqual : OpFOrdNotEqual;
1960             break;
1961         case OpTypeInt:
1962         default:
1963             op = equal ? OpIEqual : OpINotEqual;
1964             break;
1965         case OpTypeBool:
1966             op = equal ? OpLogicalEqual : OpLogicalNotEqual;
1967             precision = NoPrecision;
1968             break;
1969         }
1970
1971         if (isScalarType(valueType)) {
1972             // scalar
1973             resultId = createBinOp(op, boolType, value1, value2);
1974         } else {
1975             // vector
1976             resultId = createBinOp(op, makeVectorType(boolType, numConstituents), value1, value2);
1977             setPrecision(resultId, precision);
1978             // reduce vector compares...
1979             resultId = createUnaryOp(equal ? OpAll : OpAny, boolType, resultId);
1980         }
1981
1982         return setPrecision(resultId, precision);
1983     }
1984
1985     // Only structs, arrays, and matrices should be left.
1986     // They share in common the reduction operation across their constituents.
1987     assert(isAggregateType(valueType) || isMatrixType(valueType));
1988
1989     // Compare each pair of constituents
1990     for (int constituent = 0; constituent < numConstituents; ++constituent) {
1991         std::vector<unsigned> indexes(1, constituent);
1992         Id constituentType1 = getContainedTypeId(getTypeId(value1), constituent);
1993         Id constituentType2 = getContainedTypeId(getTypeId(value2), constituent);
1994         Id constituent1 = createCompositeExtract(value1, constituentType1, indexes);
1995         Id constituent2 = createCompositeExtract(value2, constituentType2, indexes);
1996
1997         Id subResultId = createCompositeCompare(precision, constituent1, constituent2, equal);
1998
1999         if (constituent == 0)
2000             resultId = subResultId;
2001         else
2002             resultId = setPrecision(createBinOp(equal ? OpLogicalAnd : OpLogicalOr, boolType, resultId, subResultId), precision);
2003     }
2004
2005     return resultId;
2006 }
2007
2008 // OpCompositeConstruct
2009 Id Builder::createCompositeConstruct(Id typeId, const std::vector<Id>& constituents)
2010 {
2011     assert(isAggregateType(typeId) || (getNumTypeConstituents(typeId) > 1 && getNumTypeConstituents(typeId) == (int)constituents.size()));
2012
2013     if (generatingOpCodeForSpecConst) {
2014         // Sometime, even in spec-constant-op mode, the constant composite to be
2015         // constructed may not be a specialization constant.
2016         // e.g.:
2017         //  const mat2 m2 = mat2(a_spec_const, a_front_end_const, another_front_end_const, third_front_end_const);
2018         // The first column vector should be a spec constant one, as a_spec_const is a spec constant.
2019         // The second column vector should NOT be spec constant, as it does not contain any spec constants.
2020         // To handle such cases, we check the constituents of the constant vector to determine whether this
2021         // vector should be created as a spec constant.
2022         return makeCompositeConstant(typeId, constituents,
2023                                      std::any_of(constituents.begin(), constituents.end(),
2024                                                  [&](spv::Id id) { return isSpecConstant(id); }));
2025     }
2026
2027     Instruction* op = new Instruction(getUniqueId(), typeId, OpCompositeConstruct);
2028     for (int c = 0; c < (int)constituents.size(); ++c)
2029         op->addIdOperand(constituents[c]);
2030     buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
2031
2032     return op->getResultId();
2033 }
2034
2035 // Vector or scalar constructor
2036 Id Builder::createConstructor(Decoration precision, const std::vector<Id>& sources, Id resultTypeId)
2037 {
2038     Id result = NoResult;
2039     unsigned int numTargetComponents = getNumTypeComponents(resultTypeId);
2040     unsigned int targetComponent = 0;
2041
2042     // Special case: when calling a vector constructor with a single scalar
2043     // argument, smear the scalar
2044     if (sources.size() == 1 && isScalar(sources[0]) && numTargetComponents > 1)
2045         return smearScalar(precision, sources[0], resultTypeId);
2046
2047     // accumulate the arguments for OpCompositeConstruct
2048     std::vector<Id> constituents;
2049     Id scalarTypeId = getScalarTypeId(resultTypeId);
2050
2051     // lambda to store the result of visiting an argument component
2052     const auto latchResult = [&](Id comp) {
2053         if (numTargetComponents > 1)
2054             constituents.push_back(comp);
2055         else
2056             result = comp;
2057         ++targetComponent;
2058     };
2059
2060     // lambda to visit a vector argument's components
2061     const auto accumulateVectorConstituents = [&](Id sourceArg) {
2062         unsigned int sourceSize = getNumComponents(sourceArg);
2063         unsigned int sourcesToUse = sourceSize;
2064         if (sourcesToUse + targetComponent > numTargetComponents)
2065             sourcesToUse = numTargetComponents - targetComponent;
2066
2067         for (unsigned int s = 0; s < sourcesToUse; ++s) {
2068             std::vector<unsigned> swiz;
2069             swiz.push_back(s);
2070             latchResult(createRvalueSwizzle(precision, scalarTypeId, sourceArg, swiz));
2071         }
2072     };
2073
2074     // lambda to visit a matrix argument's components
2075     const auto accumulateMatrixConstituents = [&](Id sourceArg) {
2076         unsigned int sourceSize = getNumColumns(sourceArg) * getNumRows(sourceArg);
2077         unsigned int sourcesToUse = sourceSize;
2078         if (sourcesToUse + targetComponent > numTargetComponents)
2079             sourcesToUse = numTargetComponents - targetComponent;
2080
2081         int col = 0;
2082         int row = 0;
2083         for (unsigned int s = 0; s < sourcesToUse; ++s) {
2084             if (row >= getNumRows(sourceArg)) {
2085                 row = 0;
2086                 col++;
2087             }
2088             std::vector<Id> indexes;
2089             indexes.push_back(col);
2090             indexes.push_back(row);
2091             latchResult(createCompositeExtract(sourceArg, scalarTypeId, indexes));
2092             row++;
2093         }
2094     };
2095
2096     // Go through the source arguments, each one could have either
2097     // a single or multiple components to contribute.
2098     for (unsigned int i = 0; i < sources.size(); ++i) {
2099         if (isScalar(sources[i]))
2100             latchResult(sources[i]);
2101         else if (isVector(sources[i]))
2102             accumulateVectorConstituents(sources[i]);
2103         else if (isMatrix(sources[i]))
2104             accumulateMatrixConstituents(sources[i]);
2105         else
2106             assert(0);
2107
2108         if (targetComponent >= numTargetComponents)
2109             break;
2110     }
2111
2112     // If the result is a vector, make it from the gathered constituents.
2113     if (constituents.size() > 0)
2114         result = createCompositeConstruct(resultTypeId, constituents);
2115
2116     return setPrecision(result, precision);
2117 }
2118
2119 // Comments in header
2120 Id Builder::createMatrixConstructor(Decoration precision, const std::vector<Id>& sources, Id resultTypeId)
2121 {
2122     Id componentTypeId = getScalarTypeId(resultTypeId);
2123     int numCols = getTypeNumColumns(resultTypeId);
2124     int numRows = getTypeNumRows(resultTypeId);
2125
2126     Instruction* instr = module.getInstruction(componentTypeId);
2127     unsigned bitCount = instr->getImmediateOperand(0);
2128
2129     // Optimize matrix constructed from a bigger matrix
2130     if (isMatrix(sources[0]) && getNumColumns(sources[0]) >= numCols && getNumRows(sources[0]) >= numRows) {
2131         // To truncate the matrix to a smaller number of rows/columns, we need to:
2132         // 1. For each column, extract the column and truncate it to the required size using shuffle
2133         // 2. Assemble the resulting matrix from all columns
2134         Id matrix = sources[0];
2135         Id columnTypeId = getContainedTypeId(resultTypeId);
2136         Id sourceColumnTypeId = getContainedTypeId(getTypeId(matrix));
2137
2138         std::vector<unsigned> channels;
2139         for (int row = 0; row < numRows; ++row)
2140             channels.push_back(row);
2141
2142         std::vector<Id> matrixColumns;
2143         for (int col = 0; col < numCols; ++col) {
2144             std::vector<unsigned> indexes;
2145             indexes.push_back(col);
2146             Id colv = createCompositeExtract(matrix, sourceColumnTypeId, indexes);
2147             setPrecision(colv, precision);
2148
2149             if (numRows != getNumRows(matrix)) {
2150                 matrixColumns.push_back(createRvalueSwizzle(precision, columnTypeId, colv, channels));
2151             } else {
2152                 matrixColumns.push_back(colv);
2153             }
2154         }
2155
2156         return setPrecision(createCompositeConstruct(resultTypeId, matrixColumns), precision);
2157     }
2158
2159     // Otherwise, will use a two step process
2160     // 1. make a compile-time 2D array of values
2161     // 2. construct a matrix from that array
2162
2163     // Step 1.
2164
2165     // initialize the array to the identity matrix
2166     Id ids[maxMatrixSize][maxMatrixSize];
2167     Id  one = (bitCount == 64 ? makeDoubleConstant(1.0) : makeFloatConstant(1.0));
2168     Id zero = (bitCount == 64 ? makeDoubleConstant(0.0) : makeFloatConstant(0.0));
2169     for (int col = 0; col < 4; ++col) {
2170         for (int row = 0; row < 4; ++row) {
2171             if (col == row)
2172                 ids[col][row] = one;
2173             else
2174                 ids[col][row] = zero;
2175         }
2176     }
2177
2178     // modify components as dictated by the arguments
2179     if (sources.size() == 1 && isScalar(sources[0])) {
2180         // a single scalar; resets the diagonals
2181         for (int col = 0; col < 4; ++col)
2182             ids[col][col] = sources[0];
2183     } else if (isMatrix(sources[0])) {
2184         // constructing from another matrix; copy over the parts that exist in both the argument and constructee
2185         Id matrix = sources[0];
2186         int minCols = std::min(numCols, getNumColumns(matrix));
2187         int minRows = std::min(numRows, getNumRows(matrix));
2188         for (int col = 0; col < minCols; ++col) {
2189             std::vector<unsigned> indexes;
2190             indexes.push_back(col);
2191             for (int row = 0; row < minRows; ++row) {
2192                 indexes.push_back(row);
2193                 ids[col][row] = createCompositeExtract(matrix, componentTypeId, indexes);
2194                 indexes.pop_back();
2195                 setPrecision(ids[col][row], precision);
2196             }
2197         }
2198     } else {
2199         // fill in the matrix in column-major order with whatever argument components are available
2200         int row = 0;
2201         int col = 0;
2202
2203         for (int arg = 0; arg < (int)sources.size(); ++arg) {
2204             Id argComp = sources[arg];
2205             for (int comp = 0; comp < getNumComponents(sources[arg]); ++comp) {
2206                 if (getNumComponents(sources[arg]) > 1) {
2207                     argComp = createCompositeExtract(sources[arg], componentTypeId, comp);
2208                     setPrecision(argComp, precision);
2209                 }
2210                 ids[col][row++] = argComp;
2211                 if (row == numRows) {
2212                     row = 0;
2213                     col++;
2214                 }
2215             }
2216         }
2217     }
2218
2219     // Step 2:  Construct a matrix from that array.
2220     // First make the column vectors, then make the matrix.
2221
2222     // make the column vectors
2223     Id columnTypeId = getContainedTypeId(resultTypeId);
2224     std::vector<Id> matrixColumns;
2225     for (int col = 0; col < numCols; ++col) {
2226         std::vector<Id> vectorComponents;
2227         for (int row = 0; row < numRows; ++row)
2228             vectorComponents.push_back(ids[col][row]);
2229         Id column = createCompositeConstruct(columnTypeId, vectorComponents);
2230         setPrecision(column, precision);
2231         matrixColumns.push_back(column);
2232     }
2233
2234     // make the matrix
2235     return setPrecision(createCompositeConstruct(resultTypeId, matrixColumns), precision);
2236 }
2237
2238 // Comments in header
2239 Builder::If::If(Id cond, unsigned int ctrl, Builder& gb) :
2240     builder(gb),
2241     condition(cond),
2242     control(ctrl),
2243     elseBlock(0)
2244 {
2245     function = &builder.getBuildPoint()->getParent();
2246
2247     // make the blocks, but only put the then-block into the function,
2248     // the else-block and merge-block will be added later, in order, after
2249     // earlier code is emitted
2250     thenBlock = new Block(builder.getUniqueId(), *function);
2251     mergeBlock = new Block(builder.getUniqueId(), *function);
2252
2253     // Save the current block, so that we can add in the flow control split when
2254     // makeEndIf is called.
2255     headerBlock = builder.getBuildPoint();
2256
2257     function->addBlock(thenBlock);
2258     builder.setBuildPoint(thenBlock);
2259 }
2260
2261 // Comments in header
2262 void Builder::If::makeBeginElse()
2263 {
2264     // Close out the "then" by having it jump to the mergeBlock
2265     builder.createBranch(mergeBlock);
2266
2267     // Make the first else block and add it to the function
2268     elseBlock = new Block(builder.getUniqueId(), *function);
2269     function->addBlock(elseBlock);
2270
2271     // Start building the else block
2272     builder.setBuildPoint(elseBlock);
2273 }
2274
2275 // Comments in header
2276 void Builder::If::makeEndIf()
2277 {
2278     // jump to the merge block
2279     builder.createBranch(mergeBlock);
2280
2281     // Go back to the headerBlock and make the flow control split
2282     builder.setBuildPoint(headerBlock);
2283     builder.createSelectionMerge(mergeBlock, control);
2284     if (elseBlock)
2285         builder.createConditionalBranch(condition, thenBlock, elseBlock);
2286     else
2287         builder.createConditionalBranch(condition, thenBlock, mergeBlock);
2288
2289     // add the merge block to the function
2290     function->addBlock(mergeBlock);
2291     builder.setBuildPoint(mergeBlock);
2292 }
2293
2294 // Comments in header
2295 void Builder::makeSwitch(Id selector, unsigned int control, int numSegments, const std::vector<int>& caseValues,
2296                          const std::vector<int>& valueIndexToSegment, int defaultSegment,
2297                          std::vector<Block*>& segmentBlocks)
2298 {
2299     Function& function = buildPoint->getParent();
2300
2301     // make all the blocks
2302     for (int s = 0; s < numSegments; ++s)
2303         segmentBlocks.push_back(new Block(getUniqueId(), function));
2304
2305     Block* mergeBlock = new Block(getUniqueId(), function);
2306
2307     // make and insert the switch's selection-merge instruction
2308     createSelectionMerge(mergeBlock, control);
2309
2310     // make the switch instruction
2311     Instruction* switchInst = new Instruction(NoResult, NoType, OpSwitch);
2312     switchInst->addIdOperand(selector);
2313     auto defaultOrMerge = (defaultSegment >= 0) ? segmentBlocks[defaultSegment] : mergeBlock;
2314     switchInst->addIdOperand(defaultOrMerge->getId());
2315     defaultOrMerge->addPredecessor(buildPoint);
2316     for (int i = 0; i < (int)caseValues.size(); ++i) {
2317         switchInst->addImmediateOperand(caseValues[i]);
2318         switchInst->addIdOperand(segmentBlocks[valueIndexToSegment[i]]->getId());
2319         segmentBlocks[valueIndexToSegment[i]]->addPredecessor(buildPoint);
2320     }
2321     buildPoint->addInstruction(std::unique_ptr<Instruction>(switchInst));
2322
2323     // push the merge block
2324     switchMerges.push(mergeBlock);
2325 }
2326
2327 // Comments in header
2328 void Builder::addSwitchBreak()
2329 {
2330     // branch to the top of the merge block stack
2331     createBranch(switchMerges.top());
2332     createAndSetNoPredecessorBlock("post-switch-break");
2333 }
2334
2335 // Comments in header
2336 void Builder::nextSwitchSegment(std::vector<Block*>& segmentBlock, int nextSegment)
2337 {
2338     int lastSegment = nextSegment - 1;
2339     if (lastSegment >= 0) {
2340         // Close out previous segment by jumping, if necessary, to next segment
2341         if (! buildPoint->isTerminated())
2342             createBranch(segmentBlock[nextSegment]);
2343     }
2344     Block* block = segmentBlock[nextSegment];
2345     block->getParent().addBlock(block);
2346     setBuildPoint(block);
2347 }
2348
2349 // Comments in header
2350 void Builder::endSwitch(std::vector<Block*>& /*segmentBlock*/)
2351 {
2352     // Close out previous segment by jumping, if necessary, to next segment
2353     if (! buildPoint->isTerminated())
2354         addSwitchBreak();
2355
2356     switchMerges.top()->getParent().addBlock(switchMerges.top());
2357     setBuildPoint(switchMerges.top());
2358
2359     switchMerges.pop();
2360 }
2361
2362 Block& Builder::makeNewBlock()
2363 {
2364     Function& function = buildPoint->getParent();
2365     auto block = new Block(getUniqueId(), function);
2366     function.addBlock(block);
2367     return *block;
2368 }
2369
2370 Builder::LoopBlocks& Builder::makeNewLoop()
2371 {
2372     // This verbosity is needed to simultaneously get the same behavior
2373     // everywhere (id's in the same order), have a syntax that works
2374     // across lots of versions of C++, have no warnings from pedantic
2375     // compilation modes, and leave the rest of the code alone.
2376     Block& head            = makeNewBlock();
2377     Block& body            = makeNewBlock();
2378     Block& merge           = makeNewBlock();
2379     Block& continue_target = makeNewBlock();
2380     LoopBlocks blocks(head, body, merge, continue_target);
2381     loops.push(blocks);
2382     return loops.top();
2383 }
2384
2385 void Builder::createLoopContinue()
2386 {
2387     createBranch(&loops.top().continue_target);
2388     // Set up a block for dead code.
2389     createAndSetNoPredecessorBlock("post-loop-continue");
2390 }
2391
2392 void Builder::createLoopExit()
2393 {
2394     createBranch(&loops.top().merge);
2395     // Set up a block for dead code.
2396     createAndSetNoPredecessorBlock("post-loop-break");
2397 }
2398
2399 void Builder::closeLoop()
2400 {
2401     loops.pop();
2402 }
2403
2404 void Builder::clearAccessChain()
2405 {
2406     accessChain.base = NoResult;
2407     accessChain.indexChain.clear();
2408     accessChain.instr = NoResult;
2409     accessChain.swizzle.clear();
2410     accessChain.component = NoResult;
2411     accessChain.preSwizzleBaseType = NoType;
2412     accessChain.isRValue = false;
2413     accessChain.coherentFlags.clear();
2414 }
2415
2416 // Comments in header
2417 void Builder::accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizzleBaseType)
2418 {
2419     // swizzles can be stacked in GLSL, but simplified to a single
2420     // one here; the base type doesn't change
2421     if (accessChain.preSwizzleBaseType == NoType)
2422         accessChain.preSwizzleBaseType = preSwizzleBaseType;
2423
2424     // if needed, propagate the swizzle for the current access chain
2425     if (accessChain.swizzle.size() > 0) {
2426         std::vector<unsigned> oldSwizzle = accessChain.swizzle;
2427         accessChain.swizzle.resize(0);
2428         for (unsigned int i = 0; i < swizzle.size(); ++i) {
2429             assert(swizzle[i] < oldSwizzle.size());
2430             accessChain.swizzle.push_back(oldSwizzle[swizzle[i]]);
2431         }
2432     } else
2433         accessChain.swizzle = swizzle;
2434
2435     // determine if we need to track this swizzle anymore
2436     simplifyAccessChainSwizzle();
2437 }
2438
2439 // Comments in header
2440 void Builder::accessChainStore(Id rvalue, spv::MemoryAccessMask memoryAccess, spv::Scope scope)
2441 {
2442     assert(accessChain.isRValue == false);
2443
2444     transferAccessChainSwizzle(true);
2445     Id base = collapseAccessChain();
2446     Id source = rvalue;
2447
2448     // dynamic component should be gone
2449     assert(accessChain.component == NoResult);
2450
2451     // If swizzle still exists, it is out-of-order or not full, we must load the target vector,
2452     // extract and insert elements to perform writeMask and/or swizzle.
2453     if (accessChain.swizzle.size() > 0) {
2454         Id tempBaseId = createLoad(base);
2455         source = createLvalueSwizzle(getTypeId(tempBaseId), tempBaseId, source, accessChain.swizzle);
2456     }
2457
2458     createStore(source, base, memoryAccess, scope);
2459 }
2460
2461 // Comments in header
2462 Id Builder::accessChainLoad(Decoration precision, Decoration nonUniform, Id resultType, spv::MemoryAccessMask memoryAccess, spv::Scope scope)
2463 {
2464     Id id;
2465
2466     if (accessChain.isRValue) {
2467         // transfer access chain, but try to stay in registers
2468         transferAccessChainSwizzle(false);
2469         if (accessChain.indexChain.size() > 0) {
2470             Id swizzleBase = accessChain.preSwizzleBaseType != NoType ? accessChain.preSwizzleBaseType : resultType;
2471
2472             // if all the accesses are constants, we can use OpCompositeExtract
2473             std::vector<unsigned> indexes;
2474             bool constant = true;
2475             for (int i = 0; i < (int)accessChain.indexChain.size(); ++i) {
2476                 if (isConstantScalar(accessChain.indexChain[i]))
2477                     indexes.push_back(getConstantScalar(accessChain.indexChain[i]));
2478                 else {
2479                     constant = false;
2480                     break;
2481                 }
2482             }
2483
2484             if (constant)
2485                 id = createCompositeExtract(accessChain.base, swizzleBase, indexes);
2486             else {
2487                 // make a new function variable for this r-value
2488                 Id lValue = createVariable(StorageClassFunction, getTypeId(accessChain.base), "indexable");
2489
2490                 // store into it
2491                 createStore(accessChain.base, lValue);
2492
2493                 // move base to the new variable
2494                 accessChain.base = lValue;
2495                 accessChain.isRValue = false;
2496
2497                 // load through the access chain
2498                 id = createLoad(collapseAccessChain());
2499             }
2500             setPrecision(id, precision);
2501         } else
2502             id = accessChain.base;  // no precision, it was set when this was defined
2503     } else {
2504         transferAccessChainSwizzle(true);
2505         // load through the access chain
2506         id = createLoad(collapseAccessChain(), memoryAccess, scope);
2507         setPrecision(id, precision);
2508         addDecoration(id, nonUniform);
2509     }
2510
2511     // Done, unless there are swizzles to do
2512     if (accessChain.swizzle.size() == 0 && accessChain.component == NoResult)
2513         return id;
2514
2515     // Do remaining swizzling
2516
2517     // Do the basic swizzle
2518     if (accessChain.swizzle.size() > 0) {
2519         Id swizzledType = getScalarTypeId(getTypeId(id));
2520         if (accessChain.swizzle.size() > 1)
2521             swizzledType = makeVectorType(swizzledType, (int)accessChain.swizzle.size());
2522         id = createRvalueSwizzle(precision, swizzledType, id, accessChain.swizzle);
2523     }
2524
2525     // Do the dynamic component
2526     if (accessChain.component != NoResult)
2527         id = setPrecision(createVectorExtractDynamic(id, resultType, accessChain.component), precision);
2528
2529     addDecoration(id, nonUniform);
2530     return id;
2531 }
2532
2533 Id Builder::accessChainGetLValue()
2534 {
2535     assert(accessChain.isRValue == false);
2536
2537     transferAccessChainSwizzle(true);
2538     Id lvalue = collapseAccessChain();
2539
2540     // If swizzle exists, it is out-of-order or not full, we must load the target vector,
2541     // extract and insert elements to perform writeMask and/or swizzle.  This does not
2542     // go with getting a direct l-value pointer.
2543     assert(accessChain.swizzle.size() == 0);
2544     assert(accessChain.component == NoResult);
2545
2546     return lvalue;
2547 }
2548
2549 // comment in header
2550 Id Builder::accessChainGetInferredType()
2551 {
2552     // anything to operate on?
2553     if (accessChain.base == NoResult)
2554         return NoType;
2555     Id type = getTypeId(accessChain.base);
2556
2557     // do initial dereference
2558     if (! accessChain.isRValue)
2559         type = getContainedTypeId(type);
2560
2561     // dereference each index
2562     for (auto it = accessChain.indexChain.cbegin(); it != accessChain.indexChain.cend(); ++it) {
2563         if (isStructType(type))
2564             type = getContainedTypeId(type, getConstantScalar(*it));
2565         else
2566             type = getContainedTypeId(type);
2567     }
2568
2569     // dereference swizzle
2570     if (accessChain.swizzle.size() == 1)
2571         type = getContainedTypeId(type);
2572     else if (accessChain.swizzle.size() > 1)
2573         type = makeVectorType(getContainedTypeId(type), (int)accessChain.swizzle.size());
2574
2575     // dereference component selection
2576     if (accessChain.component)
2577         type = getContainedTypeId(type);
2578
2579     return type;
2580 }
2581
2582 void Builder::dump(std::vector<unsigned int>& out) const
2583 {
2584     // Header, before first instructions:
2585     out.push_back(MagicNumber);
2586     out.push_back(spvVersion);
2587     out.push_back(builderNumber);
2588     out.push_back(uniqueId + 1);
2589     out.push_back(0);
2590
2591     // Capabilities
2592     for (auto it = capabilities.cbegin(); it != capabilities.cend(); ++it) {
2593         Instruction capInst(0, 0, OpCapability);
2594         capInst.addImmediateOperand(*it);
2595         capInst.dump(out);
2596     }
2597
2598     for (auto it = extensions.cbegin(); it != extensions.cend(); ++it) {
2599         Instruction extInst(0, 0, OpExtension);
2600         extInst.addStringOperand(it->c_str());
2601         extInst.dump(out);
2602     }
2603
2604     dumpInstructions(out, imports);
2605     Instruction memInst(0, 0, OpMemoryModel);
2606     memInst.addImmediateOperand(addressModel);
2607     memInst.addImmediateOperand(memoryModel);
2608     memInst.dump(out);
2609
2610     // Instructions saved up while building:
2611     dumpInstructions(out, entryPoints);
2612     dumpInstructions(out, executionModes);
2613
2614     // Debug instructions
2615     dumpInstructions(out, strings);
2616     dumpSourceInstructions(out);
2617     for (int e = 0; e < (int)sourceExtensions.size(); ++e) {
2618         Instruction sourceExtInst(0, 0, OpSourceExtension);
2619         sourceExtInst.addStringOperand(sourceExtensions[e]);
2620         sourceExtInst.dump(out);
2621     }
2622     dumpInstructions(out, names);
2623     dumpModuleProcesses(out);
2624
2625     // Annotation instructions
2626     dumpInstructions(out, decorations);
2627
2628     dumpInstructions(out, constantsTypesGlobals);
2629     dumpInstructions(out, externals);
2630
2631     // The functions
2632     module.dump(out);
2633 }
2634
2635 //
2636 // Protected methods.
2637 //
2638
2639 // Turn the described access chain in 'accessChain' into an instruction(s)
2640 // computing its address.  This *cannot* include complex swizzles, which must
2641 // be handled after this is called.
2642 //
2643 // Can generate code.
2644 Id Builder::collapseAccessChain()
2645 {
2646     assert(accessChain.isRValue == false);
2647
2648     // did we already emit an access chain for this?
2649     if (accessChain.instr != NoResult)
2650         return accessChain.instr;
2651
2652     // If we have a dynamic component, we can still transfer
2653     // that into a final operand to the access chain.  We need to remap the
2654     // dynamic component through the swizzle to get a new dynamic component to
2655     // update.
2656     //
2657     // This was not done in transferAccessChainSwizzle() because it might
2658     // generate code.
2659     remapDynamicSwizzle();
2660     if (accessChain.component != NoResult) {
2661         // transfer the dynamic component to the access chain
2662         accessChain.indexChain.push_back(accessChain.component);
2663         accessChain.component = NoResult;
2664     }
2665
2666     // note that non-trivial swizzling is left pending
2667
2668     // do we have an access chain?
2669     if (accessChain.indexChain.size() == 0)
2670         return accessChain.base;
2671
2672     // emit the access chain
2673     StorageClass storageClass = (StorageClass)module.getStorageClass(getTypeId(accessChain.base));
2674     accessChain.instr = createAccessChain(storageClass, accessChain.base, accessChain.indexChain);
2675
2676     return accessChain.instr;
2677 }
2678
2679 // For a dynamic component selection of a swizzle.
2680 //
2681 // Turn the swizzle and dynamic component into just a dynamic component.
2682 //
2683 // Generates code.
2684 void Builder::remapDynamicSwizzle()
2685 {
2686     // do we have a swizzle to remap a dynamic component through?
2687     if (accessChain.component != NoResult && accessChain.swizzle.size() > 1) {
2688         // build a vector of the swizzle for the component to map into
2689         std::vector<Id> components;
2690         for (int c = 0; c < (int)accessChain.swizzle.size(); ++c)
2691             components.push_back(makeUintConstant(accessChain.swizzle[c]));
2692         Id mapType = makeVectorType(makeUintType(32), (int)accessChain.swizzle.size());
2693         Id map = makeCompositeConstant(mapType, components);
2694
2695         // use it
2696         accessChain.component = createVectorExtractDynamic(map, makeUintType(32), accessChain.component);
2697         accessChain.swizzle.clear();
2698     }
2699 }
2700
2701 // clear out swizzle if it is redundant, that is reselecting the same components
2702 // that would be present without the swizzle.
2703 void Builder::simplifyAccessChainSwizzle()
2704 {
2705     // If the swizzle has fewer components than the vector, it is subsetting, and must stay
2706     // to preserve that fact.
2707     if (getNumTypeComponents(accessChain.preSwizzleBaseType) > (int)accessChain.swizzle.size())
2708         return;
2709
2710     // if components are out of order, it is a swizzle
2711     for (unsigned int i = 0; i < accessChain.swizzle.size(); ++i) {
2712         if (i != accessChain.swizzle[i])
2713             return;
2714     }
2715
2716     // otherwise, there is no need to track this swizzle
2717     accessChain.swizzle.clear();
2718     if (accessChain.component == NoResult)
2719         accessChain.preSwizzleBaseType = NoType;
2720 }
2721
2722 // To the extent any swizzling can become part of the chain
2723 // of accesses instead of a post operation, make it so.
2724 // If 'dynamic' is true, include transferring the dynamic component,
2725 // otherwise, leave it pending.
2726 //
2727 // Does not generate code. just updates the access chain.
2728 void Builder::transferAccessChainSwizzle(bool dynamic)
2729 {
2730     // non existent?
2731     if (accessChain.swizzle.size() == 0 && accessChain.component == NoResult)
2732         return;
2733
2734     // too complex?
2735     // (this requires either a swizzle, or generating code for a dynamic component)
2736     if (accessChain.swizzle.size() > 1)
2737         return;
2738
2739     // single component, either in the swizzle and/or dynamic component
2740     if (accessChain.swizzle.size() == 1) {
2741         assert(accessChain.component == NoResult);
2742         // handle static component selection
2743         accessChain.indexChain.push_back(makeUintConstant(accessChain.swizzle.front()));
2744         accessChain.swizzle.clear();
2745         accessChain.preSwizzleBaseType = NoType;
2746     } else if (dynamic && accessChain.component != NoResult) {
2747         assert(accessChain.swizzle.size() == 0);
2748         // handle dynamic component
2749         accessChain.indexChain.push_back(accessChain.component);
2750         accessChain.preSwizzleBaseType = NoType;
2751         accessChain.component = NoResult;
2752     }
2753 }
2754
2755 // Utility method for creating a new block and setting the insert point to
2756 // be in it. This is useful for flow-control operations that need a "dummy"
2757 // block proceeding them (e.g. instructions after a discard, etc).
2758 void Builder::createAndSetNoPredecessorBlock(const char* /*name*/)
2759 {
2760     Block* block = new Block(getUniqueId(), buildPoint->getParent());
2761     block->setUnreachable();
2762     buildPoint->getParent().addBlock(block);
2763     setBuildPoint(block);
2764
2765     // if (name)
2766     //    addName(block->getId(), name);
2767 }
2768
2769 // Comments in header
2770 void Builder::createBranch(Block* block)
2771 {
2772     Instruction* branch = new Instruction(OpBranch);
2773     branch->addIdOperand(block->getId());
2774     buildPoint->addInstruction(std::unique_ptr<Instruction>(branch));
2775     block->addPredecessor(buildPoint);
2776 }
2777
2778 void Builder::createSelectionMerge(Block* mergeBlock, unsigned int control)
2779 {
2780     Instruction* merge = new Instruction(OpSelectionMerge);
2781     merge->addIdOperand(mergeBlock->getId());
2782     merge->addImmediateOperand(control);
2783     buildPoint->addInstruction(std::unique_ptr<Instruction>(merge));
2784 }
2785
2786 void Builder::createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control,
2787                               unsigned int dependencyLength)
2788 {
2789     Instruction* merge = new Instruction(OpLoopMerge);
2790     merge->addIdOperand(mergeBlock->getId());
2791     merge->addIdOperand(continueBlock->getId());
2792     merge->addImmediateOperand(control);
2793     if ((control & LoopControlDependencyLengthMask) != 0)
2794         merge->addImmediateOperand(dependencyLength);
2795     buildPoint->addInstruction(std::unique_ptr<Instruction>(merge));
2796 }
2797
2798 void Builder::createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock)
2799 {
2800     Instruction* branch = new Instruction(OpBranchConditional);
2801     branch->addIdOperand(condition);
2802     branch->addIdOperand(thenBlock->getId());
2803     branch->addIdOperand(elseBlock->getId());
2804     buildPoint->addInstruction(std::unique_ptr<Instruction>(branch));
2805     thenBlock->addPredecessor(buildPoint);
2806     elseBlock->addPredecessor(buildPoint);
2807 }
2808
2809 // OpSource
2810 // [OpSourceContinued]
2811 // ...
2812 void Builder::dumpSourceInstructions(std::vector<unsigned int>& out) const
2813 {
2814     const int maxWordCount = 0xFFFF;
2815     const int opSourceWordCount = 4;
2816     const int nonNullBytesPerInstruction = 4 * (maxWordCount - opSourceWordCount) - 1;
2817
2818     if (source != SourceLanguageUnknown) {
2819         // OpSource Language Version File Source
2820         Instruction sourceInst(NoResult, NoType, OpSource);
2821         sourceInst.addImmediateOperand(source);
2822         sourceInst.addImmediateOperand(sourceVersion);
2823         // File operand
2824         if (sourceFileStringId != NoResult) {
2825             sourceInst.addIdOperand(sourceFileStringId);
2826             // Source operand
2827             if (sourceText.size() > 0) {
2828                 int nextByte = 0;
2829                 std::string subString;
2830                 while ((int)sourceText.size() - nextByte > 0) {
2831                     subString = sourceText.substr(nextByte, nonNullBytesPerInstruction);
2832                     if (nextByte == 0) {
2833                         // OpSource
2834                         sourceInst.addStringOperand(subString.c_str());
2835                         sourceInst.dump(out);
2836                     } else {
2837                         // OpSourcContinued
2838                         Instruction sourceContinuedInst(OpSourceContinued);
2839                         sourceContinuedInst.addStringOperand(subString.c_str());
2840                         sourceContinuedInst.dump(out);
2841                     }
2842                     nextByte += nonNullBytesPerInstruction;
2843                 }
2844             } else
2845                 sourceInst.dump(out);
2846         } else
2847             sourceInst.dump(out);
2848     }
2849 }
2850
2851 void Builder::dumpInstructions(std::vector<unsigned int>& out, const std::vector<std::unique_ptr<Instruction> >& instructions) const
2852 {
2853     for (int i = 0; i < (int)instructions.size(); ++i) {
2854         instructions[i]->dump(out);
2855     }
2856 }
2857
2858 void Builder::dumpModuleProcesses(std::vector<unsigned int>& out) const
2859 {
2860     for (int i = 0; i < (int)moduleProcesses.size(); ++i) {
2861         Instruction moduleProcessed(OpModuleProcessed);
2862         moduleProcessed.addStringOperand(moduleProcesses[i]);
2863         moduleProcessed.dump(out);
2864     }
2865 }
2866
2867 }; // end spv namespace