blob: aded40413a2881c761a8803b6241b1572f3bc966 [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
Lei Zhang972788b2015-11-12 13:48:30 -050020#include <cstdlib>
21
Lei Zhang923f6c12015-11-11 12:45:23 -050022#include "instruction.h"
Lei Zhangca1bf942016-04-27 16:47:13 -040023#include "macro.h"
David Neto5a703352016-02-17 14:44:00 -050024#include "spirv-tools/libspirv.h"
Lei Zhangaa056cd2015-11-11 14:24:04 -050025#include "spirv_constant.h"
David Neto4c215712015-12-22 15:08:41 -050026#include "spirv_endian.h"
Lei Zhang923f6c12015-11-11 12:45:23 -050027
David Neto78c3b432015-08-27 13:03:52 -040028namespace {
29
30// Descriptions of each opcode. Each entry describes the format of the
31// instruction that follows a particular opcode.
Dejan Mircevskicb3c49e2016-04-07 14:41:34 -040032const spv_opcode_desc_t opcodeTableEntries_1_0[] = {
Lei Zhang10dba912016-04-14 14:05:53 -040033#include "core.insts-1.0.inc"
David Neto78c3b432015-08-27 13:03:52 -040034};
Dejan Mircevskicb3c49e2016-04-07 14:41:34 -040035const spv_opcode_desc_t opcodeTableEntries_1_1[] = {
Lei Zhang10dba912016-04-14 14:05:53 -040036#include "core.insts-1.1.inc"
Dejan Mircevskicb3c49e2016-04-07 14:41:34 -040037};
David Neto78c3b432015-08-27 13:03:52 -040038
Lei Zhanga94701d2015-09-14 10:05:37 -040039} // anonymous namespace
David Neto78c3b432015-08-27 13:03:52 -040040
Lei Zhang1a0334e2015-11-02 09:41:20 -050041const char* spvGeneratorStr(uint32_t generator) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010042 switch (generator) {
43 case SPV_GENERATOR_KHRONOS:
44 return "Khronos";
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010045 case SPV_GENERATOR_LUNARG:
46 return "LunarG";
David Neto1780fc42015-10-26 15:43:12 -040047 case SPV_GENERATOR_VALVE:
48 return "Valve";
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010049 case SPV_GENERATOR_CODEPLAY:
50 return "Codeplay Software Ltd.";
David Neto1780fc42015-10-26 15:43:12 -040051 case SPV_GENERATOR_NVIDIA:
52 return "NVIDIA";
53 case SPV_GENERATOR_ARM:
54 return "ARM";
David Neto14b93e42015-11-12 18:33:47 -050055 case SPV_GENERATOR_KHRONOS_LLVM_TRANSLATOR:
56 return "Khronos LLVM/SPIR-V Translator";
57 case SPV_GENERATOR_KHRONOS_ASSEMBLER:
58 return "Khronos SPIR-V Tools Assembler";
David Neto2266ba12015-11-13 12:03:28 -060059 case SPV_GENERATOR_KHRONOS_GLSLANG:
60 return "Khronos Glslang Reference Front End";
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010061 default:
62 return "Unknown";
63 }
64}
65
Lei Zhangb36e7042015-10-28 13:40:52 -040066uint32_t spvOpcodeMake(uint16_t wordCount, SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010067 return ((uint32_t)opcode) | (((uint32_t)wordCount) << 16);
68}
69
Lei Zhang6fa3f8a2016-03-31 17:26:31 -040070void spvOpcodeSplit(const uint32_t word, uint16_t* pWordCount,
71 uint16_t* pOpcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010072 if (pWordCount) {
73 *pWordCount = (uint16_t)((0xffff0000 & word) >> 16);
74 }
75 if (pOpcode) {
Lei Zhang6fa3f8a2016-03-31 17:26:31 -040076 *pOpcode = 0x0000ffff & word;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010077 }
78}
79
Dejan Mircevskicb3c49e2016-04-07 14:41:34 -040080spv_result_t spvOpcodeTableGet(spv_opcode_table* pInstTable,
81 spv_target_env env) {
Lei Zhang40056702015-09-11 14:31:27 -040082 if (!pInstTable) return SPV_ERROR_INVALID_POINTER;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010083
Dejan Mircevskicb3c49e2016-04-07 14:41:34 -040084 static const spv_opcode_table_t table_1_0 = {
85 ARRAY_SIZE(opcodeTableEntries_1_0), opcodeTableEntries_1_0};
86 static const spv_opcode_table_t table_1_1 = {
87 ARRAY_SIZE(opcodeTableEntries_1_1), opcodeTableEntries_1_1};
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +010088
Dejan Mircevskicb3c49e2016-04-07 14:41:34 -040089 switch (env) {
90 case SPV_ENV_UNIVERSAL_1_0:
91 case SPV_ENV_VULKAN_1_0:
David Netoc2967012016-08-05 18:19:30 -040092 case SPV_ENV_OPENCL_2_1:
93 case SPV_ENV_OPENGL_4_0:
94 case SPV_ENV_OPENGL_4_1:
95 case SPV_ENV_OPENGL_4_2:
96 case SPV_ENV_OPENGL_4_3:
97 case SPV_ENV_OPENGL_4_5:
Dejan Mircevskicb3c49e2016-04-07 14:41:34 -040098 *pInstTable = &table_1_0;
99 return SPV_SUCCESS;
100 case SPV_ENV_UNIVERSAL_1_1:
David Netoc2967012016-08-05 18:19:30 -0400101 case SPV_ENV_OPENCL_2_2:
Dejan Mircevskicb3c49e2016-04-07 14:41:34 -0400102 *pInstTable = &table_1_1;
103 return SPV_SUCCESS;
104 }
105 assert(0 && "Unknown spv_target_env in spvOpcodeTableGet()");
106 return SPV_ERROR_INVALID_TABLE;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100107}
108
109spv_result_t spvOpcodeTableNameLookup(const spv_opcode_table table,
Lei Zhang1a0334e2015-11-02 09:41:20 -0500110 const char* name,
111 spv_opcode_desc* pEntry) {
Lei Zhang40056702015-09-11 14:31:27 -0400112 if (!name || !pEntry) return SPV_ERROR_INVALID_POINTER;
113 if (!table) return SPV_ERROR_INVALID_TABLE;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100114
115 // TODO: This lookup of the Opcode table is suboptimal! Binary sort would be
116 // preferable but the table requires sorting on the Opcode name, but it's
117 // static
118 // const initialized and matches the order of the spec.
119 const size_t nameLength = strlen(name);
120 for (uint64_t opcodeIndex = 0; opcodeIndex < table->count; ++opcodeIndex) {
121 if (nameLength == strlen(table->entries[opcodeIndex].name) &&
122 !strncmp(name, table->entries[opcodeIndex].name, nameLength)) {
123 // NOTE: Found out Opcode!
124 *pEntry = &table->entries[opcodeIndex];
125 return SPV_SUCCESS;
126 }
127 }
128
129 return SPV_ERROR_INVALID_LOOKUP;
130}
131
132spv_result_t spvOpcodeTableValueLookup(const spv_opcode_table table,
Lei Zhangb36e7042015-10-28 13:40:52 -0400133 const SpvOp opcode,
Lei Zhang1a0334e2015-11-02 09:41:20 -0500134 spv_opcode_desc* pEntry) {
Lei Zhang40056702015-09-11 14:31:27 -0400135 if (!table) return SPV_ERROR_INVALID_TABLE;
136 if (!pEntry) return SPV_ERROR_INVALID_POINTER;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100137
138 // TODO: As above this lookup is not optimal.
139 for (uint64_t opcodeIndex = 0; opcodeIndex < table->count; ++opcodeIndex) {
140 if (opcode == table->entries[opcodeIndex].opcode) {
141 // NOTE: Found the Opcode!
142 *pEntry = &table->entries[opcodeIndex];
143 return SPV_SUCCESS;
144 }
145 }
146
147 return SPV_ERROR_INVALID_LOOKUP;
148}
149
Lei Zhang1a0334e2015-11-02 09:41:20 -0500150void spvInstructionCopy(const uint32_t* words, const SpvOp opcode,
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100151 const uint16_t wordCount, const spv_endianness_t endian,
Lei Zhang1a0334e2015-11-02 09:41:20 -0500152 spv_instruction_t* pInst) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100153 pInst->opcode = opcode;
David Netob5dc8fc2015-10-06 16:22:00 -0400154 pInst->words.resize(wordCount);
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100155 for (uint16_t wordIndex = 0; wordIndex < wordCount; ++wordIndex) {
156 pInst->words[wordIndex] = spvFixWord(words[wordIndex], endian);
157 if (!wordIndex) {
158 uint16_t thisWordCount;
Lei Zhang6fa3f8a2016-03-31 17:26:31 -0400159 uint16_t thisOpcode;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100160 spvOpcodeSplit(pInst->words[wordIndex], &thisWordCount, &thisOpcode);
Lei Zhang6fa3f8a2016-03-31 17:26:31 -0400161 assert(opcode == static_cast<SpvOp>(thisOpcode) &&
162 wordCount == thisWordCount && "Endianness failed!");
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100163 }
164 }
165}
166
Lei Zhang1a0334e2015-11-02 09:41:20 -0500167const char* spvOpcodeString(const SpvOp opcode) {
Dejan Mircevskicb3c49e2016-04-07 14:41:34 -0400168 // Use the latest SPIR-V version, which should be backward-compatible with all
169 // previous ones.
Lei Zhangca1bf942016-04-27 16:47:13 -0400170 for (uint32_t i = 0; i < ARRAY_SIZE(opcodeTableEntries_1_1); ++i) {
Dejan Mircevskicb3c49e2016-04-07 14:41:34 -0400171 if (opcodeTableEntries_1_1[i].opcode == opcode)
172 return opcodeTableEntries_1_1[i].name;
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100173 }
Lei Zhang4f293b72016-03-21 16:36:14 -0400174 assert(0 && "Unreachable!");
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100175 return "unknown";
176}
177
Lei Zhangb36e7042015-10-28 13:40:52 -0400178int32_t spvOpcodeIsScalarType(const SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100179 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400180 case SpvOpTypeInt:
181 case SpvOpTypeFloat:
Dejan Mircevski276a7242016-01-21 15:55:43 -0500182 case SpvOpTypeBool:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100183 return true;
184 default:
185 return false;
186 }
187}
188
Lei Zhangb36e7042015-10-28 13:40:52 -0400189int32_t spvOpcodeIsConstant(const SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100190 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400191 case SpvOpConstantTrue:
192 case SpvOpConstantFalse:
193 case SpvOpConstant:
194 case SpvOpConstantComposite:
195 case SpvOpConstantSampler:
Lei Zhangb36e7042015-10-28 13:40:52 -0400196 case SpvOpConstantNull:
197 case SpvOpSpecConstantTrue:
198 case SpvOpSpecConstantFalse:
199 case SpvOpSpecConstant:
200 case SpvOpSpecConstantComposite:
Dejan Mircevski3fb26762016-04-04 15:55:05 -0400201 case SpvOpSpecConstantOp:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100202 return true;
203 default:
204 return false;
205 }
206}
207
Lei Zhangb36e7042015-10-28 13:40:52 -0400208int32_t spvOpcodeIsComposite(const SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100209 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400210 case SpvOpTypeVector:
211 case SpvOpTypeMatrix:
212 case SpvOpTypeArray:
213 case SpvOpTypeStruct:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100214 return true;
215 default:
216 return false;
217 }
218}
219
Florian Ziesche66fcb452016-03-02 22:17:54 +0100220int32_t spvOpcodeReturnsLogicalPointer(const SpvOp opcode) {
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100221 switch (opcode) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400222 case SpvOpVariable:
223 case SpvOpAccessChain:
224 case SpvOpInBoundsAccessChain:
225 case SpvOpFunctionParameter:
Florian Ziesche66fcb452016-03-02 22:17:54 +0100226 case SpvOpImageTexelPointer:
227 case SpvOpCopyObject:
Kenneth Benzie (Benie)83e5a292015-05-22 18:26:19 +0100228 return true;
229 default:
230 return false;
231 }
232}
233
Lei Zhangb36e7042015-10-28 13:40:52 -0400234int32_t spvOpcodeGeneratesType(SpvOp op) {
Lei Zhang1a0334e2015-11-02 09:41:20 -0500235 switch (op) {
Lei Zhangb36e7042015-10-28 13:40:52 -0400236 case SpvOpTypeVoid:
237 case SpvOpTypeBool:
238 case SpvOpTypeInt:
239 case SpvOpTypeFloat:
240 case SpvOpTypeVector:
241 case SpvOpTypeMatrix:
242 case SpvOpTypeImage:
243 case SpvOpTypeSampler:
244 case SpvOpTypeSampledImage:
245 case SpvOpTypeArray:
246 case SpvOpTypeRuntimeArray:
247 case SpvOpTypeStruct:
248 case SpvOpTypeOpaque:
249 case SpvOpTypePointer:
250 case SpvOpTypeFunction:
251 case SpvOpTypeEvent:
252 case SpvOpTypeDeviceEvent:
253 case SpvOpTypeReserveId:
254 case SpvOpTypeQueue:
255 case SpvOpTypePipe:
Andrew Woloszyn537e7762015-09-29 11:28:34 -0400256 return true;
David Netoaef608c2015-11-02 14:59:02 -0500257 default:
258 // In particular, OpTypeForwardPointer does not generate a type,
259 // but declares a storage class for a pointer type generated
260 // by a different instruction.
261 break;
Andrew Woloszyn537e7762015-09-29 11:28:34 -0400262 }
263 return 0;
264}