blob: 22a0df64cb45e3eb35ba579f50de0a0ea40ae5e3 [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:
104 *pInstTable = &table_1_0;
105 return SPV_SUCCESS;
106 case SPV_ENV_UNIVERSAL_1_1:
107 *pInstTable = &table_1_1;
108 return SPV_SUCCESS;
109 }
110 assert(0 && "Unknown spv_target_env in spvOpcodeTableGet()");
111 return SPV_ERROR_INVALID_TABLE;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100112}
113
114spv_result_t spvOpcodeTableNameLookup(const spv_opcode_table table,
Lei Zhang1a0334e2015-11-02 09:41:20 -0500115 const char* name,
116 spv_opcode_desc* pEntry) {
Lei Zhang40056702015-09-11 14:31:27 -0400117 if (!name || !pEntry) return SPV_ERROR_INVALID_POINTER;
118 if (!table) return SPV_ERROR_INVALID_TABLE;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100119
120 // TODO: This lookup of the Opcode table is suboptimal! Binary sort would be
121 // preferable but the table requires sorting on the Opcode name, but it's
122 // static
123 // const initialized and matches the order of the spec.
124 const size_t nameLength = strlen(name);
125 for (uint64_t opcodeIndex = 0; opcodeIndex < table->count; ++opcodeIndex) {
126 if (nameLength == strlen(table->entries[opcodeIndex].name) &&
127 !strncmp(name, table->entries[opcodeIndex].name, nameLength)) {
128 // NOTE: Found out Opcode!
129 *pEntry = &table->entries[opcodeIndex];
130 return SPV_SUCCESS;
131 }
132 }
133
134 return SPV_ERROR_INVALID_LOOKUP;
135}
136
137spv_result_t spvOpcodeTableValueLookup(const spv_opcode_table table,
Lei Zhangb36e7042015-10-28 13:40:52 -0400138 const SpvOp opcode,
Lei Zhang1a0334e2015-11-02 09:41:20 -0500139 spv_opcode_desc* pEntry) {
Lei Zhang40056702015-09-11 14:31:27 -0400140 if (!table) return SPV_ERROR_INVALID_TABLE;
141 if (!pEntry) return SPV_ERROR_INVALID_POINTER;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100142
143 // TODO: As above this lookup is not optimal.
144 for (uint64_t opcodeIndex = 0; opcodeIndex < table->count; ++opcodeIndex) {
145 if (opcode == table->entries[opcodeIndex].opcode) {
146 // NOTE: Found the Opcode!
147 *pEntry = &table->entries[opcodeIndex];
148 return SPV_SUCCESS;
149 }
150 }
151
152 return SPV_ERROR_INVALID_LOOKUP;
153}
154
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100155int32_t spvOpcodeRequiresCapabilities(spv_opcode_desc entry) {
David Neto9db3a532015-10-07 16:58:38 -0400156 return entry->capabilities != 0;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100157}
158
Lei Zhang1a0334e2015-11-02 09:41:20 -0500159void spvInstructionCopy(const uint32_t* words, const SpvOp opcode,
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100160 const uint16_t wordCount, const spv_endianness_t endian,
Lei Zhang1a0334e2015-11-02 09:41:20 -0500161 spv_instruction_t* pInst) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100162 pInst->opcode = opcode;
David Netob5dc8fc2015-10-06 16:22:00 -0400163 pInst->words.resize(wordCount);
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100164 for (uint16_t wordIndex = 0; wordIndex < wordCount; ++wordIndex) {
165 pInst->words[wordIndex] = spvFixWord(words[wordIndex], endian);
166 if (!wordIndex) {
167 uint16_t thisWordCount;
Lei Zhang6fa3f8a2016-03-31 17:26:31 -0400168 uint16_t thisOpcode;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100169 spvOpcodeSplit(pInst->words[wordIndex], &thisWordCount, &thisOpcode);
Lei Zhang6fa3f8a2016-03-31 17:26:31 -0400170 assert(opcode == static_cast<SpvOp>(thisOpcode) &&
171 wordCount == thisWordCount && "Endianness failed!");
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100172 }
173 }
174}
175
Lei Zhang1a0334e2015-11-02 09:41:20 -0500176const char* spvOpcodeString(const SpvOp opcode) {
Dejan Mircevskicb3c49e2016-04-07 14:41:34 -0400177 // Use the latest SPIR-V version, which should be backward-compatible with all
178 // previous ones.
Lei Zhangca1bf942016-04-27 16:47:13 -0400179 for (uint32_t i = 0; i < ARRAY_SIZE(opcodeTableEntries_1_1); ++i) {
Dejan Mircevskicb3c49e2016-04-07 14:41:34 -0400180 if (opcodeTableEntries_1_1[i].opcode == opcode)
181 return opcodeTableEntries_1_1[i].name;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100182 }
Lei Zhang4f293b72016-03-21 16:36:14 -0400183 assert(0 && "Unreachable!");
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100184 return "unknown";
185}
186
Lei Zhangb36e7042015-10-28 13:40:52 -0400187int32_t spvOpcodeIsScalarType(const SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100188 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400189 case SpvOpTypeInt:
190 case SpvOpTypeFloat:
Dejan Mircevski276a7242016-01-21 15:55:43 -0500191 case SpvOpTypeBool:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100192 return true;
193 default:
194 return false;
195 }
196}
197
Lei Zhangb36e7042015-10-28 13:40:52 -0400198int32_t spvOpcodeIsConstant(const SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100199 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400200 case SpvOpConstantTrue:
201 case SpvOpConstantFalse:
202 case SpvOpConstant:
203 case SpvOpConstantComposite:
204 case SpvOpConstantSampler:
Lei Zhangb36e7042015-10-28 13:40:52 -0400205 case SpvOpConstantNull:
206 case SpvOpSpecConstantTrue:
207 case SpvOpSpecConstantFalse:
208 case SpvOpSpecConstant:
209 case SpvOpSpecConstantComposite:
Dejan Mircevski3fb26762016-04-04 15:55:05 -0400210 case SpvOpSpecConstantOp:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100211 return true;
212 default:
213 return false;
214 }
215}
216
Lei Zhangb36e7042015-10-28 13:40:52 -0400217int32_t spvOpcodeIsComposite(const SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100218 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400219 case SpvOpTypeVector:
220 case SpvOpTypeMatrix:
221 case SpvOpTypeArray:
222 case SpvOpTypeStruct:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100223 return true;
224 default:
225 return false;
226 }
227}
228
Florian Ziesche66fcb452016-03-02 22:17:54 +0100229int32_t spvOpcodeReturnsLogicalPointer(const SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100230 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400231 case SpvOpVariable:
232 case SpvOpAccessChain:
233 case SpvOpInBoundsAccessChain:
234 case SpvOpFunctionParameter:
Florian Ziesche66fcb452016-03-02 22:17:54 +0100235 case SpvOpImageTexelPointer:
236 case SpvOpCopyObject:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100237 return true;
238 default:
239 return false;
240 }
241}
242
Lei Zhangb36e7042015-10-28 13:40:52 -0400243int32_t spvOpcodeGeneratesType(SpvOp op) {
Lei Zhang1a0334e2015-11-02 09:41:20 -0500244 switch (op) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400245 case SpvOpTypeVoid:
246 case SpvOpTypeBool:
247 case SpvOpTypeInt:
248 case SpvOpTypeFloat:
249 case SpvOpTypeVector:
250 case SpvOpTypeMatrix:
251 case SpvOpTypeImage:
252 case SpvOpTypeSampler:
253 case SpvOpTypeSampledImage:
254 case SpvOpTypeArray:
255 case SpvOpTypeRuntimeArray:
256 case SpvOpTypeStruct:
257 case SpvOpTypeOpaque:
258 case SpvOpTypePointer:
259 case SpvOpTypeFunction:
260 case SpvOpTypeEvent:
261 case SpvOpTypeDeviceEvent:
262 case SpvOpTypeReserveId:
263 case SpvOpTypeQueue:
264 case SpvOpTypePipe:
Andrew Woloszyn537e7762015-09-29 11:28:34 -0400265 return true;
David Netoaef608c2015-11-02 14:59:02 -0500266 default:
267 // In particular, OpTypeForwardPointer does not generate a type,
268 // but declares a storage class for a pointer type generated
269 // by a different instruction.
270 break;
Andrew Woloszyn537e7762015-09-29 11:28:34 -0400271 }
272 return 0;
273}