1// Copyright (c) 2015-2016 The Khronos Group Inc.
2//
3// 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
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// 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.
14
15#include "source/ext_inst.h"
16
17#include <cstring>
18
19// DebugInfo extended instruction set.
20// See https://www.khronos.org/registry/spir-v/specs/1.0/DebugInfo.html
21// TODO(dneto): DebugInfo.h should probably move to SPIRV-Headers.
22#include "DebugInfo.h"
23
24#include "source/latest_version_glsl_std_450_header.h"
25#include "source/latest_version_opencl_std_header.h"
26#include "source/macro.h"
27#include "source/spirv_definition.h"
28
29#include "debuginfo.insts.inc"
30#include "glsl.std.450.insts.inc"
31#include "nonsemantic.clspvreflection.insts.inc"
32#include "nonsemantic.shader.debuginfo.100.insts.inc"
33#include "opencl.debuginfo.100.insts.inc"
34#include "opencl.std.insts.inc"
35
36#include "spirv-tools/libspirv.h"
37#include "spv-amd-gcn-shader.insts.inc"
38#include "spv-amd-shader-ballot.insts.inc"
39#include "spv-amd-shader-explicit-vertex-parameter.insts.inc"
40#include "spv-amd-shader-trinary-minmax.insts.inc"
41
42static const spv_ext_inst_group_t kGroups_1_0[] = {
43 {SPV_EXT_INST_TYPE_GLSL_STD_450, ARRAY_SIZE(glsl_entries), glsl_entries},
44 {SPV_EXT_INST_TYPE_OPENCL_STD, ARRAY_SIZE(opencl_entries), opencl_entries},
45 {SPV_EXT_INST_TYPE_SPV_AMD_SHADER_EXPLICIT_VERTEX_PARAMETER,
46 ARRAY_SIZE(spv_amd_shader_explicit_vertex_parameter_entries),
47 spv_amd_shader_explicit_vertex_parameter_entries},
48 {SPV_EXT_INST_TYPE_SPV_AMD_SHADER_TRINARY_MINMAX,
49 ARRAY_SIZE(spv_amd_shader_trinary_minmax_entries),
50 spv_amd_shader_trinary_minmax_entries},
51 {SPV_EXT_INST_TYPE_SPV_AMD_GCN_SHADER,
52 ARRAY_SIZE(spv_amd_gcn_shader_entries), spv_amd_gcn_shader_entries},
53 {SPV_EXT_INST_TYPE_SPV_AMD_SHADER_BALLOT,
54 ARRAY_SIZE(spv_amd_shader_ballot_entries), spv_amd_shader_ballot_entries},
55 {SPV_EXT_INST_TYPE_DEBUGINFO, ARRAY_SIZE(debuginfo_entries),
56 debuginfo_entries},
57 {SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100,
58 ARRAY_SIZE(opencl_debuginfo_100_entries), opencl_debuginfo_100_entries},
59 {SPV_EXT_INST_TYPE_NONSEMANTIC_SHADER_DEBUGINFO_100,
60 ARRAY_SIZE(nonsemantic_shader_debuginfo_100_entries),
61 nonsemantic_shader_debuginfo_100_entries},
62 {SPV_EXT_INST_TYPE_NONSEMANTIC_CLSPVREFLECTION,
63 ARRAY_SIZE(nonsemantic_clspvreflection_entries),
64 nonsemantic_clspvreflection_entries},
65};
66
67static const spv_ext_inst_table_t kTable_1_0 = {ARRAY_SIZE(kGroups_1_0),
68 kGroups_1_0};
69
70spv_result_t spvExtInstTableGet(spv_ext_inst_table* pExtInstTable,
71 spv_target_env env) {
72 if (!pExtInstTable) return SPV_ERROR_INVALID_POINTER;
73
74 switch (env) {
75 // The extended instruction sets are all version 1.0 so far.
76 case SPV_ENV_UNIVERSAL_1_0:
77 case SPV_ENV_VULKAN_1_0:
78 case SPV_ENV_UNIVERSAL_1_1:
79 case SPV_ENV_UNIVERSAL_1_2:
80 case SPV_ENV_OPENCL_1_2:
81 case SPV_ENV_OPENCL_EMBEDDED_1_2:
82 case SPV_ENV_OPENCL_2_0:
83 case SPV_ENV_OPENCL_EMBEDDED_2_0:
84 case SPV_ENV_OPENCL_2_1:
85 case SPV_ENV_OPENCL_EMBEDDED_2_1:
86 case SPV_ENV_OPENCL_2_2:
87 case SPV_ENV_OPENCL_EMBEDDED_2_2:
88 case SPV_ENV_OPENGL_4_0:
89 case SPV_ENV_OPENGL_4_1:
90 case SPV_ENV_OPENGL_4_2:
91 case SPV_ENV_OPENGL_4_3:
92 case SPV_ENV_OPENGL_4_5:
93 case SPV_ENV_UNIVERSAL_1_3:
94 case SPV_ENV_VULKAN_1_1:
95 case SPV_ENV_VULKAN_1_1_SPIRV_1_4:
96 case SPV_ENV_UNIVERSAL_1_4:
97 case SPV_ENV_UNIVERSAL_1_5:
98 case SPV_ENV_VULKAN_1_2:
99 case SPV_ENV_UNIVERSAL_1_6:
100 case SPV_ENV_VULKAN_1_3:
101 *pExtInstTable = &kTable_1_0;
102 return SPV_SUCCESS;
103 default:
104 return SPV_ERROR_INVALID_TABLE;
105 }
106}
107
108spv_ext_inst_type_t spvExtInstImportTypeGet(const char* name) {
109 // The names are specified by the respective extension instruction
110 // specifications.
111 if (!strcmp("GLSL.std.450", name)) {
112 return SPV_EXT_INST_TYPE_GLSL_STD_450;
113 }
114 if (!strcmp("OpenCL.std", name)) {
115 return SPV_EXT_INST_TYPE_OPENCL_STD;
116 }
117 if (!strcmp("SPV_AMD_shader_explicit_vertex_parameter", name)) {
118 return SPV_EXT_INST_TYPE_SPV_AMD_SHADER_EXPLICIT_VERTEX_PARAMETER;
119 }
120 if (!strcmp("SPV_AMD_shader_trinary_minmax", name)) {
121 return SPV_EXT_INST_TYPE_SPV_AMD_SHADER_TRINARY_MINMAX;
122 }
123 if (!strcmp("SPV_AMD_gcn_shader", name)) {
124 return SPV_EXT_INST_TYPE_SPV_AMD_GCN_SHADER;
125 }
126 if (!strcmp("SPV_AMD_shader_ballot", name)) {
127 return SPV_EXT_INST_TYPE_SPV_AMD_SHADER_BALLOT;
128 }
129 if (!strcmp("DebugInfo", name)) {
130 return SPV_EXT_INST_TYPE_DEBUGINFO;
131 }
132 if (!strcmp("OpenCL.DebugInfo.100", name)) {
133 return SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100;
134 }
135 if (!strcmp("NonSemantic.Shader.DebugInfo.100", name)) {
136 return SPV_EXT_INST_TYPE_NONSEMANTIC_SHADER_DEBUGINFO_100;
137 }
138 if (!strncmp("NonSemantic.ClspvReflection.", name, 28)) {
139 return SPV_EXT_INST_TYPE_NONSEMANTIC_CLSPVREFLECTION;
140 }
141 // ensure to add any known non-semantic extended instruction sets
142 // above this point, and update spvExtInstIsNonSemantic()
143 if (!strncmp("NonSemantic.", name, 12)) {
144 return SPV_EXT_INST_TYPE_NONSEMANTIC_UNKNOWN;
145 }
146 return SPV_EXT_INST_TYPE_NONE;
147}
148
149bool spvExtInstIsNonSemantic(const spv_ext_inst_type_t type) {
150 if (type == SPV_EXT_INST_TYPE_NONSEMANTIC_UNKNOWN ||
151 type == SPV_EXT_INST_TYPE_NONSEMANTIC_SHADER_DEBUGINFO_100 ||
152 type == SPV_EXT_INST_TYPE_NONSEMANTIC_CLSPVREFLECTION) {
153 return true;
154 }
155 return false;
156}
157
158bool spvExtInstIsDebugInfo(const spv_ext_inst_type_t type) {
159 if (type == SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100 ||
160 type == SPV_EXT_INST_TYPE_NONSEMANTIC_SHADER_DEBUGINFO_100 ||
161 type == SPV_EXT_INST_TYPE_DEBUGINFO) {
162 return true;
163 }
164 return false;
165}
166
167spv_result_t spvExtInstTableNameLookup(const spv_ext_inst_table table,
168 const spv_ext_inst_type_t type,
169 const char* name,
170 spv_ext_inst_desc* pEntry) {
171 if (!table) return SPV_ERROR_INVALID_TABLE;
172 if (!pEntry) return SPV_ERROR_INVALID_POINTER;
173
174 for (uint32_t groupIndex = 0; groupIndex < table->count; groupIndex++) {
175 const auto& group = table->groups[groupIndex];
176 if (type != group.type) continue;
177 for (uint32_t index = 0; index < group.count; index++) {
178 const auto& entry = group.entries[index];
179 if (!strcmp(name, entry.name)) {
180 *pEntry = &entry;
181 return SPV_SUCCESS;
182 }
183 }
184 }
185
186 return SPV_ERROR_INVALID_LOOKUP;
187}
188
189spv_result_t spvExtInstTableValueLookup(const spv_ext_inst_table table,
190 const spv_ext_inst_type_t type,
191 const uint32_t value,
192 spv_ext_inst_desc* pEntry) {
193 if (!table) return SPV_ERROR_INVALID_TABLE;
194 if (!pEntry) return SPV_ERROR_INVALID_POINTER;
195
196 for (uint32_t groupIndex = 0; groupIndex < table->count; groupIndex++) {
197 const auto& group = table->groups[groupIndex];
198 if (type != group.type) continue;
199 for (uint32_t index = 0; index < group.count; index++) {
200 const auto& entry = group.entries[index];
201 if (value == entry.ext_inst) {
202 *pEntry = &entry;
203 return SPV_SUCCESS;
204 }
205 }
206 }
207
208 return SPV_ERROR_INVALID_LOOKUP;
209}
210