blob: 08f905ef71e9d5008d7f00666c7153fc6e5ad293 [file] [log] [blame]
John Kessenich140f3df2015-06-26 16:58:36 -06001//
John Kessenich5e4b1242015-08-06 22:53:06 -06002//Copyright (C) 2014-2015 LunarG, Inc.
John Kessenich140f3df2015-06-26 16:58:36 -06003//
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
John Kessenich5e4b1242015-08-06 22:53:06 -060024//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
John Kessenich140f3df2015-06-26 16:58:36 -060025//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
John Kessenich5e4b1242015-08-06 22:53:06 -060030//CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31//LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
John Kessenich140f3df2015-06-26 16:58:36 -060032//ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
John Kessenich5e4b1242015-08-06 22:53:06 -060033//POSSIBILITY OF SUCH DAMAGE.
John Kessenich140f3df2015-06-26 16:58:36 -060034
35//
36// Author: John Kessenich, LunarG
37//
38
39//
40// Disassembler for SPIR-V.
41//
42
43#include <stdlib.h>
John Kessenich5e4b1242015-08-06 22:53:06 -060044#include <string.h>
John Kessenich140f3df2015-06-26 16:58:36 -060045#include <assert.h>
46#include <iomanip>
47#include <stack>
48#include <sstream>
John Kessenich5e4b1242015-08-06 22:53:06 -060049#include <cstring>
John Kessenich140f3df2015-06-26 16:58:36 -060050
John Kessenich55e7d112015-11-15 21:33:39 -070051namespace spv {
52 // Include C-based headers that don't have a namespace
baldurke915da42015-11-16 18:05:07 +010053 #include "GLSL.std.450.h"
John Kessenich55e7d112015-11-15 21:33:39 -070054}
55const char* GlslStd450DebugNames[spv::GLSLstd450Count];
56
John Kessenich140f3df2015-06-26 16:58:36 -060057#include "disassemble.h"
58#include "doc.h"
59
60namespace spv {
61
62void Kill(std::ostream& out, const char* message)
63{
64 out << std::endl << "Disassembly failed: " << message << std::endl;
65 exit(1);
66}
67
John Kessenich5e4b1242015-08-06 22:53:06 -060068// used to identify the extended instruction library imported when printing
69enum ExtInstSet {
70 GLSL450Inst,
71 OpenCLExtInst,
72};
73
John Kessenich140f3df2015-06-26 16:58:36 -060074// Container class for a single instance of a SPIR-V stream, with methods for disassembly.
75class SpirvStream {
76public:
77 SpirvStream(std::ostream& out, const std::vector<unsigned int>& stream) : out(out), stream(stream), word(0), nextNestedControl(0) { }
78 virtual ~SpirvStream() { }
79
80 void validate();
81 void processInstructions();
82
83protected:
John Kessenich5e4b1242015-08-06 22:53:06 -060084 SpirvStream(const SpirvStream&);
85 SpirvStream& operator=(const SpirvStream&);
John Kessenich140f3df2015-06-26 16:58:36 -060086 Op getOpCode(int id) const { return idInstruction[id] ? (Op)(stream[idInstruction[id]] & OpCodeMask) : OpNop; }
87
88 // Output methods
89 void outputIndent();
90 void formatId(Id id, std::stringstream&);
91 void outputResultId(Id id);
92 void outputTypeId(Id id);
93 void outputId(Id id);
John Kessenich5e4b1242015-08-06 22:53:06 -060094 void outputMask(OperandClass operandClass, unsigned mask);
John Kessenich140f3df2015-06-26 16:58:36 -060095 void disassembleImmediates(int numOperands);
96 void disassembleIds(int numOperands);
John Kessenich55e7d112015-11-15 21:33:39 -070097 int disassembleString();
John Kessenich140f3df2015-06-26 16:58:36 -060098 void disassembleInstruction(Id resultId, Id typeId, Op opCode, int numOperands);
99
100 // Data
101 std::ostream& out; // where to write the disassembly
102 const std::vector<unsigned int>& stream; // the actual word stream
103 int size; // the size of the word stream
104 int word; // the next word of the stream to read
105
106 // map each <id> to the instruction that created it
107 Id bound;
108 std::vector<unsigned int> idInstruction; // the word offset into the stream where the instruction for result [id] starts; 0 if not yet seen (forward reference or function parameter)
109
110 std::vector<std::string> idDescriptor; // the best text string known for explaining the <id>
111
112 // schema
113 unsigned int schema;
114
115 // stack of structured-merge points
116 std::stack<Id> nestedControl;
117 Id nextNestedControl; // need a slight delay for when we are nested
118};
119
120void SpirvStream::validate()
121{
122 size = (int)stream.size();
123 if (size < 4)
124 Kill(out, "stream is too short");
125
126 // Magic number
127 if (stream[word++] != MagicNumber) {
128 out << "Bad magic number";
129 return;
130 }
131
132 // Version
John Kessenich55e7d112015-11-15 21:33:39 -0700133 out << "// Module Version " << std::hex << stream[word++] << std::endl;
John Kessenich140f3df2015-06-26 16:58:36 -0600134
135 // Generator's magic number
John Kessenich55e7d112015-11-15 21:33:39 -0700136 out << "// Generated by (magic number): " << std::hex << stream[word++] << std::dec << std::endl;
John Kessenich140f3df2015-06-26 16:58:36 -0600137
138 // Result <id> bound
139 bound = stream[word++];
140 idInstruction.resize(bound);
141 idDescriptor.resize(bound);
142 out << "// Id's are bound by " << bound << std::endl;
143 out << std::endl;
144
145 // Reserved schema, must be 0 for now
146 schema = stream[word++];
147 if (schema != 0)
148 Kill(out, "bad schema, must be 0");
149}
150
151// Loop over all the instructions, in order, processing each.
152// Boiler plate for each is handled here directly, the rest is dispatched.
153void SpirvStream::processInstructions()
154{
155 // Instructions
156 while (word < size) {
157 int instructionStart = word;
158
159 // Instruction wordCount and opcode
160 unsigned int firstWord = stream[word];
161 unsigned wordCount = firstWord >> WordCountShift;
162 Op opCode = (Op)(firstWord & OpCodeMask);
163 int nextInst = word + wordCount;
164 ++word;
165
166 // Presence of full instruction
167 if (nextInst > size)
168 Kill(out, "stream instruction terminated too early");
169
170 // Base for computing number of operands; will be updated as more is learned
171 unsigned numOperands = wordCount - 1;
172
173 // Type <id>
174 Id typeId = 0;
175 if (InstructionDesc[opCode].hasType()) {
176 typeId = stream[word++];
177 --numOperands;
178 }
179
180 // Result <id>
181 Id resultId = 0;
182 if (InstructionDesc[opCode].hasResult()) {
183 resultId = stream[word++];
184 --numOperands;
185
186 // save instruction for future reference
187 idInstruction[resultId] = instructionStart;
188 }
189
190 outputResultId(resultId);
191 outputTypeId(typeId);
192 outputIndent();
193
194 // Hand off the Op and all its operands
195 disassembleInstruction(resultId, typeId, opCode, numOperands);
196 if (word != nextInst) {
197 out << " ERROR, incorrect number of operands consumed. At " << word << " instead of " << nextInst << " instruction start was " << instructionStart;
198 word = nextInst;
199 }
200 out << std::endl;
201 }
202}
203
204void SpirvStream::outputIndent()
205{
206 for (int i = 0; i < (int)nestedControl.size(); ++i)
207 out << " ";
208}
209
210void SpirvStream::formatId(Id id, std::stringstream& idStream)
211{
212 if (id >= bound)
213 Kill(out, "Bad <id>");
214
215 if (id != 0) {
216 idStream << id;
217 if (idDescriptor[id].size() > 0)
218 idStream << "(" << idDescriptor[id] << ")";
219 }
220}
221
222void SpirvStream::outputResultId(Id id)
223{
224 const int width = 16;
225 std::stringstream idStream;
226 formatId(id, idStream);
227 out << std::setw(width) << std::right << idStream.str();
228 if (id != 0)
229 out << ":";
230 else
231 out << " ";
232
233 if (nestedControl.size() && id == nestedControl.top())
234 nestedControl.pop();
235}
236
237void SpirvStream::outputTypeId(Id id)
238{
239 const int width = 12;
240 std::stringstream idStream;
241 formatId(id, idStream);
242 out << std::setw(width) << std::right << idStream.str() << " ";
243}
244
245void SpirvStream::outputId(Id id)
246{
247 if (id >= bound)
248 Kill(out, "Bad <id>");
249
250 out << id;
251 if (idDescriptor[id].size() > 0)
252 out << "(" << idDescriptor[id] << ")";
253}
254
John Kessenich5e4b1242015-08-06 22:53:06 -0600255void SpirvStream::outputMask(OperandClass operandClass, unsigned mask)
256{
257 if (mask == 0)
258 out << "None";
259 else {
260 for (int m = 0; m < OperandClassParams[operandClass].ceiling; ++m) {
261 if (mask & (1 << m))
262 out << OperandClassParams[operandClass].getName(m) << " ";
263 }
264 }
265}
266
John Kessenich140f3df2015-06-26 16:58:36 -0600267void SpirvStream::disassembleImmediates(int numOperands)
268{
269 for (int i = 0; i < numOperands; ++i) {
270 out << stream[word++];
271 if (i < numOperands - 1)
272 out << " ";
273 }
274}
275
276void SpirvStream::disassembleIds(int numOperands)
277{
278 for (int i = 0; i < numOperands; ++i) {
279 outputId(stream[word++]);
280 if (i < numOperands - 1)
281 out << " ";
282 }
283}
284
John Kessenich55e7d112015-11-15 21:33:39 -0700285// return the number of operands consumed by the string
286int SpirvStream::disassembleString()
John Kessenich140f3df2015-06-26 16:58:36 -0600287{
John Kessenich55e7d112015-11-15 21:33:39 -0700288 int startWord = word;
289
John Kessenich140f3df2015-06-26 16:58:36 -0600290 out << " \"";
291
John Kessenich55e7d112015-11-15 21:33:39 -0700292 const char* wordString;
John Kessenich140f3df2015-06-26 16:58:36 -0600293 bool done = false;
294 do {
295 unsigned int content = stream[word];
John Kessenich55e7d112015-11-15 21:33:39 -0700296 wordString = (const char*)&content;
John Kessenich140f3df2015-06-26 16:58:36 -0600297 for (int charCount = 0; charCount < 4; ++charCount) {
298 if (*wordString == 0) {
299 done = true;
300 break;
301 }
302 out << *(wordString++);
303 }
304 ++word;
305 } while (! done);
306
307 out << "\"";
John Kessenich55e7d112015-11-15 21:33:39 -0700308
309 return word - startWord;
John Kessenich140f3df2015-06-26 16:58:36 -0600310}
311
312void SpirvStream::disassembleInstruction(Id resultId, Id /*typeId*/, Op opCode, int numOperands)
313{
314 // Process the opcode
315
316 out << (OpcodeString(opCode) + 2); // leave out the "Op"
317
318 if (opCode == OpLoopMerge || opCode == OpSelectionMerge)
319 nextNestedControl = stream[word];
320 else if (opCode == OpBranchConditional || opCode == OpSwitch) {
321 if (nextNestedControl) {
322 nestedControl.push(nextNestedControl);
323 nextNestedControl = 0;
324 }
John Kessenich5e4b1242015-08-06 22:53:06 -0600325 } else if (opCode == OpExtInstImport) {
Mark Adamsc11e95f2015-10-26 12:38:46 -0400326 idDescriptor[resultId] = (const char*)(&stream[word]);
John Kessenich5e4b1242015-08-06 22:53:06 -0600327 }
John Kessenich140f3df2015-06-26 16:58:36 -0600328 else {
329 if (idDescriptor[resultId].size() == 0) {
330 switch (opCode) {
331 case OpTypeInt:
332 idDescriptor[resultId] = "int";
333 break;
334 case OpTypeFloat:
335 idDescriptor[resultId] = "float";
336 break;
337 case OpTypeBool:
338 idDescriptor[resultId] = "bool";
339 break;
340 case OpTypeStruct:
341 idDescriptor[resultId] = "struct";
342 break;
343 case OpTypePointer:
344 idDescriptor[resultId] = "ptr";
345 break;
346 case OpTypeVector:
347 if (idDescriptor[stream[word]].size() > 0)
348 idDescriptor[resultId].append(idDescriptor[stream[word]].begin(), idDescriptor[stream[word]].begin() + 1);
349 idDescriptor[resultId].append("vec");
350 switch (stream[word + 1]) {
351 case 2: idDescriptor[resultId].append("2"); break;
352 case 3: idDescriptor[resultId].append("3"); break;
353 case 4: idDescriptor[resultId].append("4"); break;
354 case 8: idDescriptor[resultId].append("8"); break;
355 case 16: idDescriptor[resultId].append("16"); break;
356 case 32: idDescriptor[resultId].append("32"); break;
357 default: break;
358 }
359 break;
360 default:
361 break;
362 }
363 }
364 }
365
366 // Process the operands. Note, a new context-dependent set could be
367 // swapped in mid-traversal.
368
John Kessenich5e4b1242015-08-06 22:53:06 -0600369 // Handle images specially, so can put out helpful strings.
370 if (opCode == OpTypeImage) {
371 out << " ";
John Kessenich140f3df2015-06-26 16:58:36 -0600372 disassembleIds(1);
373 out << " " << DimensionString((Dim)stream[word++]);
John Kessenich140f3df2015-06-26 16:58:36 -0600374 out << (stream[word++] != 0 ? " depth" : "");
John Kessenich5e4b1242015-08-06 22:53:06 -0600375 out << (stream[word++] != 0 ? " array" : "");
John Kessenich140f3df2015-06-26 16:58:36 -0600376 out << (stream[word++] != 0 ? " multi-sampled" : "");
John Kessenich5e4b1242015-08-06 22:53:06 -0600377 switch (stream[word++]) {
378 case 0: out << " runtime"; break;
379 case 1: out << " sampled"; break;
380 case 2: out << " nonsampled"; break;
381 }
382 out << " format:" << ImageFormatString((ImageFormat)stream[word++]);
383
384 if (numOperands == 8) {
385 out << " " << AccessQualifierString(stream[word++]);
386 }
John Kessenich140f3df2015-06-26 16:58:36 -0600387 return;
388 }
389
390 // Handle all the parameterized operands
John Kessenich5e4b1242015-08-06 22:53:06 -0600391 for (int op = 0; op < InstructionDesc[opCode].operands.getNum() && numOperands > 0; ++op) {
John Kessenich140f3df2015-06-26 16:58:36 -0600392 out << " ";
393 OperandClass operandClass = InstructionDesc[opCode].operands.getClass(op);
394 switch (operandClass) {
395 case OperandId:
John Kessenich5e4b1242015-08-06 22:53:06 -0600396 case OperandScope:
397 case OperandMemorySemantics:
John Kessenich140f3df2015-06-26 16:58:36 -0600398 disassembleIds(1);
John Kessenich55e7d112015-11-15 21:33:39 -0700399 --numOperands;
John Kessenich140f3df2015-06-26 16:58:36 -0600400 // Get names for printing "(XXX)" for readability, *after* this id
401 if (opCode == OpName)
Mark Adamsc11e95f2015-10-26 12:38:46 -0400402 idDescriptor[stream[word - 1]] = (const char*)(&stream[word]);
John Kessenich140f3df2015-06-26 16:58:36 -0600403 break;
John Kessenich140f3df2015-06-26 16:58:36 -0600404 case OperandVariableIds:
405 disassembleIds(numOperands);
406 return;
John Kessenich55e7d112015-11-15 21:33:39 -0700407 case OperandImageOperands:
John Kessenich71631272015-10-13 10:39:19 -0600408 outputMask(OperandImageOperands, stream[word++]);
John Kessenich5e4b1242015-08-06 22:53:06 -0600409 --numOperands;
410 disassembleIds(numOperands);
411 return;
412 case OperandOptionalLiteral:
John Kessenich140f3df2015-06-26 16:58:36 -0600413 case OperandVariableLiterals:
Mark Adamsc11e95f2015-10-26 12:38:46 -0400414 if ((opCode == OpDecorate && stream[word - 1] == DecorationBuiltIn) ||
415 (opCode == OpMemberDecorate && stream[word - 1] == DecorationBuiltIn)) {
John Kessenich140f3df2015-06-26 16:58:36 -0600416 out << BuiltInString(stream[word++]);
417 --numOperands;
418 ++op;
419 }
420 disassembleImmediates(numOperands);
421 return;
John Kessenich5e4b1242015-08-06 22:53:06 -0600422 case OperandVariableIdLiteral:
423 while (numOperands > 0) {
424 out << std::endl;
425 outputResultId(0);
426 outputTypeId(0);
427 outputIndent();
428 out << " Type ";
429 disassembleIds(1);
430 out << ", member ";
431 disassembleImmediates(1);
432 numOperands -= 2;
433 }
434 return;
John Kessenich140f3df2015-06-26 16:58:36 -0600435 case OperandVariableLiteralId:
436 while (numOperands > 0) {
437 out << std::endl;
438 outputResultId(0);
439 outputTypeId(0);
440 outputIndent();
441 out << " case ";
442 disassembleImmediates(1);
443 out << ": ";
444 disassembleIds(1);
445 numOperands -= 2;
446 }
447 return;
448 case OperandLiteralNumber:
449 disassembleImmediates(1);
John Kessenich55e7d112015-11-15 21:33:39 -0700450 --numOperands;
John Kessenich140f3df2015-06-26 16:58:36 -0600451 if (opCode == OpExtInst) {
John Kessenich5e4b1242015-08-06 22:53:06 -0600452 ExtInstSet extInstSet = GLSL450Inst;
Mark Adamsc11e95f2015-10-26 12:38:46 -0400453 if (0 == memcmp("OpenCL", (const char*)(idDescriptor[stream[word-2]].c_str()), 6)) {
John Kessenich5e4b1242015-08-06 22:53:06 -0600454 extInstSet = OpenCLExtInst;
455 }
John Kessenich140f3df2015-06-26 16:58:36 -0600456 unsigned entrypoint = stream[word - 1];
John Kessenich5e4b1242015-08-06 22:53:06 -0600457 if (extInstSet == GLSL450Inst) {
John Kessenich55e7d112015-11-15 21:33:39 -0700458 if (entrypoint < GLSLstd450Count) {
John Kessenich5e4b1242015-08-06 22:53:06 -0600459 out << "(" << GlslStd450DebugNames[entrypoint] << ")";
460 }
461 }
John Kessenich140f3df2015-06-26 16:58:36 -0600462 }
463 break;
John Kessenich55e7d112015-11-15 21:33:39 -0700464 case OperandOptionalLiteralString:
John Kessenich140f3df2015-06-26 16:58:36 -0600465 case OperandLiteralString:
John Kessenich55e7d112015-11-15 21:33:39 -0700466 numOperands -= disassembleString();
467 break;
John Kessenich140f3df2015-06-26 16:58:36 -0600468 default:
469 assert(operandClass >= OperandSource && operandClass < OperandOpcode);
470
John Kessenich5e4b1242015-08-06 22:53:06 -0600471 if (OperandClassParams[operandClass].bitmask)
472 outputMask(operandClass, stream[word++]);
473 else
John Kessenich140f3df2015-06-26 16:58:36 -0600474 out << OperandClassParams[operandClass].getName(stream[word++]);
John Kessenich55e7d112015-11-15 21:33:39 -0700475 --numOperands;
John Kessenich140f3df2015-06-26 16:58:36 -0600476 break;
477 }
John Kessenich140f3df2015-06-26 16:58:36 -0600478 }
479
480 return;
481}
482
John Kessenich5e4b1242015-08-06 22:53:06 -0600483void GLSLstd450GetDebugNames(const char** names)
484{
485 for (int i = 0; i < GLSLstd450Count; ++i)
486 names[i] = "Unknown";
487
488 names[GLSLstd450Round] = "Round";
489 names[GLSLstd450RoundEven] = "RoundEven";
490 names[GLSLstd450Trunc] = "Trunc";
491 names[GLSLstd450FAbs] = "FAbs";
492 names[GLSLstd450SAbs] = "SAbs";
493 names[GLSLstd450FSign] = "FSign";
494 names[GLSLstd450SSign] = "SSign";
495 names[GLSLstd450Floor] = "Floor";
496 names[GLSLstd450Ceil] = "Ceil";
497 names[GLSLstd450Fract] = "Fract";
498 names[GLSLstd450Radians] = "Radians";
499 names[GLSLstd450Degrees] = "Degrees";
500 names[GLSLstd450Sin] = "Sin";
501 names[GLSLstd450Cos] = "Cos";
502 names[GLSLstd450Tan] = "Tan";
503 names[GLSLstd450Asin] = "Asin";
504 names[GLSLstd450Acos] = "Acos";
505 names[GLSLstd450Atan] = "Atan";
506 names[GLSLstd450Sinh] = "Sinh";
507 names[GLSLstd450Cosh] = "Cosh";
508 names[GLSLstd450Tanh] = "Tanh";
509 names[GLSLstd450Asinh] = "Asinh";
510 names[GLSLstd450Acosh] = "Acosh";
511 names[GLSLstd450Atanh] = "Atanh";
512 names[GLSLstd450Atan2] = "Atan2";
513 names[GLSLstd450Pow] = "Pow";
514 names[GLSLstd450Exp] = "Exp";
515 names[GLSLstd450Log] = "Log";
516 names[GLSLstd450Exp2] = "Exp2";
517 names[GLSLstd450Log2] = "Log2";
518 names[GLSLstd450Sqrt] = "Sqrt";
John Kessenich55e7d112015-11-15 21:33:39 -0700519 names[GLSLstd450InverseSqrt] = "InverseSqrt";
John Kessenich5e4b1242015-08-06 22:53:06 -0600520 names[GLSLstd450Determinant] = "Determinant";
John Kessenich55e7d112015-11-15 21:33:39 -0700521 names[GLSLstd450MatrixInverse] = "MatrixInverse";
John Kessenich5e4b1242015-08-06 22:53:06 -0600522 names[GLSLstd450Modf] = "Modf";
523 names[GLSLstd450ModfStruct] = "ModfStruct";
524 names[GLSLstd450FMin] = "FMin";
525 names[GLSLstd450SMin] = "SMin";
526 names[GLSLstd450UMin] = "UMin";
527 names[GLSLstd450FMax] = "FMax";
528 names[GLSLstd450SMax] = "SMax";
529 names[GLSLstd450UMax] = "UMax";
530 names[GLSLstd450FClamp] = "FClamp";
531 names[GLSLstd450SClamp] = "SClamp";
532 names[GLSLstd450UClamp] = "UClamp";
John Kessenich55e7d112015-11-15 21:33:39 -0700533 names[GLSLstd450FMix] = "FMix";
534 names[GLSLstd450IMix] = "IMix";
John Kessenich5e4b1242015-08-06 22:53:06 -0600535 names[GLSLstd450Step] = "Step";
John Kessenich55e7d112015-11-15 21:33:39 -0700536 names[GLSLstd450SmoothStep] = "SmoothStep";
John Kessenich5e4b1242015-08-06 22:53:06 -0600537 names[GLSLstd450Fma] = "Fma";
538 names[GLSLstd450Frexp] = "Frexp";
539 names[GLSLstd450FrexpStruct] = "FrexpStruct";
540 names[GLSLstd450Ldexp] = "Ldexp";
541 names[GLSLstd450PackSnorm4x8] = "PackSnorm4x8";
542 names[GLSLstd450PackUnorm4x8] = "PackUnorm4x8";
543 names[GLSLstd450PackSnorm2x16] = "PackSnorm2x16";
544 names[GLSLstd450PackUnorm2x16] = "PackUnorm2x16";
545 names[GLSLstd450PackHalf2x16] = "PackHalf2x16";
546 names[GLSLstd450PackDouble2x32] = "PackDouble2x32";
547 names[GLSLstd450UnpackSnorm2x16] = "UnpackSnorm2x16";
548 names[GLSLstd450UnpackUnorm2x16] = "UnpackUnorm2x16";
549 names[GLSLstd450UnpackHalf2x16] = "UnpackHalf2x16";
550 names[GLSLstd450UnpackSnorm4x8] = "UnpackSnorm4x8";
551 names[GLSLstd450UnpackUnorm4x8] = "UnpackUnorm4x8";
552 names[GLSLstd450UnpackDouble2x32] = "UnpackDouble2x32";
553 names[GLSLstd450Length] = "Length";
554 names[GLSLstd450Distance] = "Distance";
555 names[GLSLstd450Cross] = "Cross";
556 names[GLSLstd450Normalize] = "Normalize";
John Kessenich55e7d112015-11-15 21:33:39 -0700557 names[GLSLstd450FaceForward] = "FaceForward";
John Kessenich5e4b1242015-08-06 22:53:06 -0600558 names[GLSLstd450Reflect] = "Reflect";
559 names[GLSLstd450Refract] = "Refract";
John Kessenich55e7d112015-11-15 21:33:39 -0700560 names[GLSLstd450FindILsb] = "FindILsb";
561 names[GLSLstd450FindSMsb] = "FindSMsb";
562 names[GLSLstd450FindUMsb] = "FindUMsb";
John Kessenich5e4b1242015-08-06 22:53:06 -0600563 names[GLSLstd450InterpolateAtCentroid] = "InterpolateAtCentroid";
564 names[GLSLstd450InterpolateAtSample] = "InterpolateAtSample";
565 names[GLSLstd450InterpolateAtOffset] = "InterpolateAtOffset";
566}
567
John Kessenich140f3df2015-06-26 16:58:36 -0600568void Disassemble(std::ostream& out, const std::vector<unsigned int>& stream)
569{
570 SpirvStream SpirvStream(out, stream);
John Kessenich5e4b1242015-08-06 22:53:06 -0600571 GLSLstd450GetDebugNames(GlslStd450DebugNames);
John Kessenich140f3df2015-06-26 16:58:36 -0600572 SpirvStream.validate();
573 SpirvStream.processInstructions();
574}
575
576}; // end namespace spv