blob: ac87c707d70358357301e832ee79602b67a3294d [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 {
30
31// Descriptions of each opcode. Each entry describes the format of the
32// instruction that follows a particular opcode.
Dejan Mircevskicb3c49e2016-04-07 14:41:34 -040033const spv_opcode_desc_t opcodeTableEntries_1_0[] = {
Lei Zhang10dba912016-04-14 14:05:53 -040034#include "core.insts-1.0.inc"
David Neto78c3b432015-08-27 13:03:52 -040035};
Dejan Mircevskicb3c49e2016-04-07 14:41:34 -040036const spv_opcode_desc_t opcodeTableEntries_1_1[] = {
Lei Zhang10dba912016-04-14 14:05:53 -040037#include "core.insts-1.1.inc"
Dejan Mircevskicb3c49e2016-04-07 14:41:34 -040038};
David Neto78c3b432015-08-27 13:03:52 -040039
David Neto5a0b5ca2016-12-09 14:01:43 -050040// Represents a vendor tool entry in the SPIR-V XML Regsitry.
41struct VendorTool {
42 uint32_t value;
43 const char* vendor;
44 const char* tool; // Might be empty string.
45 const char* vendor_tool; // Combiantion of vendor and tool.
46};
47
48const VendorTool vendor_tools[] = {
49#include "generators.inc"
50};
51
Lei Zhanga94701d2015-09-14 10:05:37 -040052} // anonymous namespace
David Neto78c3b432015-08-27 13:03:52 -040053
David Neto5a0b5ca2016-12-09 14:01:43 -050054// TODO(dneto): Move this to another file. It doesn't belong with opcode
55// processing.
Lei Zhang1a0334e2015-11-02 09:41:20 -050056const char* spvGeneratorStr(uint32_t generator) {
David Neto5a0b5ca2016-12-09 14:01:43 -050057 auto where = std::find_if(
58 std::begin(vendor_tools), std::end(vendor_tools),
59 [generator](const VendorTool& vt) { return generator == vt.value; });
60 if (where != std::end(vendor_tools)) return where->vendor_tool;
61 return "Unknown";
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010062}
63
Lei Zhangb36e7042015-10-28 13:40:52 -040064uint32_t spvOpcodeMake(uint16_t wordCount, SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010065 return ((uint32_t)opcode) | (((uint32_t)wordCount) << 16);
66}
67
Lei Zhang6fa3f8a2016-03-31 17:26:31 -040068void spvOpcodeSplit(const uint32_t word, uint16_t* pWordCount,
69 uint16_t* pOpcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010070 if (pWordCount) {
71 *pWordCount = (uint16_t)((0xffff0000 & word) >> 16);
72 }
73 if (pOpcode) {
Lei Zhang6fa3f8a2016-03-31 17:26:31 -040074 *pOpcode = 0x0000ffff & word;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010075 }
76}
77
Dejan Mircevskicb3c49e2016-04-07 14:41:34 -040078spv_result_t spvOpcodeTableGet(spv_opcode_table* pInstTable,
79 spv_target_env env) {
Lei Zhang40056702015-09-11 14:31:27 -040080 if (!pInstTable) return SPV_ERROR_INVALID_POINTER;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010081
Dejan Mircevskicb3c49e2016-04-07 14:41:34 -040082 static const spv_opcode_table_t table_1_0 = {
83 ARRAY_SIZE(opcodeTableEntries_1_0), opcodeTableEntries_1_0};
84 static const spv_opcode_table_t table_1_1 = {
85 ARRAY_SIZE(opcodeTableEntries_1_1), opcodeTableEntries_1_1};
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010086
Dejan Mircevskicb3c49e2016-04-07 14:41:34 -040087 switch (env) {
88 case SPV_ENV_UNIVERSAL_1_0:
89 case SPV_ENV_VULKAN_1_0:
David Netoc2967012016-08-05 18:19:30 -040090 case SPV_ENV_OPENCL_2_1:
91 case SPV_ENV_OPENGL_4_0:
92 case SPV_ENV_OPENGL_4_1:
93 case SPV_ENV_OPENGL_4_2:
94 case SPV_ENV_OPENGL_4_3:
95 case SPV_ENV_OPENGL_4_5:
Dejan Mircevskicb3c49e2016-04-07 14:41:34 -040096 *pInstTable = &table_1_0;
97 return SPV_SUCCESS;
98 case SPV_ENV_UNIVERSAL_1_1:
David Netoc2967012016-08-05 18:19:30 -040099 case SPV_ENV_OPENCL_2_2:
Dejan Mircevskicb3c49e2016-04-07 14:41:34 -0400100 *pInstTable = &table_1_1;
101 return SPV_SUCCESS;
102 }
103 assert(0 && "Unknown spv_target_env in spvOpcodeTableGet()");
104 return SPV_ERROR_INVALID_TABLE;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100105}
106
107spv_result_t spvOpcodeTableNameLookup(const spv_opcode_table table,
Lei Zhang1a0334e2015-11-02 09:41:20 -0500108 const char* name,
109 spv_opcode_desc* pEntry) {
Lei Zhang40056702015-09-11 14:31:27 -0400110 if (!name || !pEntry) return SPV_ERROR_INVALID_POINTER;
111 if (!table) return SPV_ERROR_INVALID_TABLE;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100112
113 // TODO: This lookup of the Opcode table is suboptimal! Binary sort would be
114 // preferable but the table requires sorting on the Opcode name, but it's
115 // static
116 // const initialized and matches the order of the spec.
117 const size_t nameLength = strlen(name);
118 for (uint64_t opcodeIndex = 0; opcodeIndex < table->count; ++opcodeIndex) {
119 if (nameLength == strlen(table->entries[opcodeIndex].name) &&
120 !strncmp(name, table->entries[opcodeIndex].name, nameLength)) {
121 // NOTE: Found out Opcode!
122 *pEntry = &table->entries[opcodeIndex];
123 return SPV_SUCCESS;
124 }
125 }
126
127 return SPV_ERROR_INVALID_LOOKUP;
128}
129
130spv_result_t spvOpcodeTableValueLookup(const spv_opcode_table table,
Lei Zhangb36e7042015-10-28 13:40:52 -0400131 const SpvOp opcode,
Lei Zhang1a0334e2015-11-02 09:41:20 -0500132 spv_opcode_desc* pEntry) {
Lei Zhang40056702015-09-11 14:31:27 -0400133 if (!table) return SPV_ERROR_INVALID_TABLE;
134 if (!pEntry) return SPV_ERROR_INVALID_POINTER;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100135
136 // TODO: As above this lookup is not optimal.
137 for (uint64_t opcodeIndex = 0; opcodeIndex < table->count; ++opcodeIndex) {
138 if (opcode == table->entries[opcodeIndex].opcode) {
139 // NOTE: Found the Opcode!
140 *pEntry = &table->entries[opcodeIndex];
141 return SPV_SUCCESS;
142 }
143 }
144
145 return SPV_ERROR_INVALID_LOOKUP;
146}
147
Lei Zhang1a0334e2015-11-02 09:41:20 -0500148void spvInstructionCopy(const uint32_t* words, const SpvOp opcode,
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100149 const uint16_t wordCount, const spv_endianness_t endian,
Lei Zhang1a0334e2015-11-02 09:41:20 -0500150 spv_instruction_t* pInst) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100151 pInst->opcode = opcode;
David Netob5dc8fc2015-10-06 16:22:00 -0400152 pInst->words.resize(wordCount);
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100153 for (uint16_t wordIndex = 0; wordIndex < wordCount; ++wordIndex) {
154 pInst->words[wordIndex] = spvFixWord(words[wordIndex], endian);
155 if (!wordIndex) {
156 uint16_t thisWordCount;
Lei Zhang6fa3f8a2016-03-31 17:26:31 -0400157 uint16_t thisOpcode;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100158 spvOpcodeSplit(pInst->words[wordIndex], &thisWordCount, &thisOpcode);
Lei Zhang6fa3f8a2016-03-31 17:26:31 -0400159 assert(opcode == static_cast<SpvOp>(thisOpcode) &&
160 wordCount == thisWordCount && "Endianness failed!");
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100161 }
162 }
163}
164
Lei Zhang1a0334e2015-11-02 09:41:20 -0500165const char* spvOpcodeString(const SpvOp opcode) {
Dejan Mircevskicb3c49e2016-04-07 14:41:34 -0400166 // Use the latest SPIR-V version, which should be backward-compatible with all
167 // previous ones.
Lei Zhangca1bf942016-04-27 16:47:13 -0400168 for (uint32_t i = 0; i < ARRAY_SIZE(opcodeTableEntries_1_1); ++i) {
Dejan Mircevskicb3c49e2016-04-07 14:41:34 -0400169 if (opcodeTableEntries_1_1[i].opcode == opcode)
170 return opcodeTableEntries_1_1[i].name;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100171 }
Lei Zhang4f293b72016-03-21 16:36:14 -0400172 assert(0 && "Unreachable!");
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100173 return "unknown";
174}
175
Lei Zhangb36e7042015-10-28 13:40:52 -0400176int32_t spvOpcodeIsScalarType(const SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100177 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400178 case SpvOpTypeInt:
179 case SpvOpTypeFloat:
Dejan Mircevski276a7242016-01-21 15:55:43 -0500180 case SpvOpTypeBool:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100181 return true;
182 default:
183 return false;
184 }
185}
186
Lei Zhangb36e7042015-10-28 13:40:52 -0400187int32_t spvOpcodeIsConstant(const SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100188 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400189 case SpvOpConstantTrue:
190 case SpvOpConstantFalse:
191 case SpvOpConstant:
192 case SpvOpConstantComposite:
193 case SpvOpConstantSampler:
Lei Zhangb36e7042015-10-28 13:40:52 -0400194 case SpvOpConstantNull:
195 case SpvOpSpecConstantTrue:
196 case SpvOpSpecConstantFalse:
197 case SpvOpSpecConstant:
198 case SpvOpSpecConstantComposite:
Dejan Mircevski3fb26762016-04-04 15:55:05 -0400199 case SpvOpSpecConstantOp:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100200 return true;
201 default:
202 return false;
203 }
204}
205
David Neto1f3fb502016-09-14 11:57:20 -0400206bool spvOpcodeIsConstantOrUndef(const SpvOp opcode) {
207 return opcode == SpvOpUndef || spvOpcodeIsConstant(opcode);
208}
209
Lei Zhangb36e7042015-10-28 13:40:52 -0400210int32_t spvOpcodeIsComposite(const SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100211 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400212 case SpvOpTypeVector:
213 case SpvOpTypeMatrix:
214 case SpvOpTypeArray:
215 case SpvOpTypeStruct:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100216 return true;
217 default:
218 return false;
219 }
220}
221
Florian Ziesche66fcb452016-03-02 22:17:54 +0100222int32_t spvOpcodeReturnsLogicalPointer(const SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100223 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400224 case SpvOpVariable:
225 case SpvOpAccessChain:
226 case SpvOpInBoundsAccessChain:
227 case SpvOpFunctionParameter:
Florian Ziesche66fcb452016-03-02 22:17:54 +0100228 case SpvOpImageTexelPointer:
229 case SpvOpCopyObject:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100230 return true;
231 default:
232 return false;
233 }
234}
235
Lei Zhangb36e7042015-10-28 13:40:52 -0400236int32_t spvOpcodeGeneratesType(SpvOp op) {
Lei Zhang1a0334e2015-11-02 09:41:20 -0500237 switch (op) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400238 case SpvOpTypeVoid:
239 case SpvOpTypeBool:
240 case SpvOpTypeInt:
241 case SpvOpTypeFloat:
242 case SpvOpTypeVector:
243 case SpvOpTypeMatrix:
244 case SpvOpTypeImage:
245 case SpvOpTypeSampler:
246 case SpvOpTypeSampledImage:
247 case SpvOpTypeArray:
248 case SpvOpTypeRuntimeArray:
249 case SpvOpTypeStruct:
250 case SpvOpTypeOpaque:
251 case SpvOpTypePointer:
252 case SpvOpTypeFunction:
253 case SpvOpTypeEvent:
254 case SpvOpTypeDeviceEvent:
255 case SpvOpTypeReserveId:
256 case SpvOpTypeQueue:
257 case SpvOpTypePipe:
Andrew Woloszyn537e7762015-09-29 11:28:34 -0400258 return true;
David Netoaef608c2015-11-02 14:59:02 -0500259 default:
260 // In particular, OpTypeForwardPointer does not generate a type,
261 // but declares a storage class for a pointer type generated
262 // by a different instruction.
263 break;
Andrew Woloszyn537e7762015-09-29 11:28:34 -0400264 }
265 return 0;
266}