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