Merge pull request #133 from AWoloszyn/spirv-memory
[platform/upstream/glslang.git] / SPIRV / SpvBuilder.cpp
1 //
2 //Copyright (C) 2014 LunarG, Inc.
3 //
4 //All rights reserved.
5 //
6 //Redistribution and use in source and binary forms, with or without
7 //modification, are permitted provided that the following conditions
8 //are met:
9 //
10 //    Redistributions of source code must retain the above copyright
11 //    notice, this list of conditions and the following disclaimer.
12 //
13 //    Redistributions in binary form must reproduce the above
14 //    copyright notice, this list of conditions and the following
15 //    disclaimer in the documentation and/or other materials provided
16 //    with the distribution.
17 //
18 //    Neither the name of 3Dlabs Inc. Ltd. nor the names of its
19 //    contributors may be used to endorse or promote products derived
20 //    from this software without specific prior written permission.
21 //
22 //THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 //"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 //LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25 //FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26 //COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27 //INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28 //BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 //LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30 //CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 //LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32 //ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 //POSSIBILITY OF SUCH DAMAGE.
34
35 //
36 // Author: John Kessenich, LunarG
37 //
38
39 //
40 // Helper for making SPIR-V IR.  Generally, this is documented in the header
41 // SpvBuilder.h.
42 //
43
44 #include <assert.h>
45 #include <stdio.h>
46 #include <stdlib.h>
47
48 #include <unordered_set>
49
50 #include "SpvBuilder.h"
51
52 #ifndef _WIN32
53     #include <cstdio>
54 #endif
55
56 namespace spv {
57
58 Builder::Builder(unsigned int magicNumber) :
59     source(SourceLanguageUnknown),
60     sourceVersion(0),
61     addressModel(AddressingModelLogical),
62     memoryModel(MemoryModelGLSL450),
63     builderNumber(magicNumber),
64     buildPoint(0),
65     uniqueId(0),
66     mainFunction(0)
67 {
68     clearAccessChain();
69 }
70
71 Builder::~Builder()
72 {
73 }
74
75 Id Builder::import(const char* name)
76 {
77     Instruction* import = new Instruction(getUniqueId(), NoType, OpExtInstImport);
78     import->addStringOperand(name);
79     
80     imports.push_back(std::unique_ptr<Instruction>(import));
81     return import->getResultId();
82 }
83
84 // For creating new groupedTypes (will return old type if the requested one was already made).
85 Id Builder::makeVoidType()
86 {
87     Instruction* type;
88     if (groupedTypes[OpTypeVoid].size() == 0) {
89         type = new Instruction(getUniqueId(), NoType, OpTypeVoid);
90         groupedTypes[OpTypeVoid].push_back(type);
91         constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
92         module.mapInstruction(type);
93     } else
94         type = groupedTypes[OpTypeVoid].back();
95
96     return type->getResultId();
97 }
98
99 Id Builder::makeBoolType()
100 {
101     Instruction* type;
102     if (groupedTypes[OpTypeBool].size() == 0) {
103         type = new Instruction(getUniqueId(), NoType, OpTypeBool);
104         groupedTypes[OpTypeBool].push_back(type);
105         constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
106         module.mapInstruction(type);
107     } else
108         type = groupedTypes[OpTypeBool].back();
109
110     return type->getResultId();
111 }
112
113 Id Builder::makeSamplerType()
114 {
115     Instruction* type;
116     if (groupedTypes[OpTypeSampler].size() == 0) {
117         type = new Instruction(getUniqueId(), NoType, OpTypeSampler);
118         groupedTypes[OpTypeSampler].push_back(type);
119         constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
120         module.mapInstruction(type);
121     } else
122         type = groupedTypes[OpTypeSampler].back();
123
124     return type->getResultId();
125 }
126
127 Id Builder::makePointer(StorageClass storageClass, Id pointee)
128 {
129     // try to find it
130     Instruction* type;
131     for (int t = 0; t < (int)groupedTypes[OpTypePointer].size(); ++t) {
132         type = groupedTypes[OpTypePointer][t];
133         if (type->getImmediateOperand(0) == (unsigned)storageClass &&
134             type->getIdOperand(1) == pointee)
135             return type->getResultId();
136     }
137
138     // not found, make it
139     type = new Instruction(getUniqueId(), NoType, OpTypePointer);
140     type->addImmediateOperand(storageClass);
141     type->addIdOperand(pointee);
142     groupedTypes[OpTypePointer].push_back(type);
143     constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
144     module.mapInstruction(type);
145
146     return type->getResultId();
147 }
148
149 Id Builder::makeIntegerType(int width, bool hasSign)
150 {
151     // try to find it
152     Instruction* type;
153     for (int t = 0; t < (int)groupedTypes[OpTypeInt].size(); ++t) {
154         type = groupedTypes[OpTypeInt][t];
155         if (type->getImmediateOperand(0) == (unsigned)width &&
156             type->getImmediateOperand(1) == (hasSign ? 1u : 0u))
157             return type->getResultId();
158     }
159
160     // not found, make it
161     type = new Instruction(getUniqueId(), NoType, OpTypeInt);
162     type->addImmediateOperand(width);
163     type->addImmediateOperand(hasSign ? 1 : 0);
164     groupedTypes[OpTypeInt].push_back(type);
165     constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
166     module.mapInstruction(type);
167
168     return type->getResultId();
169 }
170
171 Id Builder::makeFloatType(int width)
172 {
173     // try to find it
174     Instruction* type;
175     for (int t = 0; t < (int)groupedTypes[OpTypeFloat].size(); ++t) {
176         type = groupedTypes[OpTypeFloat][t];
177         if (type->getImmediateOperand(0) == (unsigned)width)
178             return type->getResultId();
179     }
180
181     // not found, make it
182     type = new Instruction(getUniqueId(), NoType, OpTypeFloat);
183     type->addImmediateOperand(width);
184     groupedTypes[OpTypeFloat].push_back(type);
185     constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
186     module.mapInstruction(type);
187
188     return type->getResultId();
189 }
190
191 // Make a struct without checking for duplication.
192 // See makeStructResultType() for non-decorated structs
193 // needed as the result of some instructions, which does
194 // check for duplicates.
195 Id Builder::makeStructType(std::vector<Id>& members, const char* name)
196 {
197     // Don't look for previous one, because in the general case,
198     // structs can be duplicated except for decorations.
199
200     // not found, make it
201     Instruction* type = new Instruction(getUniqueId(), NoType, OpTypeStruct);
202     for (int op = 0; op < (int)members.size(); ++op)
203         type->addIdOperand(members[op]);
204     groupedTypes[OpTypeStruct].push_back(type);
205     constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
206     module.mapInstruction(type);
207     addName(type->getResultId(), name);
208
209     return type->getResultId();
210 }
211
212 // Make a struct for the simple results of several instructions,
213 // checking for duplication.
214 Id Builder::makeStructResultType(Id type0, Id type1)
215 {
216     // try to find it
217     Instruction* type;
218     for (int t = 0; t < (int)groupedTypes[OpTypeStruct].size(); ++t) {
219         type = groupedTypes[OpTypeStruct][t];
220         if (type->getNumOperands() != 2)
221             continue;
222         if (type->getIdOperand(0) != type0 || 
223             type->getIdOperand(1) != type1)
224             continue;
225         return type->getResultId();
226     }
227
228     // not found, make it
229     std::vector<spv::Id> members;
230     members.push_back(type0);
231     members.push_back(type1);
232
233     return makeStructType(members, "ResType");
234 }
235
236 Id Builder::makeVectorType(Id component, int size)
237 {
238     // try to find it
239     Instruction* type;
240     for (int t = 0; t < (int)groupedTypes[OpTypeVector].size(); ++t) {
241         type = groupedTypes[OpTypeVector][t];
242         if (type->getIdOperand(0) == component &&
243             type->getImmediateOperand(1) == (unsigned)size)
244             return type->getResultId();
245     }
246
247     // not found, make it
248     type = new Instruction(getUniqueId(), NoType, OpTypeVector);
249     type->addIdOperand(component);
250     type->addImmediateOperand(size);
251     groupedTypes[OpTypeVector].push_back(type);
252     constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
253     module.mapInstruction(type);
254
255     return type->getResultId();
256 }
257
258 Id Builder::makeMatrixType(Id component, int cols, int rows)
259 {
260     assert(cols <= maxMatrixSize && rows <= maxMatrixSize);
261
262     Id column = makeVectorType(component, rows);
263
264     // try to find it
265     Instruction* type;
266     for (int t = 0; t < (int)groupedTypes[OpTypeMatrix].size(); ++t) {
267         type = groupedTypes[OpTypeMatrix][t];
268         if (type->getIdOperand(0) == column &&
269             type->getImmediateOperand(1) == (unsigned)cols)
270             return type->getResultId();
271     }
272
273     // not found, make it
274     type = new Instruction(getUniqueId(), NoType, OpTypeMatrix);
275     type->addIdOperand(column);
276     type->addImmediateOperand(cols);
277     groupedTypes[OpTypeMatrix].push_back(type);
278     constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
279     module.mapInstruction(type);
280
281     return type->getResultId();
282 }
283
284 // TODO: performance: track arrays per stride
285 // If a stride is supplied (non-zero) make an array.
286 // If no stride (0), reuse previous array types.
287 Id Builder::makeArrayType(Id element, unsigned size, int stride)
288 {
289     // First, we need a constant instruction for the size
290     Id sizeId = makeUintConstant(size);
291
292     Instruction* type;
293     if (stride == 0) {
294         // try to find existing type
295         for (int t = 0; t < (int)groupedTypes[OpTypeArray].size(); ++t) {
296             type = groupedTypes[OpTypeArray][t];
297             if (type->getIdOperand(0) == element &&
298                 type->getIdOperand(1) == sizeId)
299                 return type->getResultId();
300         }
301     }
302
303     // not found, make it
304     type = new Instruction(getUniqueId(), NoType, OpTypeArray);
305     type->addIdOperand(element);
306     type->addIdOperand(sizeId);
307     groupedTypes[OpTypeArray].push_back(type);
308     constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
309     module.mapInstruction(type);
310
311     return type->getResultId();
312 }
313
314 Id Builder::makeRuntimeArray(Id element)
315 {
316     Instruction* type = new Instruction(getUniqueId(), NoType, OpTypeRuntimeArray);
317     type->addIdOperand(element);
318     constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
319     module.mapInstruction(type);
320
321     return type->getResultId();
322 }
323
324 Id Builder::makeFunctionType(Id returnType, std::vector<Id>& paramTypes)
325 {
326     // try to find it
327     Instruction* type;
328     for (int t = 0; t < (int)groupedTypes[OpTypeFunction].size(); ++t) {
329         type = groupedTypes[OpTypeFunction][t];
330         if (type->getIdOperand(0) != returnType || (int)paramTypes.size() != type->getNumOperands() - 1)
331             continue;
332         bool mismatch = false;
333         for (int p = 0; p < (int)paramTypes.size(); ++p) {
334             if (paramTypes[p] != type->getIdOperand(p + 1)) {
335                 mismatch = true;
336                 break;
337             }
338         }
339         if (! mismatch)
340             return type->getResultId();
341     }
342
343     // not found, make it
344     type = new Instruction(getUniqueId(), NoType, OpTypeFunction);
345     type->addIdOperand(returnType);
346     for (int p = 0; p < (int)paramTypes.size(); ++p)
347         type->addIdOperand(paramTypes[p]);
348     groupedTypes[OpTypeFunction].push_back(type);
349     constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
350     module.mapInstruction(type);
351
352     return type->getResultId();
353 }
354
355 Id Builder::makeImageType(Id sampledType, Dim dim, bool depth, bool arrayed, bool ms, unsigned sampled, ImageFormat format)
356 {
357     // try to find it
358     Instruction* type;
359     for (int t = 0; t < (int)groupedTypes[OpTypeImage].size(); ++t) {
360         type = groupedTypes[OpTypeImage][t];
361         if (type->getIdOperand(0) == sampledType &&
362             type->getImmediateOperand(1) == (unsigned int)dim &&
363             type->getImmediateOperand(2) == (  depth ? 1u : 0u) &&
364             type->getImmediateOperand(3) == (arrayed ? 1u : 0u) &&
365             type->getImmediateOperand(4) == (     ms ? 1u : 0u) &&
366             type->getImmediateOperand(5) == sampled &&
367             type->getImmediateOperand(6) == (unsigned int)format)
368             return type->getResultId();
369     }
370
371     // not found, make it
372     type = new Instruction(getUniqueId(), NoType, OpTypeImage);
373     type->addIdOperand(sampledType);
374     type->addImmediateOperand(   dim);
375     type->addImmediateOperand(  depth ? 1 : 0);
376     type->addImmediateOperand(arrayed ? 1 : 0);
377     type->addImmediateOperand(     ms ? 1 : 0);
378     type->addImmediateOperand(sampled);
379     type->addImmediateOperand((unsigned int)format);
380
381     groupedTypes[OpTypeImage].push_back(type);
382     constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
383     module.mapInstruction(type);
384
385     return type->getResultId();
386 }
387
388 Id Builder::makeSampledImageType(Id imageType)
389 {
390     // try to find it
391     Instruction* type;
392     for (int t = 0; t < (int)groupedTypes[OpTypeSampledImage].size(); ++t) {
393         type = groupedTypes[OpTypeSampledImage][t];
394         if (type->getIdOperand(0) == imageType)
395             return type->getResultId();
396     }
397
398     // not found, make it
399     type = new Instruction(getUniqueId(), NoType, OpTypeSampledImage);
400     type->addIdOperand(imageType);
401
402     groupedTypes[OpTypeSampledImage].push_back(type);
403     constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(type));
404     module.mapInstruction(type);
405
406     return type->getResultId();
407 }
408
409 Id Builder::getDerefTypeId(Id resultId) const
410 {
411     Id typeId = getTypeId(resultId);
412     assert(isPointerType(typeId));
413
414     return module.getInstruction(typeId)->getImmediateOperand(1);
415 }
416
417 Op Builder::getMostBasicTypeClass(Id typeId) const
418 {
419     Instruction* instr = module.getInstruction(typeId);
420
421     Op typeClass = instr->getOpCode();
422     switch (typeClass)
423     {
424     case OpTypeVoid:
425     case OpTypeBool:
426     case OpTypeInt:
427     case OpTypeFloat:
428     case OpTypeStruct:
429         return typeClass;
430     case OpTypeVector:
431     case OpTypeMatrix:
432     case OpTypeArray:
433     case OpTypeRuntimeArray:
434         return getMostBasicTypeClass(instr->getIdOperand(0));
435     case OpTypePointer:
436         return getMostBasicTypeClass(instr->getIdOperand(1));
437     default:
438         assert(0);
439         return OpTypeFloat;
440     }
441 }
442
443 int Builder::getNumTypeConstituents(Id typeId) const
444 {
445     Instruction* instr = module.getInstruction(typeId);
446
447     switch (instr->getOpCode())
448     {
449     case OpTypeBool:
450     case OpTypeInt:
451     case OpTypeFloat:
452         return 1;
453     case OpTypeVector:
454     case OpTypeMatrix:
455     case OpTypeArray:
456         return instr->getImmediateOperand(1);
457     case OpTypeStruct:
458         return instr->getNumOperands();
459     default:
460         assert(0);
461         return 1;
462     }
463 }
464
465 // Return the lowest-level type of scalar that an homogeneous composite is made out of.
466 // Typically, this is just to find out if something is made out of ints or floats.
467 // However, it includes returning a structure, if say, it is an array of structure.
468 Id Builder::getScalarTypeId(Id typeId) const
469 {
470     Instruction* instr = module.getInstruction(typeId);
471
472     Op typeClass = instr->getOpCode();
473     switch (typeClass)
474     {
475     case OpTypeVoid:
476     case OpTypeBool:
477     case OpTypeInt:
478     case OpTypeFloat:
479     case OpTypeStruct:
480         return instr->getResultId();
481     case OpTypeVector:
482     case OpTypeMatrix:
483     case OpTypeArray:
484     case OpTypeRuntimeArray:
485     case OpTypePointer:
486         return getScalarTypeId(getContainedTypeId(typeId));
487     default:
488         assert(0);
489         return NoResult;
490     }
491 }
492
493 // Return the type of 'member' of a composite.
494 Id Builder::getContainedTypeId(Id typeId, int member) const
495 {
496     Instruction* instr = module.getInstruction(typeId);
497
498     Op typeClass = instr->getOpCode();
499     switch (typeClass)
500     {
501     case OpTypeVector:
502     case OpTypeMatrix:
503     case OpTypeArray:
504     case OpTypeRuntimeArray:
505         return instr->getIdOperand(0);
506     case OpTypePointer:
507         return instr->getIdOperand(1);
508     case OpTypeStruct:
509         return instr->getIdOperand(member);
510     default:
511         assert(0);
512         return NoResult;
513     }
514 }
515
516 // Return the immediately contained type of a given composite type.
517 Id Builder::getContainedTypeId(Id typeId) const
518 {
519     return getContainedTypeId(typeId, 0);
520 }
521
522 // See if a scalar constant of this type has already been created, so it
523 // can be reused rather than duplicated.  (Required by the specification).
524 Id Builder::findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned value) const
525 {
526     Instruction* constant;
527     for (int i = 0; i < (int)groupedConstants[typeClass].size(); ++i) {
528         constant = groupedConstants[typeClass][i];
529         if (constant->getOpCode() == opcode &&
530             constant->getTypeId() == typeId &&
531             constant->getImmediateOperand(0) == value)
532             return constant->getResultId();
533     }
534
535     return 0;
536 }
537
538 // Version of findScalarConstant (see above) for scalars that take two operands (e.g. a 'double').
539 Id Builder::findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned v1, unsigned v2) const
540 {
541     Instruction* constant;
542     for (int i = 0; i < (int)groupedConstants[typeClass].size(); ++i) {
543         constant = groupedConstants[typeClass][i];
544         if (constant->getOpCode() == opcode &&
545             constant->getTypeId() == typeId &&
546             constant->getImmediateOperand(0) == v1 &&
547             constant->getImmediateOperand(1) == v2)
548             return constant->getResultId();
549     }
550
551     return 0;
552 }
553
554 // Return true if consuming 'opcode' means consuming a constant.
555 // "constant" here means after final transform to executable code,
556 // the value consumed will be a constant, so includes specialization.
557 bool Builder::isConstantOpCode(Op opcode) const
558 {
559     switch (opcode) {
560     case OpUndef: 
561     case OpConstantTrue:
562     case OpConstantFalse:
563     case OpConstant:
564     case OpConstantComposite:
565     case OpConstantSampler:
566     case OpConstantNull:
567     case OpSpecConstantTrue:
568     case OpSpecConstantFalse:
569     case OpSpecConstant:
570     case OpSpecConstantComposite:
571     case OpSpecConstantOp:
572         return true;
573     default:
574         return false;
575     }
576 }
577
578 Id Builder::makeBoolConstant(bool b, bool specConstant)
579 {
580     Id typeId = makeBoolType();
581     Instruction* constant;
582     Op opcode = specConstant ? (b ? OpSpecConstantTrue : OpSpecConstantFalse) : (b ? OpConstantTrue : OpConstantFalse);
583
584     // See if we already made it
585     Id existing = 0;
586     for (int i = 0; i < (int)groupedConstants[OpTypeBool].size(); ++i) {
587         constant = groupedConstants[OpTypeBool][i];
588         if (constant->getTypeId() == typeId && constant->getOpCode() == opcode)
589             existing = constant->getResultId();
590     }
591
592     if (existing)
593         return existing;
594
595     // Make it
596     Instruction* c = new Instruction(getUniqueId(), typeId, opcode);
597     constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(c));
598     groupedConstants[OpTypeBool].push_back(c);
599     module.mapInstruction(c);
600
601     return c->getResultId();
602 }
603
604 Id Builder::makeIntConstant(Id typeId, unsigned value, bool specConstant)
605 {
606     Op opcode = specConstant ? OpSpecConstant : OpConstant;
607     Id existing = findScalarConstant(OpTypeInt, opcode, typeId, value);
608     if (existing)
609         return existing;
610
611     Instruction* c = new Instruction(getUniqueId(), typeId, opcode);
612     c->addImmediateOperand(value);
613     constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(c));
614     groupedConstants[OpTypeInt].push_back(c);
615     module.mapInstruction(c);
616
617     return c->getResultId();
618 }
619
620 Id Builder::makeFloatConstant(float f, bool specConstant)
621 {
622     Op opcode = specConstant ? OpSpecConstant : OpConstant;
623     Id typeId = makeFloatType(32);
624     unsigned value = *(unsigned int*)&f;
625     Id existing = findScalarConstant(OpTypeFloat, opcode, typeId, value);
626     if (existing)
627         return existing;
628
629     Instruction* c = new Instruction(getUniqueId(), typeId, opcode);
630     c->addImmediateOperand(value);
631     constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(c));
632     groupedConstants[OpTypeFloat].push_back(c);
633     module.mapInstruction(c);
634
635     return c->getResultId();
636 }
637
638 Id Builder::makeDoubleConstant(double d, bool specConstant)
639 {
640     Op opcode = specConstant ? OpSpecConstant : OpConstant;
641     Id typeId = makeFloatType(64);
642     unsigned long long value = *(unsigned long long*)&d;
643     unsigned op1 = value & 0xFFFFFFFF;
644     unsigned op2 = value >> 32;
645     Id existing = findScalarConstant(OpTypeFloat, opcode, typeId, op1, op2);
646     if (existing)
647         return existing;
648
649     Instruction* c = new Instruction(getUniqueId(), typeId, opcode);
650     c->addImmediateOperand(op1);
651     c->addImmediateOperand(op2);
652     constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(c));
653     groupedConstants[OpTypeFloat].push_back(c);
654     module.mapInstruction(c);
655
656     return c->getResultId();
657 }
658
659 Id Builder::findCompositeConstant(Op typeClass, std::vector<Id>& comps) const
660 {
661     Instruction* constant = 0;
662     bool found = false;
663     for (int i = 0; i < (int)groupedConstants[typeClass].size(); ++i) {
664         constant = groupedConstants[typeClass][i];
665
666         // same shape?
667         if (constant->getNumOperands() != (int)comps.size())
668             continue;
669
670         // same contents?
671         bool mismatch = false;
672         for (int op = 0; op < constant->getNumOperands(); ++op) {
673             if (constant->getIdOperand(op) != comps[op]) {
674                 mismatch = true;
675                 break;
676             }
677         }
678         if (! mismatch) {
679             found = true;
680             break;
681         }
682     }
683
684     return found ? constant->getResultId() : NoResult;
685 }
686
687 // Comments in header
688 Id Builder::makeCompositeConstant(Id typeId, std::vector<Id>& members)
689 {
690     assert(typeId);
691     Op typeClass = getTypeClass(typeId);
692
693     switch (typeClass) {
694     case OpTypeVector:
695     case OpTypeArray:
696     case OpTypeStruct:
697     case OpTypeMatrix:
698         break;
699     default:
700         assert(0);
701         return makeFloatConstant(0.0);
702     }
703
704     Id existing = findCompositeConstant(typeClass, members);
705     if (existing)
706         return existing;
707
708     Instruction* c = new Instruction(getUniqueId(), typeId, OpConstantComposite);
709     for (int op = 0; op < (int)members.size(); ++op)
710         c->addIdOperand(members[op]);
711     constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(c));
712     groupedConstants[typeClass].push_back(c);
713     module.mapInstruction(c);
714
715     return c->getResultId();
716 }
717
718 Instruction* Builder::addEntryPoint(ExecutionModel model, Function* function, const char* name)
719 {
720     Instruction* entryPoint = new Instruction(OpEntryPoint);
721     entryPoint->addImmediateOperand(model);
722     entryPoint->addIdOperand(function->getId());
723     entryPoint->addStringOperand(name);
724
725     entryPoints.push_back(std::unique_ptr<Instruction>(entryPoint));
726
727     return entryPoint;
728 }
729
730 // Currently relying on the fact that all 'value' of interest are small non-negative values.
731 void Builder::addExecutionMode(Function* entryPoint, ExecutionMode mode, int value1, int value2, int value3)
732 {
733     Instruction* instr = new Instruction(OpExecutionMode);
734     instr->addIdOperand(entryPoint->getId());
735     instr->addImmediateOperand(mode);
736     if (value1 >= 0)
737         instr->addImmediateOperand(value1);
738     if (value2 >= 0)
739         instr->addImmediateOperand(value2);
740     if (value3 >= 0)
741         instr->addImmediateOperand(value3);
742
743     executionModes.push_back(std::unique_ptr<Instruction>(instr));
744 }
745
746 void Builder::addName(Id id, const char* string)
747 {
748     Instruction* name = new Instruction(OpName);
749     name->addIdOperand(id);
750     name->addStringOperand(string);
751
752     names.push_back(std::unique_ptr<Instruction>(name));
753 }
754
755 void Builder::addMemberName(Id id, int memberNumber, const char* string)
756 {
757     Instruction* name = new Instruction(OpMemberName);
758     name->addIdOperand(id);
759     name->addImmediateOperand(memberNumber);
760     name->addStringOperand(string);
761
762     names.push_back(std::unique_ptr<Instruction>(name));
763 }
764
765 void Builder::addLine(Id target, Id fileName, int lineNum, int column)
766 {
767     Instruction* line = new Instruction(OpLine);
768     line->addIdOperand(target);
769     line->addIdOperand(fileName);
770     line->addImmediateOperand(lineNum);
771     line->addImmediateOperand(column);
772
773     lines.push_back(std::unique_ptr<Instruction>(line));
774 }
775
776 void Builder::addDecoration(Id id, Decoration decoration, int num)
777 {
778     if (decoration == (spv::Decoration)spv::BadValue)
779         return;
780     Instruction* dec = new Instruction(OpDecorate);
781     dec->addIdOperand(id);
782     dec->addImmediateOperand(decoration);
783     if (num >= 0)
784         dec->addImmediateOperand(num);
785
786     decorations.push_back(std::unique_ptr<Instruction>(dec));
787 }
788
789 void Builder::addMemberDecoration(Id id, unsigned int member, Decoration decoration, int num)
790 {
791     Instruction* dec = new Instruction(OpMemberDecorate);
792     dec->addIdOperand(id);
793     dec->addImmediateOperand(member);
794     dec->addImmediateOperand(decoration);
795     if (num >= 0)
796         dec->addImmediateOperand(num);
797
798     decorations.push_back(std::unique_ptr<Instruction>(dec));
799 }
800
801 // Comments in header
802 Function* Builder::makeMain()
803 {
804     assert(! mainFunction);
805
806     Block* entry;
807     std::vector<Id> params;
808
809     mainFunction = makeFunctionEntry(makeVoidType(), "main", params, &entry);
810
811     return mainFunction;
812 }
813
814 // Comments in header
815 Function* Builder::makeFunctionEntry(Id returnType, const char* name, std::vector<Id>& paramTypes, Block **entry)
816 {
817     Id typeId = makeFunctionType(returnType, paramTypes);
818     Id firstParamId = paramTypes.size() == 0 ? 0 : getUniqueIds((int)paramTypes.size());
819     Function* function = new Function(getUniqueId(), returnType, typeId, firstParamId, module);
820
821     if (entry) {
822         *entry = new Block(getUniqueId(), *function);
823         function->addBlock(*entry);
824         setBuildPoint(*entry);
825     }
826
827     if (name)
828         addName(function->getId(), name);
829
830     functions.push_back(std::unique_ptr<Function>(function));
831
832     return function;
833 }
834
835 // Comments in header
836 void Builder::makeReturn(bool implicit, Id retVal)
837 {
838     if (retVal) {
839         Instruction* inst = new Instruction(NoResult, NoType, OpReturnValue);
840         inst->addIdOperand(retVal);
841         buildPoint->addInstruction(std::unique_ptr<Instruction>(inst));
842     } else
843         buildPoint->addInstruction(std::unique_ptr<Instruction>(new Instruction(NoResult, NoType, OpReturn)));
844
845     if (! implicit)
846         createAndSetNoPredecessorBlock("post-return");
847 }
848
849 // Comments in header
850 void Builder::leaveFunction()
851 {
852     Block* block = buildPoint;
853     Function& function = buildPoint->getParent();
854     assert(block);
855
856     // If our function did not contain a return, add a return void now.
857     if (! block->isTerminated()) {
858
859         // Whether we're in an unreachable (non-entry) block.
860         bool unreachable = function.getEntryBlock() != block && block->getNumPredecessors() == 0;
861
862         if (unreachable) {
863             // Given that this block is at the end of a function, it must be right after an
864             // explicit return, just remove it.
865             function.popBlock(block);
866         } else {
867             // We'll add a return instruction at the end of the current block,
868             // which for a non-void function is really error recovery (?), as the source
869             // being translated should have had an explicit return, which would have been
870             // followed by an unreachable block, which was handled above.
871             if (function.getReturnType() == makeVoidType())
872                 makeReturn(true);
873             else {
874                 makeReturn(true, createUndefined(function.getReturnType()));
875             }
876         }
877     }
878 }
879
880 // Comments in header
881 void Builder::makeDiscard()
882 {
883     buildPoint->addInstruction(std::unique_ptr<Instruction>(new Instruction(OpKill)));
884     createAndSetNoPredecessorBlock("post-discard");
885 }
886
887 // Comments in header
888 Id Builder::createVariable(StorageClass storageClass, Id type, const char* name)
889 {
890     Id pointerType = makePointer(storageClass, type);
891     Instruction* inst = new Instruction(getUniqueId(), pointerType, OpVariable);
892     inst->addImmediateOperand(storageClass);
893
894     switch (storageClass) {
895     case StorageClassFunction:
896         // Validation rules require the declaration in the entry block
897         buildPoint->getParent().addLocalVariable(std::unique_ptr<Instruction>(inst));
898         break;
899
900     default:
901         constantsTypesGlobals.push_back(std::unique_ptr<Instruction>(inst));
902         module.mapInstruction(inst);
903         break;
904     }
905
906     if (name)
907         addName(inst->getResultId(), name);
908
909     return inst->getResultId();
910 }
911
912 // Comments in header
913 Id Builder::createUndefined(Id type)
914 {
915   Instruction* inst = new Instruction(getUniqueId(), type, OpUndef);
916   buildPoint->addInstruction(std::unique_ptr<Instruction>(inst));
917   return inst->getResultId();
918 }
919
920 // Comments in header
921 void Builder::createStore(Id rValue, Id lValue)
922 {
923     Instruction* store = new Instruction(OpStore);
924     store->addIdOperand(lValue);
925     store->addIdOperand(rValue);
926     buildPoint->addInstruction(std::unique_ptr<Instruction>(store));
927 }
928
929 // Comments in header
930 Id Builder::createLoad(Id lValue)
931 {
932     Instruction* load = new Instruction(getUniqueId(), getDerefTypeId(lValue), OpLoad);
933     load->addIdOperand(lValue);
934     buildPoint->addInstruction(std::unique_ptr<Instruction>(load));
935
936     return load->getResultId();
937 }
938
939 // Comments in header
940 Id Builder::createAccessChain(StorageClass storageClass, Id base, std::vector<Id>& offsets)
941 {
942     // Figure out the final resulting type.
943     spv::Id typeId = getTypeId(base);
944     assert(isPointerType(typeId) && offsets.size() > 0);
945     typeId = getContainedTypeId(typeId);
946     for (int i = 0; i < (int)offsets.size(); ++i) {
947         if (isStructType(typeId)) {
948             assert(isConstantScalar(offsets[i]));
949             typeId = getContainedTypeId(typeId, getConstantScalar(offsets[i]));
950         } else
951             typeId = getContainedTypeId(typeId, offsets[i]);
952     }
953     typeId = makePointer(storageClass, typeId);
954
955     // Make the instruction
956     Instruction* chain = new Instruction(getUniqueId(), typeId, OpAccessChain);
957     chain->addIdOperand(base);
958     for (int i = 0; i < (int)offsets.size(); ++i)
959         chain->addIdOperand(offsets[i]);
960     buildPoint->addInstruction(std::unique_ptr<Instruction>(chain));
961
962     return chain->getResultId();
963 }
964
965 Id Builder::createArrayLength(Id base, unsigned int member)
966 {
967     Instruction* length = new Instruction(getUniqueId(), makeIntType(32), OpArrayLength);
968     length->addIdOperand(base);
969     length->addImmediateOperand(member);
970     buildPoint->addInstruction(std::unique_ptr<Instruction>(length));
971
972     return length->getResultId();
973 }
974
975 Id Builder::createCompositeExtract(Id composite, Id typeId, unsigned index)
976 {
977     Instruction* extract = new Instruction(getUniqueId(), typeId, OpCompositeExtract);
978     extract->addIdOperand(composite);
979     extract->addImmediateOperand(index);
980     buildPoint->addInstruction(std::unique_ptr<Instruction>(extract));
981
982     return extract->getResultId();
983 }
984
985 Id Builder::createCompositeExtract(Id composite, Id typeId, std::vector<unsigned>& indexes)
986 {
987     Instruction* extract = new Instruction(getUniqueId(), typeId, OpCompositeExtract);
988     extract->addIdOperand(composite);
989     for (int i = 0; i < (int)indexes.size(); ++i)
990         extract->addImmediateOperand(indexes[i]);
991     buildPoint->addInstruction(std::unique_ptr<Instruction>(extract));
992
993     return extract->getResultId();
994 }
995
996 Id Builder::createCompositeInsert(Id object, Id composite, Id typeId, unsigned index)
997 {
998     Instruction* insert = new Instruction(getUniqueId(), typeId, OpCompositeInsert);
999     insert->addIdOperand(object);
1000     insert->addIdOperand(composite);
1001     insert->addImmediateOperand(index);
1002     buildPoint->addInstruction(std::unique_ptr<Instruction>(insert));
1003
1004     return insert->getResultId();
1005 }
1006
1007 Id Builder::createCompositeInsert(Id object, Id composite, Id typeId, std::vector<unsigned>& indexes)
1008 {
1009     Instruction* insert = new Instruction(getUniqueId(), typeId, OpCompositeInsert);
1010     insert->addIdOperand(object);
1011     insert->addIdOperand(composite);
1012     for (int i = 0; i < (int)indexes.size(); ++i)
1013         insert->addImmediateOperand(indexes[i]);
1014     buildPoint->addInstruction(std::unique_ptr<Instruction>(insert));
1015
1016     return insert->getResultId();
1017 }
1018
1019 Id Builder::createVectorExtractDynamic(Id vector, Id typeId, Id componentIndex)
1020 {
1021     Instruction* extract = new Instruction(getUniqueId(), typeId, OpVectorExtractDynamic);
1022     extract->addIdOperand(vector);
1023     extract->addIdOperand(componentIndex);
1024     buildPoint->addInstruction(std::unique_ptr<Instruction>(extract));
1025
1026     return extract->getResultId();
1027 }
1028
1029 Id Builder::createVectorInsertDynamic(Id vector, Id typeId, Id component, Id componentIndex)
1030 {
1031     Instruction* insert = new Instruction(getUniqueId(), typeId, OpVectorInsertDynamic);
1032     insert->addIdOperand(vector);
1033     insert->addIdOperand(component);
1034     insert->addIdOperand(componentIndex);
1035     buildPoint->addInstruction(std::unique_ptr<Instruction>(insert));
1036
1037     return insert->getResultId();
1038 }
1039
1040 // An opcode that has no operands, no result id, and no type
1041 void Builder::createNoResultOp(Op opCode)
1042 {
1043     Instruction* op = new Instruction(opCode);
1044     buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
1045 }
1046
1047 // An opcode that has one operand, no result id, and no type
1048 void Builder::createNoResultOp(Op opCode, Id operand)
1049 {
1050     Instruction* op = new Instruction(opCode);
1051     op->addIdOperand(operand);
1052     buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
1053 }
1054
1055 // An opcode that has one operand, no result id, and no type
1056 void Builder::createNoResultOp(Op opCode, const std::vector<Id>& operands)
1057 {
1058     Instruction* op = new Instruction(opCode);
1059     for (auto operand : operands)
1060         op->addIdOperand(operand);
1061     buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
1062 }
1063
1064 void Builder::createControlBarrier(Scope execution, Scope memory, MemorySemanticsMask semantics)
1065 {
1066     Instruction* op = new Instruction(OpControlBarrier);
1067     op->addImmediateOperand(makeUintConstant(execution));
1068     op->addImmediateOperand(makeUintConstant(memory));
1069     op->addImmediateOperand(makeUintConstant(semantics));
1070     buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
1071 }
1072
1073 void Builder::createMemoryBarrier(unsigned executionScope, unsigned memorySemantics)
1074 {
1075     Instruction* op = new Instruction(OpMemoryBarrier);
1076     op->addImmediateOperand(makeUintConstant(executionScope));
1077     op->addImmediateOperand(makeUintConstant(memorySemantics));
1078     buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
1079 }
1080
1081 // An opcode that has one operands, a result id, and a type
1082 Id Builder::createUnaryOp(Op opCode, Id typeId, Id operand)
1083 {
1084     Instruction* op = new Instruction(getUniqueId(), typeId, opCode);
1085     op->addIdOperand(operand);
1086     buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
1087
1088     return op->getResultId();
1089 }
1090
1091 Id Builder::createBinOp(Op opCode, Id typeId, Id left, Id right)
1092 {
1093     Instruction* op = new Instruction(getUniqueId(), typeId, opCode);
1094     op->addIdOperand(left);
1095     op->addIdOperand(right);
1096     buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
1097
1098     return op->getResultId();
1099 }
1100
1101 Id Builder::createTriOp(Op opCode, Id typeId, Id op1, Id op2, Id op3)
1102 {
1103     Instruction* op = new Instruction(getUniqueId(), typeId, opCode);
1104     op->addIdOperand(op1);
1105     op->addIdOperand(op2);
1106     op->addIdOperand(op3);
1107     buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
1108
1109     return op->getResultId();
1110 }
1111
1112 Id Builder::createOp(Op opCode, Id typeId, const std::vector<Id>& operands)
1113 {
1114     Instruction* op = new Instruction(getUniqueId(), typeId, opCode);
1115     for (auto operand : operands)
1116         op->addIdOperand(operand);
1117     buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
1118
1119     return op->getResultId();
1120 }
1121
1122 Id Builder::createFunctionCall(spv::Function* function, std::vector<spv::Id>& args)
1123 {
1124     Instruction* op = new Instruction(getUniqueId(), function->getReturnType(), OpFunctionCall);
1125     op->addIdOperand(function->getId());
1126     for (int a = 0; a < (int)args.size(); ++a)
1127         op->addIdOperand(args[a]);
1128     buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
1129
1130     return op->getResultId();
1131 }
1132
1133 // Comments in header
1134 Id Builder::createRvalueSwizzle(Id typeId, Id source, std::vector<unsigned>& channels)
1135 {
1136     if (channels.size() == 1)
1137         return createCompositeExtract(source, typeId, channels.front());
1138
1139     Instruction* swizzle = new Instruction(getUniqueId(), typeId, OpVectorShuffle);
1140     assert(isVector(source));
1141     swizzle->addIdOperand(source);
1142     swizzle->addIdOperand(source);
1143     for (int i = 0; i < (int)channels.size(); ++i)
1144         swizzle->addImmediateOperand(channels[i]);
1145     buildPoint->addInstruction(std::unique_ptr<Instruction>(swizzle));
1146
1147     return swizzle->getResultId();
1148 }
1149
1150 // Comments in header
1151 Id Builder::createLvalueSwizzle(Id typeId, Id target, Id source, std::vector<unsigned>& channels)
1152 {
1153     assert(getNumComponents(source) == (int)channels.size());
1154     if (channels.size() == 1 && getNumComponents(source) == 1)
1155         return createCompositeInsert(source, target, typeId, channels.front());
1156
1157     Instruction* swizzle = new Instruction(getUniqueId(), typeId, OpVectorShuffle);
1158     assert(isVector(source));
1159     assert(isVector(target));
1160     swizzle->addIdOperand(target);
1161     swizzle->addIdOperand(source);
1162
1163     // Set up an identity shuffle from the base value to the result value
1164     unsigned int components[4];
1165     int numTargetComponents = getNumComponents(target);
1166     for (int i = 0; i < numTargetComponents; ++i)
1167         components[i] = i;
1168
1169     // Punch in the l-value swizzle
1170     for (int i = 0; i < (int)channels.size(); ++i)
1171         components[channels[i]] = numTargetComponents + i;
1172
1173     // finish the instruction with these components selectors
1174     for (int i = 0; i < numTargetComponents; ++i)
1175         swizzle->addImmediateOperand(components[i]);
1176     buildPoint->addInstruction(std::unique_ptr<Instruction>(swizzle));
1177
1178     return swizzle->getResultId();
1179 }
1180
1181 // Comments in header
1182 void Builder::promoteScalar(Decoration precision, Id& left, Id& right)
1183 {
1184     int direction = getNumComponents(right) - getNumComponents(left);
1185
1186     if (direction > 0)
1187         left = smearScalar(precision, left, makeVectorType(getTypeId(left), getNumComponents(right)));
1188     else if (direction < 0)
1189         right = smearScalar(precision, right, makeVectorType(getTypeId(right), getNumComponents(left)));
1190
1191     return;
1192 }
1193
1194 // Comments in header
1195 Id Builder::smearScalar(Decoration /*precision*/, Id scalar, Id vectorType)
1196 {
1197     assert(getNumComponents(scalar) == 1);
1198     assert(getTypeId(scalar) == getScalarTypeId(vectorType));
1199
1200     int numComponents = getNumTypeComponents(vectorType);
1201     if (numComponents == 1)
1202         return scalar;
1203
1204     Instruction* smear = new Instruction(getUniqueId(), vectorType, OpCompositeConstruct);
1205     for (int c = 0; c < numComponents; ++c)
1206         smear->addIdOperand(scalar);
1207     buildPoint->addInstruction(std::unique_ptr<Instruction>(smear));
1208
1209     return smear->getResultId();
1210 }
1211
1212 // Comments in header
1213 Id Builder::createBuiltinCall(Decoration /*precision*/, Id resultType, Id builtins, int entryPoint, std::vector<Id>& args)
1214 {
1215     Instruction* inst = new Instruction(getUniqueId(), resultType, OpExtInst);
1216     inst->addIdOperand(builtins);
1217     inst->addImmediateOperand(entryPoint);
1218     for (int arg = 0; arg < (int)args.size(); ++arg)
1219         inst->addIdOperand(args[arg]);
1220
1221     buildPoint->addInstruction(std::unique_ptr<Instruction>(inst));
1222     return inst->getResultId();
1223 }
1224
1225 // Accept all parameters needed to create a texture instruction.
1226 // Create the correct instruction based on the inputs, and make the call.
1227 Id Builder::createTextureCall(Decoration precision, Id resultType, bool sparse, bool fetch, bool proj, bool gather, const TextureParameters& parameters)
1228 {
1229     static const int maxTextureArgs = 10;
1230     Id texArgs[maxTextureArgs] = {};
1231
1232     //
1233     // Set up the fixed arguments
1234     //
1235     int numArgs = 0;
1236     bool xplicit = false;
1237     texArgs[numArgs++] = parameters.sampler;
1238     texArgs[numArgs++] = parameters.coords;
1239     if (parameters.Dref)
1240         texArgs[numArgs++] = parameters.Dref;
1241     if (parameters.comp)
1242         texArgs[numArgs++] = parameters.comp;
1243
1244     //
1245     // Set up the optional arguments
1246     //
1247     int optArgNum = numArgs;                        // track which operand, if it exists, is the mask of optional arguments
1248     ++numArgs;                                      // speculatively make room for the mask operand
1249     ImageOperandsMask mask = ImageOperandsMaskNone; // the mask operand
1250     if (parameters.bias) {
1251         mask = (ImageOperandsMask)(mask | ImageOperandsBiasMask);
1252         texArgs[numArgs++] = parameters.bias;
1253     }
1254     if (parameters.lod) {
1255         mask = (ImageOperandsMask)(mask | ImageOperandsLodMask);
1256         texArgs[numArgs++] = parameters.lod;
1257         xplicit = true;
1258     }
1259     if (parameters.gradX) {
1260         mask = (ImageOperandsMask)(mask | ImageOperandsGradMask);
1261         texArgs[numArgs++] = parameters.gradX;
1262         texArgs[numArgs++] = parameters.gradY;
1263         xplicit = true;
1264     }
1265     if (parameters.offset) {
1266         if (isConstant(parameters.offset))
1267             mask = (ImageOperandsMask)(mask | ImageOperandsConstOffsetMask);
1268         else
1269             mask = (ImageOperandsMask)(mask | ImageOperandsOffsetMask);
1270         texArgs[numArgs++] = parameters.offset;
1271     }
1272     if (parameters.offsets) {
1273         mask = (ImageOperandsMask)(mask | ImageOperandsConstOffsetsMask);
1274         texArgs[numArgs++] = parameters.offsets;
1275     }
1276     if (parameters.sample) {
1277         mask = (ImageOperandsMask)(mask | ImageOperandsSampleMask);
1278         texArgs[numArgs++] = parameters.sample;
1279     }
1280     if (parameters.lodClamp) {
1281         mask = (ImageOperandsMask)(mask | ImageOperandsMinLodMask);
1282         texArgs[numArgs++] = parameters.lodClamp;
1283     }
1284     if (mask == ImageOperandsMaskNone)
1285         --numArgs;  // undo speculative reservation for the mask argument
1286     else
1287         texArgs[optArgNum] = mask;
1288
1289     //
1290     // Set up the instruction
1291     //
1292     Op opCode;
1293     opCode = OpImageSampleImplicitLod;
1294     if (fetch) {
1295         if (sparse)
1296             opCode = OpImageSparseFetch;
1297         else
1298             opCode = OpImageFetch;
1299     } else if (gather) {
1300         if (parameters.Dref)
1301             if (sparse)
1302                 opCode = OpImageSparseDrefGather;
1303             else
1304                 opCode = OpImageDrefGather;
1305         else
1306             if (sparse)
1307                 opCode = OpImageSparseGather;
1308             else
1309                 opCode = OpImageGather;
1310     } else if (xplicit) {
1311         if (parameters.Dref) {
1312             if (proj)
1313                 if (sparse)
1314                     opCode = OpImageSparseSampleProjDrefExplicitLod;
1315                 else
1316                     opCode = OpImageSampleProjDrefExplicitLod;
1317             else
1318                 if (sparse)
1319                     opCode = OpImageSparseSampleDrefExplicitLod;
1320                 else
1321                     opCode = OpImageSampleDrefExplicitLod;
1322         } else {
1323             if (proj)
1324                 if (sparse)
1325                     opCode = OpImageSparseSampleProjExplicitLod;
1326                 else
1327                     opCode = OpImageSampleProjExplicitLod;
1328             else
1329                 if (sparse)
1330                     opCode = OpImageSparseSampleExplicitLod;
1331                 else
1332                     opCode = OpImageSampleExplicitLod;
1333         }
1334     } else {
1335         if (parameters.Dref) {
1336             if (proj)
1337                 if (sparse)
1338                     opCode = OpImageSparseSampleProjDrefImplicitLod;
1339                 else
1340                     opCode = OpImageSampleProjDrefImplicitLod;
1341             else
1342                 if (sparse)
1343                     opCode = OpImageSparseSampleDrefImplicitLod;
1344                 else
1345                     opCode = OpImageSampleDrefImplicitLod;
1346         } else {
1347             if (proj)
1348                 if (sparse)
1349                     opCode = OpImageSparseSampleProjImplicitLod;
1350                 else
1351                     opCode = OpImageSampleProjImplicitLod;
1352             else
1353                 if (sparse)
1354                     opCode = OpImageSparseSampleImplicitLod;
1355                 else
1356                     opCode = OpImageSampleImplicitLod;
1357         }
1358     }
1359
1360     // See if the result type is expecting a smeared result.
1361     // This happens when a legacy shadow*() call is made, which
1362     // gets a vec4 back instead of a float.
1363     Id smearedType = resultType;
1364     if (! isScalarType(resultType)) {
1365         switch (opCode) {
1366         case OpImageSampleDrefImplicitLod:
1367         case OpImageSampleDrefExplicitLod:
1368         case OpImageSampleProjDrefImplicitLod:
1369         case OpImageSampleProjDrefExplicitLod:
1370             resultType = getScalarTypeId(resultType);
1371             break;
1372         default:
1373             break;
1374         }
1375     }
1376
1377     Id typeId0 = 0;
1378     Id typeId1 = 0;
1379
1380     if (sparse) {
1381         typeId0 = resultType;
1382         typeId1 = getDerefTypeId(parameters.texelOut);
1383         resultType = makeStructResultType(typeId0, typeId1);
1384     }
1385
1386     // Build the SPIR-V instruction
1387     Instruction* textureInst = new Instruction(getUniqueId(), resultType, opCode);
1388     for (int op = 0; op < optArgNum; ++op)
1389         textureInst->addIdOperand(texArgs[op]);
1390     if (optArgNum < numArgs)
1391         textureInst->addImmediateOperand(texArgs[optArgNum]);
1392     for (int op = optArgNum + 1; op < numArgs; ++op)
1393         textureInst->addIdOperand(texArgs[op]);
1394     setPrecision(textureInst->getResultId(), precision);
1395     buildPoint->addInstruction(std::unique_ptr<Instruction>(textureInst));
1396
1397     Id resultId = textureInst->getResultId();
1398
1399     if (sparse) {
1400         // Decode the return type that was a special structure
1401         createStore(createCompositeExtract(resultId, typeId1, 1), parameters.texelOut);
1402         resultId = createCompositeExtract(resultId, typeId0, 0);
1403     } else {
1404         // When a smear is needed, do it, as per what was computed
1405         // above when resultType was changed to a scalar type.
1406         if (resultType != smearedType)
1407             resultId = smearScalar(precision, resultId, smearedType);
1408     }
1409
1410     return resultId;
1411 }
1412
1413 // Comments in header
1414 Id Builder::createTextureQueryCall(Op opCode, const TextureParameters& parameters)
1415 {
1416     // Figure out the result type
1417     Id resultType = 0;
1418     switch (opCode) {
1419     case OpImageQuerySize:
1420     case OpImageQuerySizeLod:
1421     {
1422         int numComponents = 0;
1423         switch (getTypeDimensionality(getImageType(parameters.sampler))) {
1424         case Dim1D:
1425         case DimBuffer:
1426             numComponents = 1;
1427             break;
1428         case Dim2D:
1429         case DimCube:
1430         case DimRect:
1431         case DimSubpassData:
1432             numComponents = 2;
1433             break;
1434         case Dim3D:
1435             numComponents = 3;
1436             break;
1437
1438         default:
1439             assert(0);
1440             break;
1441         }
1442         if (isArrayedImageType(getImageType(parameters.sampler)))
1443             ++numComponents;
1444         if (numComponents == 1)
1445             resultType = makeIntType(32);
1446         else
1447             resultType = makeVectorType(makeIntType(32), numComponents);
1448
1449         break;
1450     }
1451     case OpImageQueryLod:
1452         resultType = makeVectorType(makeFloatType(32), 2);
1453         break;
1454     case OpImageQueryLevels:
1455     case OpImageQuerySamples:
1456         resultType = makeIntType(32);
1457         break;
1458     default:
1459         assert(0);
1460         break;
1461     }
1462
1463     Instruction* query = new Instruction(getUniqueId(), resultType, opCode);
1464     query->addIdOperand(parameters.sampler);
1465     if (parameters.coords)
1466         query->addIdOperand(parameters.coords);
1467     if (parameters.lod)
1468         query->addIdOperand(parameters.lod);
1469     buildPoint->addInstruction(std::unique_ptr<Instruction>(query));
1470
1471     return query->getResultId();
1472 }
1473
1474 // External comments in header.
1475 // Operates recursively to visit the composite's hierarchy.
1476 Id Builder::createCompositeCompare(Decoration precision, Id value1, Id value2, bool equal)
1477 {
1478     Id boolType = makeBoolType();
1479     Id valueType = getTypeId(value1);
1480
1481     Id resultId;
1482
1483     int numConstituents = getNumTypeConstituents(valueType);
1484
1485     // Scalars and Vectors
1486
1487     if (isScalarType(valueType) || isVectorType(valueType)) {
1488         assert(valueType == getTypeId(value2));
1489         // These just need a single comparison, just have
1490         // to figure out what it is.
1491         Op op;
1492         switch (getMostBasicTypeClass(valueType)) {
1493         case OpTypeFloat:
1494             op = equal ? OpFOrdEqual : OpFOrdNotEqual;
1495             break;
1496         case OpTypeInt:
1497             op = equal ? OpIEqual : OpINotEqual;
1498             break;
1499         case OpTypeBool:
1500             op = equal ? OpLogicalEqual : OpLogicalNotEqual;
1501             precision = NoPrecision;
1502             break;
1503         }
1504
1505         if (isScalarType(valueType)) {
1506             // scalar
1507             resultId = createBinOp(op, boolType, value1, value2);
1508             setPrecision(resultId, precision);
1509         } else {
1510             // vector
1511             resultId = createBinOp(op, makeVectorType(boolType, numConstituents), value1, value2);
1512             setPrecision(resultId, precision);
1513             // reduce vector compares...
1514             resultId = createUnaryOp(equal ? OpAll : OpAny, boolType, resultId);
1515         }
1516
1517         return resultId;
1518     }
1519
1520     // Only structs, arrays, and matrices should be left.
1521     // They share in common the reduction operation across their constituents.
1522     assert(isAggregateType(valueType) || isMatrixType(valueType));
1523
1524     // Compare each pair of constituents
1525     for (int constituent = 0; constituent < numConstituents; ++constituent) {
1526         std::vector<unsigned> indexes(1, constituent);
1527         Id constituentType1 = getContainedTypeId(getTypeId(value1), constituent);
1528         Id constituentType2 = getContainedTypeId(getTypeId(value2), constituent);
1529         Id constituent1 = createCompositeExtract(value1, constituentType1, indexes);
1530         Id constituent2 = createCompositeExtract(value2, constituentType2, indexes);
1531
1532         Id subResultId = createCompositeCompare(precision, constituent1, constituent2, equal);
1533
1534         if (constituent == 0)
1535             resultId = subResultId;
1536         else
1537             resultId = createBinOp(equal ? OpLogicalAnd : OpLogicalOr, boolType, resultId, subResultId);
1538     }
1539
1540     return resultId;
1541 }
1542
1543 // OpCompositeConstruct
1544 Id Builder::createCompositeConstruct(Id typeId, std::vector<Id>& constituents)
1545 {
1546     assert(isAggregateType(typeId) || (getNumTypeConstituents(typeId) > 1 && getNumTypeConstituents(typeId) == (int)constituents.size()));
1547
1548     Instruction* op = new Instruction(getUniqueId(), typeId, OpCompositeConstruct);
1549     for (int c = 0; c < (int)constituents.size(); ++c)
1550         op->addIdOperand(constituents[c]);
1551     buildPoint->addInstruction(std::unique_ptr<Instruction>(op));
1552
1553     return op->getResultId();
1554 }
1555
1556 // Vector or scalar constructor
1557 Id Builder::createConstructor(Decoration precision, const std::vector<Id>& sources, Id resultTypeId)
1558 {
1559     Id result = 0;
1560     unsigned int numTargetComponents = getNumTypeComponents(resultTypeId);
1561     unsigned int targetComponent = 0;
1562
1563     // Special case: when calling a vector constructor with a single scalar
1564     // argument, smear the scalar
1565     if (sources.size() == 1 && isScalar(sources[0]) && numTargetComponents > 1)
1566         return smearScalar(precision, sources[0], resultTypeId);
1567
1568     Id scalarTypeId = getScalarTypeId(resultTypeId);
1569     std::vector<Id> constituents;  // accumulate the arguments for OpCompositeConstruct
1570     for (unsigned int i = 0; i < sources.size(); ++i) {
1571         assert(! isAggregate(sources[i]));
1572         unsigned int sourceSize = getNumComponents(sources[i]);
1573         unsigned int sourcesToUse = sourceSize;
1574         if (sourcesToUse + targetComponent > numTargetComponents)
1575             sourcesToUse = numTargetComponents - targetComponent;
1576
1577         for (unsigned int s = 0; s < sourcesToUse; ++s) {
1578             Id arg = sources[i];
1579             if (sourceSize > 1) {
1580                 std::vector<unsigned> swiz;
1581                 swiz.push_back(s);
1582                 arg = createRvalueSwizzle(scalarTypeId, arg, swiz);
1583             }
1584
1585             if (numTargetComponents > 1)
1586                 constituents.push_back(arg);
1587             else
1588                 result = arg;
1589             ++targetComponent;
1590         }
1591
1592         if (targetComponent >= numTargetComponents)
1593             break;
1594     }
1595
1596     if (constituents.size() > 0)
1597         result = createCompositeConstruct(resultTypeId, constituents);
1598
1599     setPrecision(result, precision);
1600
1601     return result;
1602 }
1603
1604 // Comments in header
1605 Id Builder::createMatrixConstructor(Decoration precision, const std::vector<Id>& sources, Id resultTypeId)
1606 {
1607     Id componentTypeId = getScalarTypeId(resultTypeId);
1608     int numCols = getTypeNumColumns(resultTypeId);
1609     int numRows = getTypeNumRows(resultTypeId);
1610
1611     // Will use a two step process
1612     // 1. make a compile-time 2D array of values
1613     // 2. construct a matrix from that array
1614
1615     // Step 1.
1616
1617     // initialize the array to the identity matrix
1618     Id ids[maxMatrixSize][maxMatrixSize];
1619     Id  one = makeFloatConstant(1.0);
1620     Id zero = makeFloatConstant(0.0);
1621     for (int col = 0; col < 4; ++col) {
1622         for (int row = 0; row < 4; ++row) {
1623             if (col == row)
1624                 ids[col][row] = one;
1625             else
1626                 ids[col][row] = zero;
1627         }
1628     }
1629
1630     // modify components as dictated by the arguments
1631     if (sources.size() == 1 && isScalar(sources[0])) {
1632         // a single scalar; resets the diagonals
1633         for (int col = 0; col < 4; ++col)
1634             ids[col][col] = sources[0];
1635     } else if (isMatrix(sources[0])) {
1636         // constructing from another matrix; copy over the parts that exist in both the argument and constructee
1637         Id matrix = sources[0];
1638         int minCols = std::min(numCols, getNumColumns(matrix));
1639         int minRows = std::min(numRows, getNumRows(matrix));
1640         for (int col = 0; col < minCols; ++col) {
1641             std::vector<unsigned> indexes;
1642             indexes.push_back(col);
1643             for (int row = 0; row < minRows; ++row) {
1644                 indexes.push_back(row);
1645                 ids[col][row] = createCompositeExtract(matrix, componentTypeId, indexes);
1646                 indexes.pop_back();
1647                 setPrecision(ids[col][row], precision);
1648             }
1649         }
1650     } else {
1651         // fill in the matrix in column-major order with whatever argument components are available
1652         int row = 0;
1653         int col = 0;
1654
1655         for (int arg = 0; arg < (int)sources.size(); ++arg) {
1656             Id argComp = sources[arg];
1657             for (int comp = 0; comp < getNumComponents(sources[arg]); ++comp) {
1658                 if (getNumComponents(sources[arg]) > 1) {
1659                     argComp = createCompositeExtract(sources[arg], componentTypeId, comp);
1660                     setPrecision(argComp, precision);
1661                 }
1662                 ids[col][row++] = argComp;
1663                 if (row == numRows) {
1664                     row = 0;
1665                     col++;
1666                 }
1667             }
1668         }
1669     }
1670
1671
1672     // Step 2:  Construct a matrix from that array.
1673     // First make the column vectors, then make the matrix.
1674
1675     // make the column vectors
1676     Id columnTypeId = getContainedTypeId(resultTypeId);
1677     std::vector<Id> matrixColumns;
1678     for (int col = 0; col < numCols; ++col) {
1679         std::vector<Id> vectorComponents;
1680         for (int row = 0; row < numRows; ++row)
1681             vectorComponents.push_back(ids[col][row]);
1682         matrixColumns.push_back(createCompositeConstruct(columnTypeId, vectorComponents));
1683     }
1684
1685     // make the matrix
1686     return createCompositeConstruct(resultTypeId, matrixColumns);
1687 }
1688
1689 // Comments in header
1690 Builder::If::If(Id cond, Builder& gb) :
1691     builder(gb),
1692     condition(cond),
1693     elseBlock(0)
1694 {
1695     function = &builder.getBuildPoint()->getParent();
1696
1697     // make the blocks, but only put the then-block into the function,
1698     // the else-block and merge-block will be added later, in order, after
1699     // earlier code is emitted
1700     thenBlock = new Block(builder.getUniqueId(), *function);
1701     mergeBlock = new Block(builder.getUniqueId(), *function);
1702
1703     // Save the current block, so that we can add in the flow control split when
1704     // makeEndIf is called.
1705     headerBlock = builder.getBuildPoint();
1706
1707     function->addBlock(thenBlock);
1708     builder.setBuildPoint(thenBlock);
1709 }
1710
1711 // Comments in header
1712 void Builder::If::makeBeginElse()
1713 {
1714     // Close out the "then" by having it jump to the mergeBlock
1715     builder.createBranch(mergeBlock);
1716
1717     // Make the first else block and add it to the function
1718     elseBlock = new Block(builder.getUniqueId(), *function);
1719     function->addBlock(elseBlock);
1720
1721     // Start building the else block
1722     builder.setBuildPoint(elseBlock);
1723 }
1724
1725 // Comments in header
1726 void Builder::If::makeEndIf()
1727 {
1728     // jump to the merge block
1729     builder.createBranch(mergeBlock);
1730
1731     // Go back to the headerBlock and make the flow control split
1732     builder.setBuildPoint(headerBlock);
1733     builder.createSelectionMerge(mergeBlock, SelectionControlMaskNone);
1734     if (elseBlock)
1735         builder.createConditionalBranch(condition, thenBlock, elseBlock);
1736     else
1737         builder.createConditionalBranch(condition, thenBlock, mergeBlock);
1738
1739     // add the merge block to the function
1740     function->addBlock(mergeBlock);
1741     builder.setBuildPoint(mergeBlock);
1742 }
1743
1744 // Comments in header
1745 void Builder::makeSwitch(Id selector, int numSegments, std::vector<int>& caseValues, std::vector<int>& valueIndexToSegment, int defaultSegment,
1746                          std::vector<Block*>& segmentBlocks)
1747 {
1748     Function& function = buildPoint->getParent();
1749
1750     // make all the blocks
1751     for (int s = 0; s < numSegments; ++s)
1752         segmentBlocks.push_back(new Block(getUniqueId(), function));
1753
1754     Block* mergeBlock = new Block(getUniqueId(), function);
1755
1756     // make and insert the switch's selection-merge instruction
1757     createSelectionMerge(mergeBlock, SelectionControlMaskNone);
1758
1759     // make the switch instruction
1760     Instruction* switchInst = new Instruction(NoResult, NoType, OpSwitch);
1761     switchInst->addIdOperand(selector);
1762     switchInst->addIdOperand(defaultSegment >= 0 ? segmentBlocks[defaultSegment]->getId() : mergeBlock->getId());
1763     for (int i = 0; i < (int)caseValues.size(); ++i) {
1764         switchInst->addImmediateOperand(caseValues[i]);
1765         switchInst->addIdOperand(segmentBlocks[valueIndexToSegment[i]]->getId());
1766     }
1767     buildPoint->addInstruction(std::unique_ptr<Instruction>(switchInst));
1768
1769     // push the merge block
1770     switchMerges.push(mergeBlock);
1771 }
1772
1773 // Comments in header
1774 void Builder::addSwitchBreak()
1775 {
1776     // branch to the top of the merge block stack
1777     createBranch(switchMerges.top());
1778     createAndSetNoPredecessorBlock("post-switch-break");
1779 }
1780
1781 // Comments in header
1782 void Builder::nextSwitchSegment(std::vector<Block*>& segmentBlock, int nextSegment)
1783 {
1784     int lastSegment = nextSegment - 1;
1785     if (lastSegment >= 0) {
1786         // Close out previous segment by jumping, if necessary, to next segment
1787         if (! buildPoint->isTerminated())
1788             createBranch(segmentBlock[nextSegment]);
1789     }
1790     Block* block = segmentBlock[nextSegment];
1791     block->getParent().addBlock(block);
1792     setBuildPoint(block);
1793 }
1794
1795 // Comments in header
1796 void Builder::endSwitch(std::vector<Block*>& /*segmentBlock*/)
1797 {
1798     // Close out previous segment by jumping, if necessary, to next segment
1799     if (! buildPoint->isTerminated())
1800         addSwitchBreak();
1801
1802     switchMerges.top()->getParent().addBlock(switchMerges.top());
1803     setBuildPoint(switchMerges.top());
1804
1805     switchMerges.pop();
1806 }
1807
1808 // Comments in header
1809 void Builder::makeNewLoop(bool loopTestFirst)
1810 {
1811     loops.push(Loop(*this, loopTestFirst));
1812     const Loop& loop = loops.top();
1813
1814     // The loop test is always emitted before the loop body.
1815     // But if the loop test executes at the bottom of the loop, then
1816     // execute the test only on the second and subsequent iterations.
1817
1818     // Remember the block that branches to the loop header.  This
1819     // is required for the test-after-body case.
1820     Block* preheader = getBuildPoint();
1821
1822     // Branch into the loop
1823     createBranch(loop.header);
1824
1825     // Set ourselves inside the loop
1826     loop.function->addBlock(loop.header);
1827     setBuildPoint(loop.header);
1828
1829     if (!loopTestFirst) {
1830         // Generate code to defer the loop test until the second and
1831         // subsequent iterations.
1832
1833         // It's always the first iteration when coming from the preheader.
1834         // All other branches to this loop header will need to indicate "false",
1835         // but we don't yet know where they will come from.
1836         loop.isFirstIteration->addIdOperand(makeBoolConstant(true));
1837         loop.isFirstIteration->addIdOperand(preheader->getId());
1838         getBuildPoint()->addInstruction(std::unique_ptr<Instruction>(loop.isFirstIteration));
1839
1840         // Mark the end of the structured loop. This must exist in the loop header block.
1841         createLoopMerge(loop.merge, loop.header, LoopControlMaskNone);
1842
1843         // Generate code to see if this is the first iteration of the loop.
1844         // It needs to be in its own block, since the loop merge and
1845         // the selection merge instructions can't both be in the same
1846         // (header) block.
1847         Block* firstIterationCheck = new Block(getUniqueId(), *loop.function);
1848         createBranch(firstIterationCheck);
1849         loop.function->addBlock(firstIterationCheck);
1850         setBuildPoint(firstIterationCheck);
1851
1852         // Control flow after this "if" normally reconverges at the loop body.
1853         // However, the loop test has a "break branch" out of this selection
1854         // construct because it can transfer control to the loop merge block.
1855         createSelectionMerge(loop.body, SelectionControlMaskNone);
1856
1857         Block* loopTest = new Block(getUniqueId(), *loop.function);
1858         createConditionalBranch(loop.isFirstIteration->getResultId(), loop.body, loopTest);
1859
1860         loop.function->addBlock(loopTest);
1861         setBuildPoint(loopTest);
1862     }
1863 }
1864
1865 void Builder::createLoopTestBranch(Id condition)
1866 {
1867     const Loop& loop = loops.top();
1868
1869     // Generate the merge instruction. If the loop test executes before
1870     // the body, then this is a loop merge.  Otherwise the loop merge
1871     // has already been generated and this is a conditional merge.
1872     if (loop.testFirst) {
1873         createLoopMerge(loop.merge, loop.header, LoopControlMaskNone);
1874         // Branching to the "body" block will keep control inside
1875         // the loop.
1876         createConditionalBranch(condition, loop.body, loop.merge);
1877         loop.function->addBlock(loop.body);
1878         setBuildPoint(loop.body);
1879     } else {
1880         // The branch to the loop merge block is the allowed exception
1881         // to the structured control flow.  Otherwise, control flow will
1882         // continue to loop.body block.  Since that is already the target
1883         // of a merge instruction, and a block can't be the target of more
1884         // than one merge instruction, we need to make an intermediate block.
1885         Block* stayInLoopBlock = new Block(getUniqueId(), *loop.function);
1886         createSelectionMerge(stayInLoopBlock, SelectionControlMaskNone);
1887
1888         // This is the loop test.
1889         createConditionalBranch(condition, stayInLoopBlock, loop.merge);
1890
1891         // The dummy block just branches to the real loop body.
1892         loop.function->addBlock(stayInLoopBlock);
1893         setBuildPoint(stayInLoopBlock);
1894         createBranchToBody();
1895     }
1896 }
1897
1898 void Builder::createBranchToBody()
1899 {
1900     const Loop& loop = loops.top();
1901     assert(loop.body);
1902
1903     // This is a reconvergence of control flow, so no merge instruction
1904     // is required.
1905     createBranch(loop.body);
1906     loop.function->addBlock(loop.body);
1907     setBuildPoint(loop.body);
1908 }
1909
1910 void Builder::createLoopContinue()
1911 {
1912     createBranchToLoopHeaderFromInside(loops.top());
1913     // Set up a block for dead code.
1914     createAndSetNoPredecessorBlock("post-loop-continue");
1915 }
1916
1917 // Add an exit (e.g. "break") for the innermost loop that you're in
1918 void Builder::createLoopExit()
1919 {
1920     createBranch(loops.top().merge);
1921     // Set up a block for dead code.
1922     createAndSetNoPredecessorBlock("post-loop-break");
1923 }
1924
1925 // Close the innermost loop
1926 void Builder::closeLoop()
1927 {
1928     const Loop& loop = loops.top();
1929
1930     // Branch back to the top
1931     createBranchToLoopHeaderFromInside(loop);
1932
1933     // Add the merge block and set the build point to it
1934     loop.function->addBlock(loop.merge);
1935     setBuildPoint(loop.merge);
1936
1937     loops.pop();
1938 }
1939
1940 // Create a branch to the header of the given loop, from inside
1941 // the loop body.
1942 // Adjusts the phi node for the first-iteration value if needeed.
1943 void Builder::createBranchToLoopHeaderFromInside(const Loop& loop)
1944 {
1945     createBranch(loop.header);
1946     if (loop.isFirstIteration) {
1947         loop.isFirstIteration->addIdOperand(makeBoolConstant(false));
1948         loop.isFirstIteration->addIdOperand(getBuildPoint()->getId());
1949     }
1950 }
1951
1952 void Builder::clearAccessChain()
1953 {
1954     accessChain.base = NoResult;
1955     accessChain.indexChain.clear();
1956     accessChain.instr = NoResult;
1957     accessChain.swizzle.clear();
1958     accessChain.component = NoResult;
1959     accessChain.preSwizzleBaseType = NoType;
1960     accessChain.isRValue = false;
1961 }
1962
1963 // Comments in header
1964 void Builder::accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizzleBaseType)
1965 {
1966     // swizzles can be stacked in GLSL, but simplified to a single
1967     // one here; the base type doesn't change
1968     if (accessChain.preSwizzleBaseType == NoType)
1969         accessChain.preSwizzleBaseType = preSwizzleBaseType;
1970
1971     // if needed, propagate the swizzle for the current access chain
1972     if (accessChain.swizzle.size()) {
1973         std::vector<unsigned> oldSwizzle = accessChain.swizzle;
1974         accessChain.swizzle.resize(0);
1975         for (unsigned int i = 0; i < swizzle.size(); ++i) {
1976             accessChain.swizzle.push_back(oldSwizzle[swizzle[i]]);
1977         }
1978     } else
1979         accessChain.swizzle = swizzle;
1980
1981     // determine if we need to track this swizzle anymore
1982     simplifyAccessChainSwizzle();
1983 }
1984
1985 // Comments in header
1986 void Builder::accessChainStore(Id rvalue)
1987 {
1988     assert(accessChain.isRValue == false);
1989
1990     transferAccessChainSwizzle(true);
1991     Id base = collapseAccessChain();
1992
1993     if (accessChain.swizzle.size() && accessChain.component != NoResult)
1994         MissingFunctionality("simultaneous l-value swizzle and dynamic component selection");
1995
1996     // If swizzle still exists, it is out-of-order or not full, we must load the target vector,
1997     // extract and insert elements to perform writeMask and/or swizzle.
1998     Id source = NoResult;
1999     if (accessChain.swizzle.size()) {
2000         Id tempBaseId = createLoad(base);
2001         source = createLvalueSwizzle(getTypeId(tempBaseId), tempBaseId, rvalue, accessChain.swizzle);
2002     }
2003
2004     // dynamic component selection
2005     if (accessChain.component != NoResult) {
2006         Id tempBaseId = (source == NoResult) ? createLoad(base) : source;
2007         source = createVectorInsertDynamic(tempBaseId, getTypeId(tempBaseId), rvalue, accessChain.component);
2008     }
2009
2010     if (source == NoResult)
2011         source = rvalue;
2012
2013     createStore(source, base);
2014 }
2015
2016 // Comments in header
2017 Id Builder::accessChainLoad(Id resultType)
2018 {
2019     Id id;
2020
2021     if (accessChain.isRValue) {
2022         // transfer access chain, but keep it static, so we can stay in registers
2023         transferAccessChainSwizzle(false);
2024         if (accessChain.indexChain.size() > 0) {
2025             Id swizzleBase = accessChain.preSwizzleBaseType != NoType ? accessChain.preSwizzleBaseType : resultType;
2026         
2027             // if all the accesses are constants, we can use OpCompositeExtract
2028             std::vector<unsigned> indexes;
2029             bool constant = true;
2030             for (int i = 0; i < (int)accessChain.indexChain.size(); ++i) {
2031                 if (isConstantScalar(accessChain.indexChain[i]))
2032                     indexes.push_back(getConstantScalar(accessChain.indexChain[i]));
2033                 else {
2034                     constant = false;
2035                     break;
2036                 }
2037             }
2038
2039             if (constant)
2040                 id = createCompositeExtract(accessChain.base, swizzleBase, indexes);
2041             else {
2042                 // make a new function variable for this r-value
2043                 Id lValue = createVariable(StorageClassFunction, getTypeId(accessChain.base), "indexable");
2044
2045                 // store into it
2046                 createStore(accessChain.base, lValue);
2047
2048                 // move base to the new variable
2049                 accessChain.base = lValue;
2050                 accessChain.isRValue = false;
2051
2052                 // load through the access chain
2053                 id = createLoad(collapseAccessChain());
2054             }
2055         } else
2056             id = accessChain.base;
2057     } else {
2058         transferAccessChainSwizzle(true);
2059         // load through the access chain
2060         id = createLoad(collapseAccessChain());
2061     }
2062
2063     // Done, unless there are swizzles to do
2064     if (accessChain.swizzle.size() == 0 && accessChain.component == NoResult)
2065         return id;
2066
2067     // Do remaining swizzling
2068     // First, static swizzling
2069     if (accessChain.swizzle.size()) {
2070         // static swizzle
2071         Id swizzledType = getScalarTypeId(getTypeId(id));
2072         if (accessChain.swizzle.size() > 1)
2073             swizzledType = makeVectorType(swizzledType, (int)accessChain.swizzle.size());
2074         id = createRvalueSwizzle(swizzledType, id, accessChain.swizzle);
2075     }
2076
2077     // dynamic single-component selection
2078     if (accessChain.component != NoResult)
2079         id = createVectorExtractDynamic(id, resultType, accessChain.component);
2080
2081     return id;
2082 }
2083
2084 Id Builder::accessChainGetLValue()
2085 {
2086     assert(accessChain.isRValue == false);
2087
2088     transferAccessChainSwizzle(true);
2089     Id lvalue = collapseAccessChain();
2090
2091     // If swizzle exists, it is out-of-order or not full, we must load the target vector,
2092     // extract and insert elements to perform writeMask and/or swizzle.  This does not
2093     // go with getting a direct l-value pointer.
2094     assert(accessChain.swizzle.size() == 0);
2095     assert(accessChain.component == NoResult);
2096
2097     return lvalue;
2098 }
2099
2100 void Builder::dump(std::vector<unsigned int>& out) const
2101 {
2102     // Header, before first instructions:
2103     out.push_back(MagicNumber);
2104     out.push_back(Version);
2105     out.push_back(builderNumber);
2106     out.push_back(uniqueId + 1);
2107     out.push_back(0);
2108
2109     // Capabilities
2110     for (auto cap : capabilities) {
2111         Instruction capInst(0, 0, OpCapability);
2112         capInst.addImmediateOperand(cap);
2113         capInst.dump(out);
2114     }
2115
2116     // TBD: OpExtension ...
2117
2118     dumpInstructions(out, imports);
2119     Instruction memInst(0, 0, OpMemoryModel);
2120     memInst.addImmediateOperand(addressModel);
2121     memInst.addImmediateOperand(memoryModel);
2122     memInst.dump(out);
2123
2124     // Instructions saved up while building:
2125     dumpInstructions(out, entryPoints);
2126     dumpInstructions(out, executionModes);
2127
2128     // Debug instructions
2129     if (source != SourceLanguageUnknown) {
2130         Instruction sourceInst(0, 0, OpSource);
2131         sourceInst.addImmediateOperand(source);
2132         sourceInst.addImmediateOperand(sourceVersion);
2133         sourceInst.dump(out);
2134     }
2135     for (int e = 0; e < (int)extensions.size(); ++e) {
2136         Instruction extInst(0, 0, OpSourceExtension);
2137         extInst.addStringOperand(extensions[e]);
2138         extInst.dump(out);
2139     }
2140     dumpInstructions(out, names);
2141     dumpInstructions(out, lines);
2142
2143     // Annotation instructions
2144     dumpInstructions(out, decorations);
2145
2146     dumpInstructions(out, constantsTypesGlobals);
2147     dumpInstructions(out, externals);
2148
2149     // The functions
2150     module.dump(out);
2151 }
2152
2153 //
2154 // Protected methods.
2155 //
2156
2157 // Turn the described access chain in 'accessChain' into an instruction
2158 // computing its address.  This *cannot* include complex swizzles, which must
2159 // be handled after this is called, but it does include swizzles that select
2160 // an individual element, as a single address of a scalar type can be
2161 // computed by an OpAccessChain instruction.
2162 Id Builder::collapseAccessChain()
2163 {
2164     assert(accessChain.isRValue == false);
2165
2166     if (accessChain.indexChain.size() > 0) {
2167         if (accessChain.instr == 0) {
2168             StorageClass storageClass = (StorageClass)module.getStorageClass(getTypeId(accessChain.base));
2169             accessChain.instr = createAccessChain(storageClass, accessChain.base, accessChain.indexChain);
2170         }
2171
2172         return accessChain.instr;
2173     } else
2174         return accessChain.base;
2175
2176     // note that non-trivial swizzling is left pending...
2177 }
2178
2179 // clear out swizzle if it is redundant, that is reselecting the same components
2180 // that would be present without the swizzle.
2181 void Builder::simplifyAccessChainSwizzle()
2182 {
2183     // If the swizzle has fewer components than the vector, it is subsetting, and must stay
2184     // to preserve that fact.
2185     if (getNumTypeComponents(accessChain.preSwizzleBaseType) > (int)accessChain.swizzle.size())
2186         return;
2187
2188     // if components are out of order, it is a swizzle
2189     for (unsigned int i = 0; i < accessChain.swizzle.size(); ++i) {
2190         if (i != accessChain.swizzle[i])
2191             return;
2192     }
2193
2194     // otherwise, there is no need to track this swizzle
2195     accessChain.swizzle.clear();
2196     if (accessChain.component == NoResult)
2197         accessChain.preSwizzleBaseType = NoType;
2198 }
2199
2200 // To the extent any swizzling can become part of the chain
2201 // of accesses instead of a post operation, make it so.
2202 // If 'dynamic' is true, include transfering a non-static component index,
2203 // otherwise, only transfer static indexes.
2204 //
2205 // Also, Boolean vectors are likely to be special.  While
2206 // for external storage, they should only be integer types,
2207 // function-local bool vectors could use sub-word indexing,
2208 // so keep that as a separate Insert/Extract on a loaded vector.
2209 void Builder::transferAccessChainSwizzle(bool dynamic)
2210 {
2211     // too complex?
2212     if (accessChain.swizzle.size() > 1)
2213         return;
2214
2215     // non existent?
2216     if (accessChain.swizzle.size() == 0 && accessChain.component == NoResult)
2217         return;
2218
2219     // single component...
2220
2221     // skip doing it for Boolean vectors
2222     if (isBoolType(getContainedTypeId(accessChain.preSwizzleBaseType)))
2223         return;
2224
2225     if (accessChain.swizzle.size() == 1) {
2226         // handle static component
2227         accessChain.indexChain.push_back(makeUintConstant(accessChain.swizzle.front()));
2228         accessChain.swizzle.clear();
2229         // note, the only valid remaining dynamic access would be to this one
2230         // component, so don't bother even looking at accessChain.component
2231         accessChain.preSwizzleBaseType = NoType;
2232         accessChain.component = NoResult;
2233     } else if (dynamic && accessChain.component != NoResult) {
2234         // handle dynamic component
2235         accessChain.indexChain.push_back(accessChain.component);
2236         accessChain.preSwizzleBaseType = NoType;
2237         accessChain.component = NoResult;
2238     }
2239 }
2240
2241 // Utility method for creating a new block and setting the insert point to
2242 // be in it. This is useful for flow-control operations that need a "dummy"
2243 // block proceeding them (e.g. instructions after a discard, etc).
2244 void Builder::createAndSetNoPredecessorBlock(const char* /*name*/)
2245 {
2246     Block* block = new Block(getUniqueId(), buildPoint->getParent());
2247     block->setUnreachable();
2248     buildPoint->getParent().addBlock(block);
2249     setBuildPoint(block);
2250
2251     //if (name)
2252     //    addName(block->getId(), name);
2253 }
2254
2255 // Comments in header
2256 void Builder::createBranch(Block* block)
2257 {
2258     Instruction* branch = new Instruction(OpBranch);
2259     branch->addIdOperand(block->getId());
2260     buildPoint->addInstruction(std::unique_ptr<Instruction>(branch));
2261     block->addPredecessor(buildPoint);
2262 }
2263
2264 void Builder::createSelectionMerge(Block* mergeBlock, unsigned int control)
2265 {
2266     Instruction* merge = new Instruction(OpSelectionMerge);
2267     merge->addIdOperand(mergeBlock->getId());
2268     merge->addImmediateOperand(control);
2269     buildPoint->addInstruction(std::unique_ptr<Instruction>(merge));
2270 }
2271
2272 void Builder::createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control)
2273 {
2274     Instruction* merge = new Instruction(OpLoopMerge);
2275     merge->addIdOperand(mergeBlock->getId());
2276     merge->addIdOperand(continueBlock->getId());
2277     merge->addImmediateOperand(control);
2278     buildPoint->addInstruction(std::unique_ptr<Instruction>(merge));
2279 }
2280
2281 void Builder::createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock)
2282 {
2283     Instruction* branch = new Instruction(OpBranchConditional);
2284     branch->addIdOperand(condition);
2285     branch->addIdOperand(thenBlock->getId());
2286     branch->addIdOperand(elseBlock->getId());
2287     buildPoint->addInstruction(std::unique_ptr<Instruction>(branch));
2288     thenBlock->addPredecessor(buildPoint);
2289     elseBlock->addPredecessor(buildPoint);
2290 }
2291
2292 void Builder::dumpInstructions(std::vector<unsigned int>& out, const std::vector<std::unique_ptr<Instruction> >& instructions) const
2293 {
2294     for (int i = 0; i < (int)instructions.size(); ++i) {
2295         instructions[i]->dump(out);
2296     }
2297 }
2298
2299 void TbdFunctionality(const char* tbd)
2300 {
2301     static std::unordered_set<const char*> issued;
2302
2303     if (issued.find(tbd) == issued.end()) {
2304         printf("TBD functionality: %s\n", tbd);
2305         issued.insert(tbd);
2306     }
2307 }
2308
2309 void MissingFunctionality(const char* fun)
2310 {
2311     printf("Missing functionality: %s\n", fun);
2312 }
2313
2314 Builder::Loop::Loop(Builder& builder, bool testFirstArg)
2315   : function(&builder.getBuildPoint()->getParent()),
2316     header(new Block(builder.getUniqueId(), *function)),
2317     merge(new Block(builder.getUniqueId(), *function)),
2318     body(new Block(builder.getUniqueId(), *function)),
2319     testFirst(testFirstArg),
2320     isFirstIteration(nullptr)
2321 {
2322     if (!testFirst)
2323     {
2324 // You may be tempted to rewrite this as
2325 // new Instruction(builder.getUniqueId(), builder.makeBoolType(), OpPhi);
2326 // This will cause subtle test failures because builder.getUniqueId(),
2327 // and builder.makeBoolType() can then get run in a compiler-specific
2328 // order making tests fail for certain configurations.
2329         Id instructionId = builder.getUniqueId();
2330         isFirstIteration = new Instruction(instructionId, builder.makeBoolType(), OpPhi);
2331     }
2332 }
2333
2334 }; // end spv namespace