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