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// "Builder" is an interface to fully build SPIR-V IR.   Allocate one of
38// these to build (a thread safe) internal SPIR-V representation (IR),
39// and then dump it as a binary stream according to the SPIR-V specification.
40//
41// A Builder has a 1:1 relationship with a SPIR-V module.
42//
43
44#pragma once
45#ifndef SpvBuilder_H
46#define SpvBuilder_H
47
48#include "Logger.h"
49#include "spirv.hpp"
50#include "spvIR.h"
51
52#include <algorithm>
53#include <map>
54#include <memory>
55#include <set>
56#include <sstream>
57#include <stack>
58
59namespace spv {
60
61class Builder {
62public:
63    Builder(unsigned int userNumber, SpvBuildLogger* logger);
64    virtual ~Builder();
65
66    static const int maxMatrixSize = 4;
67
68    void setSource(spv::SourceLanguage lang, int version)
69    {
70        source = lang;
71        sourceVersion = version;
72    }
73    void addSourceExtension(const char* ext) { extensions.push_back(ext); }
74    Id import(const char*);
75    void setMemoryModel(spv::AddressingModel addr, spv::MemoryModel mem)
76    {
77        addressModel = addr;
78        memoryModel = mem;
79    }
80
81    void addCapability(spv::Capability cap) { capabilities.insert(cap); }
82
83    // To get a new <id> for anything needing a new one.
84    Id getUniqueId() { return ++uniqueId; }
85
86    // To get a set of new <id>s, e.g., for a set of function parameters
87    Id getUniqueIds(int numIds)
88    {
89        Id id = uniqueId + 1;
90        uniqueId += numIds;
91        return id;
92    }
93
94    // For creating new types (will return old type if the requested one was already made).
95    Id makeVoidType();
96    Id makeBoolType();
97    Id makePointer(StorageClass, Id type);
98    Id makeIntegerType(int width, bool hasSign);   // generic
99    Id makeIntType(int width) { return makeIntegerType(width, true); }
100    Id makeUintType(int width) { return makeIntegerType(width, false); }
101    Id makeFloatType(int width);
102    Id makeStructType(const std::vector<Id>& members, const char*);
103    Id makeStructResultType(Id type0, Id type1);
104    Id makeVectorType(Id component, int size);
105    Id makeMatrixType(Id component, int cols, int rows);
106    Id makeArrayType(Id element, Id sizeId, int stride);  // 0 stride means no stride decoration
107    Id makeRuntimeArray(Id element);
108    Id makeFunctionType(Id returnType, const std::vector<Id>& paramTypes);
109    Id makeImageType(Id sampledType, Dim, bool depth, bool arrayed, bool ms, unsigned sampled, ImageFormat format);
110    Id makeSamplerType();
111    Id makeSampledImageType(Id imageType);
112
113    // For querying about types.
114    Id getTypeId(Id resultId) const { return module.getTypeId(resultId); }
115    Id getDerefTypeId(Id resultId) const;
116    Op getOpCode(Id id) const { return module.getInstruction(id)->getOpCode(); }
117    Op getTypeClass(Id typeId) const { return getOpCode(typeId); }
118    Op getMostBasicTypeClass(Id typeId) const;
119    int getNumComponents(Id resultId) const { return getNumTypeComponents(getTypeId(resultId)); }
120    int getNumTypeConstituents(Id typeId) const;
121    int getNumTypeComponents(Id typeId) const { return getNumTypeConstituents(typeId); }
122    Id getScalarTypeId(Id typeId) const;
123    Id getContainedTypeId(Id typeId) const;
124    Id getContainedTypeId(Id typeId, int) const;
125    StorageClass getTypeStorageClass(Id typeId) const { return module.getStorageClass(typeId); }
126    ImageFormat getImageTypeFormat(Id typeId) const { return (ImageFormat)module.getInstruction(typeId)->getImmediateOperand(6); }
127
128    bool isPointer(Id resultId)      const { return isPointerType(getTypeId(resultId)); }
129    bool isScalar(Id resultId)       const { return isScalarType(getTypeId(resultId)); }
130    bool isVector(Id resultId)       const { return isVectorType(getTypeId(resultId)); }
131    bool isMatrix(Id resultId)       const { return isMatrixType(getTypeId(resultId)); }
132    bool isAggregate(Id resultId)    const { return isAggregateType(getTypeId(resultId)); }
133    bool isSampledImage(Id resultId) const { return isSampledImageType(getTypeId(resultId)); }
134
135    bool isBoolType(Id typeId)         const { return groupedTypes[OpTypeBool].size() > 0 && typeId == groupedTypes[OpTypeBool].back()->getResultId(); }
136    bool isPointerType(Id typeId)      const { return getTypeClass(typeId) == OpTypePointer; }
137    bool isScalarType(Id typeId)       const { return getTypeClass(typeId) == OpTypeFloat  || getTypeClass(typeId) == OpTypeInt || getTypeClass(typeId) == OpTypeBool; }
138    bool isVectorType(Id typeId)       const { return getTypeClass(typeId) == OpTypeVector; }
139    bool isMatrixType(Id typeId)       const { return getTypeClass(typeId) == OpTypeMatrix; }
140    bool isStructType(Id typeId)       const { return getTypeClass(typeId) == OpTypeStruct; }
141    bool isArrayType(Id typeId)        const { return getTypeClass(typeId) == OpTypeArray; }
142    bool isAggregateType(Id typeId)    const { return isArrayType(typeId) || isStructType(typeId); }
143    bool isImageType(Id typeId)        const { return getTypeClass(typeId) == OpTypeImage; }
144    bool isSamplerType(Id typeId)      const { return getTypeClass(typeId) == OpTypeSampler; }
145    bool isSampledImageType(Id typeId) const { return getTypeClass(typeId) == OpTypeSampledImage; }
146
147    bool isConstantOpCode(Op opcode) const;
148    bool isSpecConstantOpCode(Op opcode) const;
149    bool isConstant(Id resultId) const { return isConstantOpCode(getOpCode(resultId)); }
150    bool isConstantScalar(Id resultId) const { return getOpCode(resultId) == OpConstant; }
151    bool isSpecConstant(Id resultId) const { return isSpecConstantOpCode(getOpCode(resultId)); }
152    unsigned int getConstantScalar(Id resultId) const { return module.getInstruction(resultId)->getImmediateOperand(0); }
153    StorageClass getStorageClass(Id resultId) const { return getTypeStorageClass(getTypeId(resultId)); }
154
155    int getTypeNumColumns(Id typeId) const
156    {
157        assert(isMatrixType(typeId));
158        return getNumTypeConstituents(typeId);
159    }
160    int getNumColumns(Id resultId) const { return getTypeNumColumns(getTypeId(resultId)); }
161    int getTypeNumRows(Id typeId) const
162    {
163        assert(isMatrixType(typeId));
164        return getNumTypeComponents(getContainedTypeId(typeId));
165    }
166    int getNumRows(Id resultId) const { return getTypeNumRows(getTypeId(resultId)); }
167
168    Dim getTypeDimensionality(Id typeId) const
169    {
170        assert(isImageType(typeId));
171        return (Dim)module.getInstruction(typeId)->getImmediateOperand(1);
172    }
173    Id getImageType(Id resultId) const
174    {
175        Id typeId = getTypeId(resultId);
176        assert(isImageType(typeId) || isSampledImageType(typeId));
177        return isSampledImageType(typeId) ? module.getInstruction(typeId)->getIdOperand(0) : typeId;
178    }
179    bool isArrayedImageType(Id typeId) const
180    {
181        assert(isImageType(typeId));
182        return module.getInstruction(typeId)->getImmediateOperand(3) != 0;
183    }
184
185    // For making new constants (will return old constant if the requested one was already made).
186    Id makeBoolConstant(bool b, bool specConstant = false);
187    Id makeIntConstant(int i, bool specConstant = false)         { return makeIntConstant(makeIntType(32),  (unsigned)i, specConstant); }
188    Id makeUintConstant(unsigned u, bool specConstant = false)   { return makeIntConstant(makeUintType(32),           u, specConstant); }
189    Id makeInt64Constant(long long i, bool specConstant = false)            { return makeInt64Constant(makeIntType(64),  (unsigned long long)i, specConstant); }
190    Id makeUint64Constant(unsigned long long u, bool specConstant = false)  { return makeInt64Constant(makeUintType(64),                     u, specConstant); }
191    Id makeFloatConstant(float f, bool specConstant = false);
192    Id makeDoubleConstant(double d, bool specConstant = false);
193
194    // Turn the array of constants into a proper spv constant of the requested type.
195    Id makeCompositeConstant(Id type, std::vector<Id>& comps, bool specConst = false);
196
197    // Methods for adding information outside the CFG.
198    Instruction* addEntryPoint(ExecutionModel, Function*, const char* name);
199    void addExecutionMode(Function*, ExecutionMode mode, int value1 = -1, int value2 = -1, int value3 = -1);
200    void addName(Id, const char* name);
201    void addMemberName(Id, int member, const char* name);
202    void addLine(Id target, Id fileName, int line, int column);
203    void addDecoration(Id, Decoration, int num = -1);
204    void addMemberDecoration(Id, unsigned int member, Decoration, int num = -1);
205
206    // At the end of what block do the next create*() instructions go?
207    void setBuildPoint(Block* bp) { buildPoint = bp; }
208    Block* getBuildPoint() const { return buildPoint; }
209
210    // Make the entry-point function. The returned pointer is only valid
211    // for the lifetime of this builder.
212    Function* makeEntrypoint(const char*);
213
214    // Make a shader-style function, and create its entry block if entry is non-zero.
215    // Return the function, pass back the entry.
216    // The returned pointer is only valid for the lifetime of this builder.
217    Function* makeFunctionEntry(Decoration precision, Id returnType, const char* name, const std::vector<Id>& paramTypes,
218                                const std::vector<Decoration>& precisions, Block **entry = 0);
219
220    // Create a return. An 'implicit' return is one not appearing in the source
221    // code.  In the case of an implicit return, no post-return block is inserted.
222    void makeReturn(bool implicit, Id retVal = 0);
223
224    // Generate all the code needed to finish up a function.
225    void leaveFunction();
226
227    // Create a discard.
228    void makeDiscard();
229
230    // Create a global or function local or IO variable.
231    Id createVariable(StorageClass, Id type, const char* name = 0);
232
233    // Create an intermediate with an undefined value.
234    Id createUndefined(Id type);
235
236    // Store into an Id and return the l-value
237    void createStore(Id rValue, Id lValue);
238
239    // Load from an Id and return it
240    Id createLoad(Id lValue);
241
242    // Create an OpAccessChain instruction
243    Id createAccessChain(StorageClass, Id base, std::vector<Id>& offsets);
244
245    // Create an OpArrayLength instruction
246    Id createArrayLength(Id base, unsigned int member);
247
248    // Create an OpCompositeExtract instruction
249    Id createCompositeExtract(Id composite, Id typeId, unsigned index);
250    Id createCompositeExtract(Id composite, Id typeId, std::vector<unsigned>& indexes);
251    Id createCompositeInsert(Id object, Id composite, Id typeId, unsigned index);
252    Id createCompositeInsert(Id object, Id composite, Id typeId, std::vector<unsigned>& indexes);
253
254    Id createVectorExtractDynamic(Id vector, Id typeId, Id componentIndex);
255    Id createVectorInsertDynamic(Id vector, Id typeId, Id component, Id componentIndex);
256
257    void createNoResultOp(Op);
258    void createNoResultOp(Op, Id operand);
259    void createNoResultOp(Op, const std::vector<Id>& operands);
260    void createControlBarrier(Scope execution, Scope memory, MemorySemanticsMask);
261    void createMemoryBarrier(unsigned executionScope, unsigned memorySemantics);
262    Id createUnaryOp(Op, Id typeId, Id operand);
263    Id createBinOp(Op, Id typeId, Id operand1, Id operand2);
264    Id createTriOp(Op, Id typeId, Id operand1, Id operand2, Id operand3);
265    Id createOp(Op, Id typeId, const std::vector<Id>& operands);
266    Id createFunctionCall(spv::Function*, std::vector<spv::Id>&);
267    Id createSpecConstantOp(Op, Id typeId, const std::vector<spv::Id>& operands, const std::vector<unsigned>& literals);
268
269    // Take an rvalue (source) and a set of channels to extract from it to
270    // make a new rvalue, which is returned.
271    Id createRvalueSwizzle(Decoration precision, Id typeId, Id source, std::vector<unsigned>& channels);
272
273    // Take a copy of an lvalue (target) and a source of components, and set the
274    // source components into the lvalue where the 'channels' say to put them.
275    // An updated version of the target is returned.
276    // (No true lvalue or stores are used.)
277    Id createLvalueSwizzle(Id typeId, Id target, Id source, std::vector<unsigned>& channels);
278
279    // If both the id and precision are valid, the id
280    // gets tagged with the requested precision.
281    // The passed in id is always the returned id, to simplify use patterns.
282    Id setPrecision(Id id, Decoration precision)
283    {
284        if (precision != NoPrecision && id != NoResult)
285            addDecoration(id, precision);
286
287        return id;
288    }
289
290    // Can smear a scalar to a vector for the following forms:
291    //   - promoteScalar(scalar, vector)  // smear scalar to width of vector
292    //   - promoteScalar(vector, scalar)  // smear scalar to width of vector
293    //   - promoteScalar(pointer, scalar) // smear scalar to width of what pointer points to
294    //   - promoteScalar(scalar, scalar)  // do nothing
295    // Other forms are not allowed.
296    //
297    // Generally, the type of 'scalar' does not need to be the same type as the components in 'vector'.
298    // The type of the created vector is a vector of components of the same type as the scalar.
299    //
300    // Note: One of the arguments will change, with the result coming back that way rather than
301    // through the return value.
302    void promoteScalar(Decoration precision, Id& left, Id& right);
303
304    // Make a value by smearing the scalar to fill the type.
305    // vectorType should be the correct type for making a vector of scalarVal.
306    // (No conversions are done.)
307    Id smearScalar(Decoration precision, Id scalarVal, Id vectorType);
308
309    // Create a call to a built-in function.
310    Id createBuiltinCall(Id resultType, Id builtins, int entryPoint, std::vector<Id>& args);
311
312    // List of parameters used to create a texture operation
313    struct TextureParameters {
314        Id sampler;
315        Id coords;
316        Id bias;
317        Id lod;
318        Id Dref;
319        Id offset;
320        Id offsets;
321        Id gradX;
322        Id gradY;
323        Id sample;
324        Id component;
325        Id texelOut;
326        Id lodClamp;
327    };
328
329    // Select the correct texture operation based on all inputs, and emit the correct instruction
330    Id createTextureCall(Decoration precision, Id resultType, bool sparse, bool fetch, bool proj, bool gather, bool noImplicit, const TextureParameters&);
331
332    // Emit the OpTextureQuery* instruction that was passed in.
333    // Figure out the right return value and type, and return it.
334    Id createTextureQueryCall(Op, const TextureParameters&);
335
336    Id createSamplePositionCall(Decoration precision, Id, Id);
337
338    Id createBitFieldExtractCall(Decoration precision, Id, Id, Id, bool isSigned);
339    Id createBitFieldInsertCall(Decoration precision, Id, Id, Id, Id);
340
341    // Reduction comparison for composites:  For equal and not-equal resulting in a scalar.
342    Id createCompositeCompare(Decoration precision, Id, Id, bool /* true if for equal, false if for not-equal */);
343
344    // OpCompositeConstruct
345    Id createCompositeConstruct(Id typeId, std::vector<Id>& constituents);
346
347    // vector or scalar constructor
348    Id createConstructor(Decoration precision, const std::vector<Id>& sources, Id resultTypeId);
349
350    // matrix constructor
351    Id createMatrixConstructor(Decoration precision, const std::vector<Id>& sources, Id constructee);
352
353    // Helper to use for building nested control flow with if-then-else.
354    class If {
355    public:
356        If(Id condition, Builder& builder);
357        ~If() {}
358
359        void makeBeginElse();
360        void makeEndIf();
361
362    private:
363        If(const If&);
364        If& operator=(If&);
365
366        Builder& builder;
367        Id condition;
368        Function* function;
369        Block* headerBlock;
370        Block* thenBlock;
371        Block* elseBlock;
372        Block* mergeBlock;
373    };
374
375    // Make a switch statement.  A switch has 'numSegments' of pieces of code, not containing
376    // any case/default labels, all separated by one or more case/default labels.  Each possible
377    // case value v is a jump to the caseValues[v] segment.  The defaultSegment is also in this
378    // number space.  How to compute the value is given by 'condition', as in switch(condition).
379    //
380    // The SPIR-V Builder will maintain the stack of post-switch merge blocks for nested switches.
381    //
382    // Use a defaultSegment < 0 if there is no default segment (to branch to post switch).
383    //
384    // Returns the right set of basic blocks to start each code segment with, so that the caller's
385    // recursion stack can hold the memory for it.
386    //
387    void makeSwitch(Id condition, int numSegments, std::vector<int>& caseValues, std::vector<int>& valueToSegment, int defaultSegment,
388                    std::vector<Block*>& segmentBB);  // return argument
389
390    // Add a branch to the innermost switch's merge block.
391    void addSwitchBreak();
392
393    // Move to the next code segment, passing in the return argument in makeSwitch()
394    void nextSwitchSegment(std::vector<Block*>& segmentBB, int segment);
395
396    // Finish off the innermost switch.
397    void endSwitch(std::vector<Block*>& segmentBB);
398
399    struct LoopBlocks {
400        LoopBlocks(Block& head, Block& body, Block& merge, Block& continue_target) :
401            head(head), body(body), merge(merge), continue_target(continue_target) { }
402        Block &head, &body, &merge, &continue_target;
403    private:
404        LoopBlocks();
405        LoopBlocks& operator=(const LoopBlocks&);
406    };
407
408    // Start a new loop and prepare the builder to generate code for it.  Until
409    // closeLoop() is called for this loop, createLoopContinue() and
410    // createLoopExit() will target its corresponding blocks.
411    LoopBlocks& makeNewLoop();
412
413    // Create a new block in the function containing the build point.  Memory is
414    // owned by the function object.
415    Block& makeNewBlock();
416
417    // Add a branch to the continue_target of the current (innermost) loop.
418    void createLoopContinue();
419
420    // Add an exit (e.g. "break") from the innermost loop that we're currently
421    // in.
422    void createLoopExit();
423
424    // Close the innermost loop that you're in
425    void closeLoop();
426
427    //
428    // Access chain design for an R-Value vs. L-Value:
429    //
430    // There is a single access chain the builder is building at
431    // any particular time.  Such a chain can be used to either to a load or
432    // a store, when desired.
433    //
434    // Expressions can be r-values, l-values, or both, or only r-values:
435    //    a[b.c].d = ....  // l-value
436    //    ... = a[b.c].d;  // r-value, that also looks like an l-value
437    //    ++a[b.c].d;      // r-value and l-value
438    //    (x + y)[2];      // r-value only, can't possibly be l-value
439    //
440    // Computing an r-value means generating code.  Hence,
441    // r-values should only be computed when they are needed, not speculatively.
442    //
443    // Computing an l-value means saving away information for later use in the compiler,
444    // no code is generated until the l-value is later dereferenced.  It is okay
445    // to speculatively generate an l-value, just not okay to speculatively dereference it.
446    //
447    // The base of the access chain (the left-most variable or expression
448    // from which everything is based) can be set either as an l-value
449    // or as an r-value.  Most efficient would be to set an l-value if one
450    // is available.  If an expression was evaluated, the resulting r-value
451    // can be set as the chain base.
452    //
453    // The users of this single access chain can save and restore if they
454    // want to nest or manage multiple chains.
455    //
456
457    struct AccessChain {
458        Id base;                       // for l-values, pointer to the base object, for r-values, the base object
459        std::vector<Id> indexChain;
460        Id instr;                      // cache the instruction that generates this access chain
461        std::vector<unsigned> swizzle; // each std::vector element selects the next GLSL component number
462        Id component;                  // a dynamic component index, can coexist with a swizzle, done after the swizzle, NoResult if not present
463        Id preSwizzleBaseType;         // dereferenced type, before swizzle or component is applied; NoType unless a swizzle or component is present
464        bool isRValue;                 // true if 'base' is an r-value, otherwise, base is an l-value
465    };
466
467    //
468    // the SPIR-V builder maintains a single active chain that
469    // the following methods operated on
470    //
471
472    // for external save and restore
473    AccessChain getAccessChain() { return accessChain; }
474    void setAccessChain(AccessChain newChain) { accessChain = newChain; }
475
476    // clear accessChain
477    void clearAccessChain();
478
479    // set new base as an l-value base
480    void setAccessChainLValue(Id lValue)
481    {
482        assert(isPointer(lValue));
483        accessChain.base = lValue;
484    }
485
486    // set new base value as an r-value
487    void setAccessChainRValue(Id rValue)
488    {
489        accessChain.isRValue = true;
490        accessChain.base = rValue;
491    }
492
493    // push offset onto the end of the chain
494    void accessChainPush(Id offset)
495    {
496        accessChain.indexChain.push_back(offset);
497    }
498
499    // push new swizzle onto the end of any existing swizzle, merging into a single swizzle
500    void accessChainPushSwizzle(std::vector<unsigned>& swizzle, Id preSwizzleBaseType);
501
502    // push a variable component selection onto the access chain; supporting only one, so unsided
503    void accessChainPushComponent(Id component, Id preSwizzleBaseType)
504    {
505        accessChain.component = component;
506        if (accessChain.preSwizzleBaseType == NoType)
507            accessChain.preSwizzleBaseType = preSwizzleBaseType;
508    }
509
510    // use accessChain and swizzle to store value
511    void accessChainStore(Id rvalue);
512
513    // use accessChain and swizzle to load an r-value
514    Id accessChainLoad(Decoration precision, Id ResultType);
515
516    // get the direct pointer for an l-value
517    Id accessChainGetLValue();
518
519    // Get the inferred SPIR-V type of the result of the current access chain,
520    // based on the type of the base and the chain of dereferences.
521    Id accessChainGetInferredType();
522
523    // Remove OpDecorate instructions whose operands are defined in unreachable
524    // blocks.
525    void eliminateDeadDecorations();
526    void dump(std::vector<unsigned int>&) const;
527
528    void createBranch(Block* block);
529    void createConditionalBranch(Id condition, Block* thenBlock, Block* elseBlock);
530    void createLoopMerge(Block* mergeBlock, Block* continueBlock, unsigned int control);
531
532    // Sets to generate opcode for specialization constants.
533    void setToSpecConstCodeGenMode() { generatingOpCodeForSpecConst = true; }
534    // Sets to generate opcode for non-specialization constants (normal mode).
535    void setToNormalCodeGenMode() { generatingOpCodeForSpecConst = false; }
536    // Check if the builder is generating code for spec constants.
537    bool isInSpecConstCodeGenMode() { return generatingOpCodeForSpecConst; }
538
539 protected:
540    Id makeIntConstant(Id typeId, unsigned value, bool specConstant);
541    Id makeInt64Constant(Id typeId, unsigned long long value, bool specConstant);
542    Id findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned value) const;
543    Id findScalarConstant(Op typeClass, Op opcode, Id typeId, unsigned v1, unsigned v2) const;
544    Id findCompositeConstant(Op typeClass, std::vector<Id>& comps) const;
545    Id collapseAccessChain();
546    void transferAccessChainSwizzle(bool dynamic);
547    void simplifyAccessChainSwizzle();
548    void createAndSetNoPredecessorBlock(const char*);
549    void createSelectionMerge(Block* mergeBlock, unsigned int control);
550    void dumpInstructions(std::vector<unsigned int>&, const std::vector<std::unique_ptr<Instruction> >&) const;
551
552    SourceLanguage source;
553    int sourceVersion;
554    std::vector<const char*> extensions;
555    AddressingModel addressModel;
556    MemoryModel memoryModel;
557    std::set<spv::Capability> capabilities;
558    int builderNumber;
559    Module module;
560    Block* buildPoint;
561    Id uniqueId;
562    Function* mainFunction;
563    bool generatingOpCodeForSpecConst;
564    AccessChain accessChain;
565
566    // special blocks of instructions for output
567    std::vector<std::unique_ptr<Instruction> > imports;
568    std::vector<std::unique_ptr<Instruction> > entryPoints;
569    std::vector<std::unique_ptr<Instruction> > executionModes;
570    std::vector<std::unique_ptr<Instruction> > names;
571    std::vector<std::unique_ptr<Instruction> > lines;
572    std::vector<std::unique_ptr<Instruction> > decorations;
573    std::vector<std::unique_ptr<Instruction> > constantsTypesGlobals;
574    std::vector<std::unique_ptr<Instruction> > externals;
575    std::vector<std::unique_ptr<Function> > functions;
576
577     // not output, internally used for quick & dirty canonical (unique) creation
578    std::vector<Instruction*> groupedConstants[OpConstant];  // all types appear before OpConstant
579    std::vector<Instruction*> groupedTypes[OpConstant];
580
581    // stack of switches
582    std::stack<Block*> switchMerges;
583
584    // Our loop stack.
585    std::stack<LoopBlocks> loops;
586
587    // The stream for outputing warnings and errors.
588    SpvBuildLogger* logger;
589};  // end Builder class
590
591};  // end spv namespace
592
593#endif // SpvBuilder_H
594