blob: dae1f9ff7cd65d02ec42c82ca46d557e97c546a5 [file] [log] [blame]
Dejan Mircevskib6fe02f2016-01-07 13:44:22 -05001// Copyright (c) 2015-2016 The Khronos Group Inc.
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +01002//
3// Permission is hereby granted, free of charge, to any person obtaining a
4// copy of this software and/or associated documentation files (the
5// "Materials"), to deal in the Materials without restriction, including
6// without limitation the rights to use, copy, modify, merge, publish,
7// distribute, sublicense, and/or sell copies of the Materials, and to
8// permit persons to whom the Materials are furnished to do so, subject to
9// the following conditions:
10//
11// The above copyright notice and this permission notice shall be included
12// in all copies or substantial portions of the Materials.
13//
14// MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS
15// KHRONOS STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS
16// SPECIFICATIONS AND HEADER INFORMATION ARE LOCATED AT
17// https://www.khronos.org/registry/
18//
19// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
23// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
26
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010027#include "opcode.h"
28
29#include <assert.h>
30#include <string.h>
31
Lei Zhang972788b2015-11-12 13:48:30 -050032#include <cstdlib>
33
Lei Zhang923f6c12015-11-11 12:45:23 -050034#include "instruction.h"
Lei Zhangca1bf942016-04-27 16:47:13 -040035#include "macro.h"
David Neto5a703352016-02-17 14:44:00 -050036#include "spirv-tools/libspirv.h"
Lei Zhangaa056cd2015-11-11 14:24:04 -050037#include "spirv_constant.h"
David Neto4c215712015-12-22 15:08:41 -050038#include "spirv_endian.h"
Lei Zhang923f6c12015-11-11 12:45:23 -050039
David Neto78c3b432015-08-27 13:03:52 -040040namespace {
41
42// Descriptions of each opcode. Each entry describes the format of the
43// instruction that follows a particular opcode.
Dejan Mircevskicb3c49e2016-04-07 14:41:34 -040044const spv_opcode_desc_t opcodeTableEntries_1_0[] = {
Lei Zhang10dba912016-04-14 14:05:53 -040045#include "core.insts-1.0.inc"
David Neto78c3b432015-08-27 13:03:52 -040046};
Dejan Mircevskicb3c49e2016-04-07 14:41:34 -040047const spv_opcode_desc_t opcodeTableEntries_1_1[] = {
Lei Zhang10dba912016-04-14 14:05:53 -040048#include "core.insts-1.1.inc"
Dejan Mircevskicb3c49e2016-04-07 14:41:34 -040049};
David Neto78c3b432015-08-27 13:03:52 -040050
Lei Zhanga94701d2015-09-14 10:05:37 -040051} // anonymous namespace
David Neto78c3b432015-08-27 13:03:52 -040052
Lei Zhang1a0334e2015-11-02 09:41:20 -050053const char* spvGeneratorStr(uint32_t generator) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010054 switch (generator) {
55 case SPV_GENERATOR_KHRONOS:
56 return "Khronos";
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010057 case SPV_GENERATOR_LUNARG:
58 return "LunarG";
David Neto1780fc42015-10-26 15:43:12 -040059 case SPV_GENERATOR_VALVE:
60 return "Valve";
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010061 case SPV_GENERATOR_CODEPLAY:
62 return "Codeplay Software Ltd.";
David Neto1780fc42015-10-26 15:43:12 -040063 case SPV_GENERATOR_NVIDIA:
64 return "NVIDIA";
65 case SPV_GENERATOR_ARM:
66 return "ARM";
David Neto14b93e42015-11-12 18:33:47 -050067 case SPV_GENERATOR_KHRONOS_LLVM_TRANSLATOR:
68 return "Khronos LLVM/SPIR-V Translator";
69 case SPV_GENERATOR_KHRONOS_ASSEMBLER:
70 return "Khronos SPIR-V Tools Assembler";
David Neto2266ba12015-11-13 12:03:28 -060071 case SPV_GENERATOR_KHRONOS_GLSLANG:
72 return "Khronos Glslang Reference Front End";
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010073 default:
74 return "Unknown";
75 }
76}
77
Lei Zhangb36e7042015-10-28 13:40:52 -040078uint32_t spvOpcodeMake(uint16_t wordCount, SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010079 return ((uint32_t)opcode) | (((uint32_t)wordCount) << 16);
80}
81
Lei Zhang6fa3f8a2016-03-31 17:26:31 -040082void spvOpcodeSplit(const uint32_t word, uint16_t* pWordCount,
83 uint16_t* pOpcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010084 if (pWordCount) {
85 *pWordCount = (uint16_t)((0xffff0000 & word) >> 16);
86 }
87 if (pOpcode) {
Lei Zhang6fa3f8a2016-03-31 17:26:31 -040088 *pOpcode = 0x0000ffff & word;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010089 }
90}
91
Dejan Mircevskicb3c49e2016-04-07 14:41:34 -040092spv_result_t spvOpcodeTableGet(spv_opcode_table* pInstTable,
93 spv_target_env env) {
Lei Zhang40056702015-09-11 14:31:27 -040094 if (!pInstTable) return SPV_ERROR_INVALID_POINTER;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010095
Dejan Mircevskicb3c49e2016-04-07 14:41:34 -040096 static const spv_opcode_table_t table_1_0 = {
97 ARRAY_SIZE(opcodeTableEntries_1_0), opcodeTableEntries_1_0};
98 static const spv_opcode_table_t table_1_1 = {
99 ARRAY_SIZE(opcodeTableEntries_1_1), opcodeTableEntries_1_1};
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100100
Dejan Mircevskicb3c49e2016-04-07 14:41:34 -0400101 switch (env) {
102 case SPV_ENV_UNIVERSAL_1_0:
103 case SPV_ENV_VULKAN_1_0:
David Netoc2967012016-08-05 18:19:30 -0400104 case SPV_ENV_OPENCL_2_1:
105 case SPV_ENV_OPENGL_4_0:
106 case SPV_ENV_OPENGL_4_1:
107 case SPV_ENV_OPENGL_4_2:
108 case SPV_ENV_OPENGL_4_3:
109 case SPV_ENV_OPENGL_4_5:
Dejan Mircevskicb3c49e2016-04-07 14:41:34 -0400110 *pInstTable = &table_1_0;
111 return SPV_SUCCESS;
112 case SPV_ENV_UNIVERSAL_1_1:
David Netoc2967012016-08-05 18:19:30 -0400113 case SPV_ENV_OPENCL_2_2:
Dejan Mircevskicb3c49e2016-04-07 14:41:34 -0400114 *pInstTable = &table_1_1;
115 return SPV_SUCCESS;
116 }
117 assert(0 && "Unknown spv_target_env in spvOpcodeTableGet()");
118 return SPV_ERROR_INVALID_TABLE;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100119}
120
121spv_result_t spvOpcodeTableNameLookup(const spv_opcode_table table,
Lei Zhang1a0334e2015-11-02 09:41:20 -0500122 const char* name,
123 spv_opcode_desc* pEntry) {
Lei Zhang40056702015-09-11 14:31:27 -0400124 if (!name || !pEntry) return SPV_ERROR_INVALID_POINTER;
125 if (!table) return SPV_ERROR_INVALID_TABLE;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100126
127 // TODO: This lookup of the Opcode table is suboptimal! Binary sort would be
128 // preferable but the table requires sorting on the Opcode name, but it's
129 // static
130 // const initialized and matches the order of the spec.
131 const size_t nameLength = strlen(name);
132 for (uint64_t opcodeIndex = 0; opcodeIndex < table->count; ++opcodeIndex) {
133 if (nameLength == strlen(table->entries[opcodeIndex].name) &&
134 !strncmp(name, table->entries[opcodeIndex].name, nameLength)) {
135 // NOTE: Found out Opcode!
136 *pEntry = &table->entries[opcodeIndex];
137 return SPV_SUCCESS;
138 }
139 }
140
141 return SPV_ERROR_INVALID_LOOKUP;
142}
143
144spv_result_t spvOpcodeTableValueLookup(const spv_opcode_table table,
Lei Zhangb36e7042015-10-28 13:40:52 -0400145 const SpvOp opcode,
Lei Zhang1a0334e2015-11-02 09:41:20 -0500146 spv_opcode_desc* pEntry) {
Lei Zhang40056702015-09-11 14:31:27 -0400147 if (!table) return SPV_ERROR_INVALID_TABLE;
148 if (!pEntry) return SPV_ERROR_INVALID_POINTER;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100149
150 // TODO: As above this lookup is not optimal.
151 for (uint64_t opcodeIndex = 0; opcodeIndex < table->count; ++opcodeIndex) {
152 if (opcode == table->entries[opcodeIndex].opcode) {
153 // NOTE: Found the Opcode!
154 *pEntry = &table->entries[opcodeIndex];
155 return SPV_SUCCESS;
156 }
157 }
158
159 return SPV_ERROR_INVALID_LOOKUP;
160}
161
Lei Zhang1a0334e2015-11-02 09:41:20 -0500162void spvInstructionCopy(const uint32_t* words, const SpvOp opcode,
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100163 const uint16_t wordCount, const spv_endianness_t endian,
Lei Zhang1a0334e2015-11-02 09:41:20 -0500164 spv_instruction_t* pInst) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100165 pInst->opcode = opcode;
David Netob5dc8fc2015-10-06 16:22:00 -0400166 pInst->words.resize(wordCount);
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100167 for (uint16_t wordIndex = 0; wordIndex < wordCount; ++wordIndex) {
168 pInst->words[wordIndex] = spvFixWord(words[wordIndex], endian);
169 if (!wordIndex) {
170 uint16_t thisWordCount;
Lei Zhang6fa3f8a2016-03-31 17:26:31 -0400171 uint16_t thisOpcode;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100172 spvOpcodeSplit(pInst->words[wordIndex], &thisWordCount, &thisOpcode);
Lei Zhang6fa3f8a2016-03-31 17:26:31 -0400173 assert(opcode == static_cast<SpvOp>(thisOpcode) &&
174 wordCount == thisWordCount && "Endianness failed!");
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100175 }
176 }
177}
178
Lei Zhang1a0334e2015-11-02 09:41:20 -0500179const char* spvOpcodeString(const SpvOp opcode) {
Dejan Mircevskicb3c49e2016-04-07 14:41:34 -0400180 // Use the latest SPIR-V version, which should be backward-compatible with all
181 // previous ones.
Lei Zhangca1bf942016-04-27 16:47:13 -0400182 for (uint32_t i = 0; i < ARRAY_SIZE(opcodeTableEntries_1_1); ++i) {
Dejan Mircevskicb3c49e2016-04-07 14:41:34 -0400183 if (opcodeTableEntries_1_1[i].opcode == opcode)
184 return opcodeTableEntries_1_1[i].name;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100185 }
Lei Zhang4f293b72016-03-21 16:36:14 -0400186 assert(0 && "Unreachable!");
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100187 return "unknown";
188}
189
Lei Zhangb36e7042015-10-28 13:40:52 -0400190int32_t spvOpcodeIsScalarType(const SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100191 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400192 case SpvOpTypeInt:
193 case SpvOpTypeFloat:
Dejan Mircevski276a7242016-01-21 15:55:43 -0500194 case SpvOpTypeBool:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100195 return true;
196 default:
197 return false;
198 }
199}
200
Lei Zhangb36e7042015-10-28 13:40:52 -0400201int32_t spvOpcodeIsConstant(const SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100202 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400203 case SpvOpConstantTrue:
204 case SpvOpConstantFalse:
205 case SpvOpConstant:
206 case SpvOpConstantComposite:
207 case SpvOpConstantSampler:
Lei Zhangb36e7042015-10-28 13:40:52 -0400208 case SpvOpConstantNull:
209 case SpvOpSpecConstantTrue:
210 case SpvOpSpecConstantFalse:
211 case SpvOpSpecConstant:
212 case SpvOpSpecConstantComposite:
Dejan Mircevski3fb26762016-04-04 15:55:05 -0400213 case SpvOpSpecConstantOp:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100214 return true;
215 default:
216 return false;
217 }
218}
219
Lei Zhangb36e7042015-10-28 13:40:52 -0400220int32_t spvOpcodeIsComposite(const SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100221 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400222 case SpvOpTypeVector:
223 case SpvOpTypeMatrix:
224 case SpvOpTypeArray:
225 case SpvOpTypeStruct:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100226 return true;
227 default:
228 return false;
229 }
230}
231
Florian Ziesche66fcb452016-03-02 22:17:54 +0100232int32_t spvOpcodeReturnsLogicalPointer(const SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100233 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400234 case SpvOpVariable:
235 case SpvOpAccessChain:
236 case SpvOpInBoundsAccessChain:
237 case SpvOpFunctionParameter:
Florian Ziesche66fcb452016-03-02 22:17:54 +0100238 case SpvOpImageTexelPointer:
239 case SpvOpCopyObject:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100240 return true;
241 default:
242 return false;
243 }
244}
245
Lei Zhangb36e7042015-10-28 13:40:52 -0400246int32_t spvOpcodeGeneratesType(SpvOp op) {
Lei Zhang1a0334e2015-11-02 09:41:20 -0500247 switch (op) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400248 case SpvOpTypeVoid:
249 case SpvOpTypeBool:
250 case SpvOpTypeInt:
251 case SpvOpTypeFloat:
252 case SpvOpTypeVector:
253 case SpvOpTypeMatrix:
254 case SpvOpTypeImage:
255 case SpvOpTypeSampler:
256 case SpvOpTypeSampledImage:
257 case SpvOpTypeArray:
258 case SpvOpTypeRuntimeArray:
259 case SpvOpTypeStruct:
260 case SpvOpTypeOpaque:
261 case SpvOpTypePointer:
262 case SpvOpTypeFunction:
263 case SpvOpTypeEvent:
264 case SpvOpTypeDeviceEvent:
265 case SpvOpTypeReserveId:
266 case SpvOpTypeQueue:
267 case SpvOpTypePipe:
Andrew Woloszyn537e7762015-09-29 11:28:34 -0400268 return true;
David Netoaef608c2015-11-02 14:59:02 -0500269 default:
270 // In particular, OpTypeForwardPointer does not generate a type,
271 // but declares a storage class for a pointer type generated
272 // by a different instruction.
273 break;
Andrew Woloszyn537e7762015-09-29 11:28:34 -0400274 }
275 return 0;
276}