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