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