blob: 9bb8cb736c6e08d05b49af49de4242c721812aec [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//
David Neto9fc86582016-09-01 15:33:59 -04003// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +01006//
David Neto9fc86582016-09-01 15:33:59 -04007// http://www.apache.org/licenses/LICENSE-2.0
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +01008//
David Neto9fc86582016-09-01 15:33:59 -04009// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010014
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010015#include "opcode.h"
16
17#include <assert.h>
18#include <string.h>
19
David Neto5a0b5ca2016-12-09 14:01:43 -050020#include <algorithm>
Lei Zhang972788b2015-11-12 13:48:30 -050021#include <cstdlib>
22
Lei Zhang923f6c12015-11-11 12:45:23 -050023#include "instruction.h"
Lei Zhangca1bf942016-04-27 16:47:13 -040024#include "macro.h"
David Neto5a703352016-02-17 14:44:00 -050025#include "spirv-tools/libspirv.h"
Lei Zhangaa056cd2015-11-11 14:24:04 -050026#include "spirv_constant.h"
David Neto4c215712015-12-22 15:08:41 -050027#include "spirv_endian.h"
Lei Zhang923f6c12015-11-11 12:45:23 -050028
David Neto78c3b432015-08-27 13:03:52 -040029namespace {
Lei Zhang16981f82017-09-21 17:24:57 -040030struct OpcodeDescPtrLen {
31 const spv_opcode_desc_t* ptr;
32 uint32_t len;
33};
David Neto78c3b432015-08-27 13:03:52 -040034
Lei Zhang16981f82017-09-21 17:24:57 -040035OpcodeDescPtrLen getOpcodeTableEntries_1_2() {
36 static const spv_opcode_desc_t opcodeTableEntries_1_2[] = {
David Netodbc20492017-03-14 12:43:41 -040037#include "core.insts-1.2.inc"
Lei Zhang16981f82017-09-21 17:24:57 -040038 };
39
40 return {opcodeTableEntries_1_2, ARRAY_SIZE(opcodeTableEntries_1_2)};
41}
David Neto78c3b432015-08-27 13:03:52 -040042
David Neto5a0b5ca2016-12-09 14:01:43 -050043// Represents a vendor tool entry in the SPIR-V XML Regsitry.
44struct VendorTool {
45 uint32_t value;
46 const char* vendor;
Lei Zhang16981f82017-09-21 17:24:57 -040047 const char* tool; // Might be empty string.
48 const char* vendor_tool; // Combiantion of vendor and tool.
David Neto5a0b5ca2016-12-09 14:01:43 -050049};
50
51const VendorTool vendor_tools[] = {
52#include "generators.inc"
53};
54
Lei Zhanga94701d2015-09-14 10:05:37 -040055} // anonymous namespace
David Neto78c3b432015-08-27 13:03:52 -040056
David Neto5a0b5ca2016-12-09 14:01:43 -050057// TODO(dneto): Move this to another file. It doesn't belong with opcode
58// processing.
Lei Zhang1a0334e2015-11-02 09:41:20 -050059const char* spvGeneratorStr(uint32_t generator) {
David Neto5a0b5ca2016-12-09 14:01:43 -050060 auto where = std::find_if(
61 std::begin(vendor_tools), std::end(vendor_tools),
62 [generator](const VendorTool& vt) { return generator == vt.value; });
63 if (where != std::end(vendor_tools)) return where->vendor_tool;
64 return "Unknown";
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010065}
66
Lei Zhangb36e7042015-10-28 13:40:52 -040067uint32_t spvOpcodeMake(uint16_t wordCount, SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010068 return ((uint32_t)opcode) | (((uint32_t)wordCount) << 16);
69}
70
Lei Zhang6fa3f8a2016-03-31 17:26:31 -040071void spvOpcodeSplit(const uint32_t word, uint16_t* pWordCount,
72 uint16_t* pOpcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010073 if (pWordCount) {
74 *pWordCount = (uint16_t)((0xffff0000 & word) >> 16);
75 }
76 if (pOpcode) {
Lei Zhang6fa3f8a2016-03-31 17:26:31 -040077 *pOpcode = 0x0000ffff & word;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010078 }
79}
80
Dejan Mircevskicb3c49e2016-04-07 14:41:34 -040081spv_result_t spvOpcodeTableGet(spv_opcode_table* pInstTable,
82 spv_target_env env) {
Lei Zhang40056702015-09-11 14:31:27 -040083 if (!pInstTable) return SPV_ERROR_INVALID_POINTER;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010084
Lei Zhang16981f82017-09-21 17:24:57 -040085 // Descriptions of each opcode. Each entry describes the format of the
86 // instruction that follows a particular opcode.
87 static const spv_opcode_desc_t opcodeTableEntries_1_0[] = {
88#include "core.insts-1.0.inc"
89 };
90 static const spv_opcode_desc_t opcodeTableEntries_1_1[] = {
91#include "core.insts-1.1.inc"
92 };
93
94 const auto ptr_len = getOpcodeTableEntries_1_2();
95
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};
Lei Zhang16981f82017-09-21 17:24:57 -0400100 static const spv_opcode_table_t table_1_2 = {ptr_len.len, ptr_len.ptr};
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100101
Dejan Mircevskicb3c49e2016-04-07 14:41:34 -0400102 switch (env) {
103 case SPV_ENV_UNIVERSAL_1_0:
104 case SPV_ENV_VULKAN_1_0:
David Netoc2967012016-08-05 18:19:30 -0400105 case SPV_ENV_OPENCL_2_1:
106 case SPV_ENV_OPENGL_4_0:
107 case SPV_ENV_OPENGL_4_1:
108 case SPV_ENV_OPENGL_4_2:
109 case SPV_ENV_OPENGL_4_3:
110 case SPV_ENV_OPENGL_4_5:
Dejan Mircevskicb3c49e2016-04-07 14:41:34 -0400111 *pInstTable = &table_1_0;
112 return SPV_SUCCESS;
113 case SPV_ENV_UNIVERSAL_1_1:
114 *pInstTable = &table_1_1;
115 return SPV_SUCCESS;
David Netodbc20492017-03-14 12:43:41 -0400116 case SPV_ENV_UNIVERSAL_1_2:
117 case SPV_ENV_OPENCL_2_2:
118 *pInstTable = &table_1_2;
119 return SPV_SUCCESS;
Dejan Mircevskicb3c49e2016-04-07 14:41:34 -0400120 }
121 assert(0 && "Unknown spv_target_env in spvOpcodeTableGet()");
122 return SPV_ERROR_INVALID_TABLE;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100123}
124
125spv_result_t spvOpcodeTableNameLookup(const spv_opcode_table table,
Lei Zhang1a0334e2015-11-02 09:41:20 -0500126 const char* name,
127 spv_opcode_desc* pEntry) {
Lei Zhang40056702015-09-11 14:31:27 -0400128 if (!name || !pEntry) return SPV_ERROR_INVALID_POINTER;
129 if (!table) return SPV_ERROR_INVALID_TABLE;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100130
131 // TODO: This lookup of the Opcode table is suboptimal! Binary sort would be
132 // preferable but the table requires sorting on the Opcode name, but it's
133 // static
134 // const initialized and matches the order of the spec.
135 const size_t nameLength = strlen(name);
136 for (uint64_t opcodeIndex = 0; opcodeIndex < table->count; ++opcodeIndex) {
137 if (nameLength == strlen(table->entries[opcodeIndex].name) &&
138 !strncmp(name, table->entries[opcodeIndex].name, nameLength)) {
139 // NOTE: Found out Opcode!
140 *pEntry = &table->entries[opcodeIndex];
141 return SPV_SUCCESS;
142 }
143 }
144
145 return SPV_ERROR_INVALID_LOOKUP;
146}
147
148spv_result_t spvOpcodeTableValueLookup(const spv_opcode_table table,
Lei Zhangb36e7042015-10-28 13:40:52 -0400149 const SpvOp opcode,
Lei Zhang1a0334e2015-11-02 09:41:20 -0500150 spv_opcode_desc* pEntry) {
Lei Zhang40056702015-09-11 14:31:27 -0400151 if (!table) return SPV_ERROR_INVALID_TABLE;
152 if (!pEntry) return SPV_ERROR_INVALID_POINTER;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100153
154 // TODO: As above this lookup is not optimal.
155 for (uint64_t opcodeIndex = 0; opcodeIndex < table->count; ++opcodeIndex) {
156 if (opcode == table->entries[opcodeIndex].opcode) {
157 // NOTE: Found the Opcode!
158 *pEntry = &table->entries[opcodeIndex];
159 return SPV_SUCCESS;
160 }
161 }
162
163 return SPV_ERROR_INVALID_LOOKUP;
164}
165
Lei Zhang1a0334e2015-11-02 09:41:20 -0500166void spvInstructionCopy(const uint32_t* words, const SpvOp opcode,
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100167 const uint16_t wordCount, const spv_endianness_t endian,
Lei Zhang1a0334e2015-11-02 09:41:20 -0500168 spv_instruction_t* pInst) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100169 pInst->opcode = opcode;
David Netob5dc8fc2015-10-06 16:22:00 -0400170 pInst->words.resize(wordCount);
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100171 for (uint16_t wordIndex = 0; wordIndex < wordCount; ++wordIndex) {
172 pInst->words[wordIndex] = spvFixWord(words[wordIndex], endian);
173 if (!wordIndex) {
174 uint16_t thisWordCount;
Lei Zhang6fa3f8a2016-03-31 17:26:31 -0400175 uint16_t thisOpcode;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100176 spvOpcodeSplit(pInst->words[wordIndex], &thisWordCount, &thisOpcode);
Lei Zhang6fa3f8a2016-03-31 17:26:31 -0400177 assert(opcode == static_cast<SpvOp>(thisOpcode) &&
178 wordCount == thisWordCount && "Endianness failed!");
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100179 }
180 }
181}
182
Lei Zhang1a0334e2015-11-02 09:41:20 -0500183const char* spvOpcodeString(const SpvOp opcode) {
Dejan Mircevskicb3c49e2016-04-07 14:41:34 -0400184 // Use the latest SPIR-V version, which should be backward-compatible with all
185 // previous ones.
Lei Zhang16981f82017-09-21 17:24:57 -0400186 const auto entries = getOpcodeTableEntries_1_2();
187
188 for (uint32_t i = 0; i < entries.len; ++i) {
189 if (entries.ptr[i].opcode == opcode) return entries.ptr[i].name;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100190 }
Lei Zhang16981f82017-09-21 17:24:57 -0400191
Lei Zhang4f293b72016-03-21 16:36:14 -0400192 assert(0 && "Unreachable!");
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100193 return "unknown";
194}
195
Lei Zhangb36e7042015-10-28 13:40:52 -0400196int32_t spvOpcodeIsScalarType(const SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100197 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400198 case SpvOpTypeInt:
199 case SpvOpTypeFloat:
Dejan Mircevski276a7242016-01-21 15:55:43 -0500200 case SpvOpTypeBool:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100201 return true;
202 default:
203 return false;
204 }
205}
206
Lei Zhangb36e7042015-10-28 13:40:52 -0400207int32_t spvOpcodeIsConstant(const SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100208 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400209 case SpvOpConstantTrue:
210 case SpvOpConstantFalse:
211 case SpvOpConstant:
212 case SpvOpConstantComposite:
213 case SpvOpConstantSampler:
Lei Zhangb36e7042015-10-28 13:40:52 -0400214 case SpvOpConstantNull:
215 case SpvOpSpecConstantTrue:
216 case SpvOpSpecConstantFalse:
217 case SpvOpSpecConstant:
218 case SpvOpSpecConstantComposite:
Dejan Mircevski3fb26762016-04-04 15:55:05 -0400219 case SpvOpSpecConstantOp:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100220 return true;
221 default:
222 return false;
223 }
224}
225
David Neto1f3fb502016-09-14 11:57:20 -0400226bool spvOpcodeIsConstantOrUndef(const SpvOp opcode) {
227 return opcode == SpvOpUndef || spvOpcodeIsConstant(opcode);
228}
229
Aliya Pazylbekovaedb52642017-02-24 20:43:28 -0500230bool spvOpcodeIsScalarSpecConstant(const SpvOp opcode) {
231 switch (opcode) {
232 case SpvOpSpecConstantTrue:
233 case SpvOpSpecConstantFalse:
234 case SpvOpSpecConstant:
235 return true;
236 default:
237 return false;
238 }
239}
240
Lei Zhangb36e7042015-10-28 13:40:52 -0400241int32_t spvOpcodeIsComposite(const SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100242 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400243 case SpvOpTypeVector:
244 case SpvOpTypeMatrix:
245 case SpvOpTypeArray:
246 case SpvOpTypeStruct:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100247 return true;
248 default:
249 return false;
250 }
251}
252
Ehsan Nasiri23af06c2017-02-01 15:37:39 -0500253bool spvOpcodeReturnsLogicalVariablePointer(const SpvOp opcode) {
254 switch (opcode) {
255 case SpvOpVariable:
256 case SpvOpAccessChain:
257 case SpvOpInBoundsAccessChain:
258 case SpvOpFunctionParameter:
259 case SpvOpImageTexelPointer:
260 case SpvOpCopyObject:
261 case SpvOpSelect:
262 case SpvOpPhi:
263 case SpvOpFunctionCall:
264 case SpvOpPtrAccessChain:
265 case SpvOpLoad:
266 case SpvOpConstantNull:
267 return true;
268 default:
269 return false;
270 }
271}
272
Florian Ziesche66fcb452016-03-02 22:17:54 +0100273int32_t spvOpcodeReturnsLogicalPointer(const SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100274 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400275 case SpvOpVariable:
276 case SpvOpAccessChain:
277 case SpvOpInBoundsAccessChain:
278 case SpvOpFunctionParameter:
Florian Ziesche66fcb452016-03-02 22:17:54 +0100279 case SpvOpImageTexelPointer:
280 case SpvOpCopyObject:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100281 return true;
282 default:
283 return false;
284 }
285}
286
Lei Zhangb36e7042015-10-28 13:40:52 -0400287int32_t spvOpcodeGeneratesType(SpvOp op) {
Lei Zhang1a0334e2015-11-02 09:41:20 -0500288 switch (op) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400289 case SpvOpTypeVoid:
290 case SpvOpTypeBool:
291 case SpvOpTypeInt:
292 case SpvOpTypeFloat:
293 case SpvOpTypeVector:
294 case SpvOpTypeMatrix:
295 case SpvOpTypeImage:
296 case SpvOpTypeSampler:
297 case SpvOpTypeSampledImage:
298 case SpvOpTypeArray:
299 case SpvOpTypeRuntimeArray:
300 case SpvOpTypeStruct:
301 case SpvOpTypeOpaque:
302 case SpvOpTypePointer:
303 case SpvOpTypeFunction:
304 case SpvOpTypeEvent:
305 case SpvOpTypeDeviceEvent:
306 case SpvOpTypeReserveId:
307 case SpvOpTypeQueue:
308 case SpvOpTypePipe:
Andrey Tuganov4ef3b3e2017-02-28 11:53:47 -0500309 case SpvOpTypePipeStorage:
310 case SpvOpTypeNamedBarrier:
Andrew Woloszyn537e7762015-09-29 11:28:34 -0400311 return true;
David Netoaef608c2015-11-02 14:59:02 -0500312 default:
313 // In particular, OpTypeForwardPointer does not generate a type,
314 // but declares a storage class for a pointer type generated
315 // by a different instruction.
316 break;
Andrew Woloszyn537e7762015-09-29 11:28:34 -0400317 }
318 return 0;
319}