1 // Copyright (c) 2018 Google Inc.
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
7 // http://www.apache.org/licenses/LICENSE-2.0
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.
15 // Validates correctness of extension SPIR-V instructions.
21 #include "NonSemanticShaderDebugInfo100.h"
22 #include "OpenCLDebugInfo100.h"
23 #include "source/common_debug_info.h"
24 #include "source/enum_string_mapping.h"
25 #include "source/extensions.h"
26 #include "source/latest_version_glsl_std_450_header.h"
27 #include "source/latest_version_opencl_std_header.h"
28 #include "source/spirv_constant.h"
29 #include "source/val/instruction.h"
30 #include "source/val/validate.h"
31 #include "source/val/validation_state.h"
32 #include "spirv/unified1/NonSemanticClspvReflection.h"
38 std::string
ReflectionInstructionName(ValidationState_t
& _
,
39 const Instruction
* inst
) {
40 spv_ext_inst_desc desc
= nullptr;
41 if (_
.grammar().lookupExtInst(SPV_EXT_INST_TYPE_NONSEMANTIC_CLSPVREFLECTION
,
42 inst
->word(4), &desc
) != SPV_SUCCESS
||
44 return std::string("Unknown ExtInst");
46 std::ostringstream ss
;
52 uint32_t GetSizeTBitWidth(const ValidationState_t
& _
) {
53 if (_
.addressing_model() == spv::AddressingModel::Physical32
) return 32;
55 if (_
.addressing_model() == spv::AddressingModel::Physical64
) return 64;
60 bool IsIntScalar(ValidationState_t
& _
, uint32_t id
, bool must_len32
,
62 auto type
= _
.FindDef(id
);
63 if (!type
|| type
->opcode() != spv::Op::OpTypeInt
) {
67 if (must_len32
&& type
->GetOperandAs
<uint32_t>(1) != 32) {
71 return !must_unsigned
|| type
->GetOperandAs
<uint32_t>(2) == 0;
74 bool IsUint32Constant(ValidationState_t
& _
, uint32_t id
) {
75 auto inst
= _
.FindDef(id
);
76 if (!inst
|| inst
->opcode() != spv::Op::OpConstant
) {
80 return IsIntScalar(_
, inst
->type_id(), true, true);
83 uint32_t GetUint32Constant(ValidationState_t
& _
, uint32_t id
) {
84 auto inst
= _
.FindDef(id
);
88 // Check that the operand of a debug info instruction |inst| at |word_index|
89 // is a result id of an instruction with |expected_opcode|.
90 spv_result_t
ValidateOperandForDebugInfo(
91 ValidationState_t
& _
, const std::string
& operand_name
,
92 spv::Op expected_opcode
, const Instruction
* inst
, uint32_t word_index
,
93 const std::function
<std::string()>& ext_inst_name
) {
94 auto* operand
= _
.FindDef(inst
->word(word_index
));
95 if (operand
->opcode() != expected_opcode
) {
96 spv_opcode_desc desc
= nullptr;
97 if (_
.grammar().lookupOpcode(expected_opcode
, &desc
) != SPV_SUCCESS
||
99 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
100 << ext_inst_name() << ": "
101 << "expected operand " << operand_name
<< " is invalid";
103 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
104 << ext_inst_name() << ": "
105 << "expected operand " << operand_name
<< " must be a result id of "
106 << "Op" << desc
->name
;
111 // For NonSemantic.Shader.DebugInfo.100 check that the operand of a debug info
112 // instruction |inst| at |word_index| is a result id of a 32-bit integer
113 // OpConstant instruction. For OpenCL.DebugInfo.100 the parameter is a literal
114 // word so cannot be validated.
115 spv_result_t
ValidateUint32ConstantOperandForDebugInfo(
116 ValidationState_t
& _
, const std::string
& operand_name
,
117 const Instruction
* inst
, uint32_t word_index
,
118 const std::function
<std::string()>& ext_inst_name
) {
119 if (!IsUint32Constant(_
, inst
->word(word_index
))) {
120 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
121 << ext_inst_name() << ": expected operand " << operand_name
122 << " must be a result id of 32-bit unsigned OpConstant";
127 #define CHECK_OPERAND(NAME, opcode, index) \
129 auto result = ValidateOperandForDebugInfo(_, NAME, opcode, inst, index, \
131 if (result != SPV_SUCCESS) return result; \
134 #define CHECK_CONST_UINT_OPERAND(NAME, index) \
135 if (vulkanDebugInfo) { \
136 auto result = ValidateUint32ConstantOperandForDebugInfo( \
137 _, NAME, inst, index, ext_inst_name); \
138 if (result != SPV_SUCCESS) return result; \
141 // True if the operand of a debug info instruction |inst| at |word_index|
142 // satisfies |expectation| that is given as a function. Otherwise,
144 bool DoesDebugInfoOperandMatchExpectation(
145 const ValidationState_t
& _
,
146 const std::function
<bool(CommonDebugInfoInstructions
)>& expectation
,
147 const Instruction
* inst
, uint32_t word_index
) {
148 if (inst
->words().size() <= word_index
) return false;
149 auto* debug_inst
= _
.FindDef(inst
->word(word_index
));
150 if (!spvIsExtendedInstruction(debug_inst
->opcode()) ||
151 (debug_inst
->ext_inst_type() != SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100
&&
152 debug_inst
->ext_inst_type() !=
153 SPV_EXT_INST_TYPE_NONSEMANTIC_SHADER_DEBUGINFO_100
) ||
154 !expectation(CommonDebugInfoInstructions(debug_inst
->word(4)))) {
160 // Overload for NonSemanticShaderDebugInfo100Instructions.
161 bool DoesDebugInfoOperandMatchExpectation(
162 const ValidationState_t
& _
,
163 const std::function
<bool(NonSemanticShaderDebugInfo100Instructions
)>&
165 const Instruction
* inst
, uint32_t word_index
) {
166 if (inst
->words().size() <= word_index
) return false;
167 auto* debug_inst
= _
.FindDef(inst
->word(word_index
));
168 if (!spvIsExtendedInstruction(debug_inst
->opcode()) ||
169 (debug_inst
->ext_inst_type() !=
170 SPV_EXT_INST_TYPE_NONSEMANTIC_SHADER_DEBUGINFO_100
) ||
172 NonSemanticShaderDebugInfo100Instructions(debug_inst
->word(4)))) {
178 // Check that the operand of a debug info instruction |inst| at |word_index|
179 // is a result id of an debug info instruction whose debug instruction type
180 // is |expected_debug_inst|.
181 spv_result_t
ValidateDebugInfoOperand(
182 ValidationState_t
& _
, const std::string
& debug_inst_name
,
183 CommonDebugInfoInstructions expected_debug_inst
, const Instruction
* inst
,
184 uint32_t word_index
, const std::function
<std::string()>& ext_inst_name
) {
185 std::function
<bool(CommonDebugInfoInstructions
)> expectation
=
186 [expected_debug_inst
](CommonDebugInfoInstructions dbg_inst
) {
187 return dbg_inst
== expected_debug_inst
;
189 if (DoesDebugInfoOperandMatchExpectation(_
, expectation
, inst
, word_index
))
192 spv_ext_inst_desc desc
= nullptr;
193 if (_
.grammar().lookupExtInst(inst
->ext_inst_type(), expected_debug_inst
,
194 &desc
) != SPV_SUCCESS
||
196 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
197 << ext_inst_name() << ": "
198 << "expected operand " << debug_inst_name
<< " is invalid";
200 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
201 << ext_inst_name() << ": "
202 << "expected operand " << debug_inst_name
<< " must be a result id of "
206 #define CHECK_DEBUG_OPERAND(NAME, debug_opcode, index) \
208 auto result = ValidateDebugInfoOperand(_, NAME, debug_opcode, inst, index, \
210 if (result != SPV_SUCCESS) return result; \
213 // Check that the operand of a debug info instruction |inst| at |word_index|
214 // is a result id of an debug info instruction with DebugTypeBasic.
215 spv_result_t
ValidateOperandBaseType(
216 ValidationState_t
& _
, const Instruction
* inst
, uint32_t word_index
,
217 const std::function
<std::string()>& ext_inst_name
) {
218 return ValidateDebugInfoOperand(_
, "Base Type", CommonDebugInfoDebugTypeBasic
,
219 inst
, word_index
, ext_inst_name
);
222 // Check that the operand of a debug info instruction |inst| at |word_index|
223 // is a result id of a debug lexical scope instruction which is one of
224 // DebugCompilationUnit, DebugFunction, DebugLexicalBlock, or
225 // DebugTypeComposite.
226 spv_result_t
ValidateOperandLexicalScope(
227 ValidationState_t
& _
, const std::string
& debug_inst_name
,
228 const Instruction
* inst
, uint32_t word_index
,
229 const std::function
<std::string()>& ext_inst_name
) {
230 std::function
<bool(CommonDebugInfoInstructions
)> expectation
=
231 [](CommonDebugInfoInstructions dbg_inst
) {
232 return dbg_inst
== CommonDebugInfoDebugCompilationUnit
||
233 dbg_inst
== CommonDebugInfoDebugFunction
||
234 dbg_inst
== CommonDebugInfoDebugLexicalBlock
||
235 dbg_inst
== CommonDebugInfoDebugTypeComposite
;
237 if (DoesDebugInfoOperandMatchExpectation(_
, expectation
, inst
, word_index
))
240 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
241 << ext_inst_name() << ": "
242 << "expected operand " << debug_inst_name
243 << " must be a result id of a lexical scope";
246 // Check that the operand of a debug info instruction |inst| at |word_index|
247 // is a result id of a debug type instruction (See DebugTypeXXX in
248 // "4.3. Type instructions" section of OpenCL.DebugInfo.100 spec.
249 spv_result_t
ValidateOperandDebugType(
250 ValidationState_t
& _
, const std::string
& debug_inst_name
,
251 const Instruction
* inst
, uint32_t word_index
,
252 const std::function
<std::string()>& ext_inst_name
,
253 bool allow_template_param
) {
254 // Check for NonSemanticShaderDebugInfo100 specific types.
255 if (inst
->ext_inst_type() ==
256 SPV_EXT_INST_TYPE_NONSEMANTIC_SHADER_DEBUGINFO_100
) {
257 std::function
<bool(NonSemanticShaderDebugInfo100Instructions
)> expectation
=
258 [](NonSemanticShaderDebugInfo100Instructions dbg_inst
) {
259 return dbg_inst
== NonSemanticShaderDebugInfo100DebugTypeMatrix
;
261 if (DoesDebugInfoOperandMatchExpectation(_
, expectation
, inst
, word_index
))
265 // Check for common types.
266 std::function
<bool(CommonDebugInfoInstructions
)> expectation
=
267 [&allow_template_param
](CommonDebugInfoInstructions dbg_inst
) {
268 if (allow_template_param
&&
269 (dbg_inst
== CommonDebugInfoDebugTypeTemplateParameter
||
270 dbg_inst
== CommonDebugInfoDebugTypeTemplateTemplateParameter
)) {
273 return CommonDebugInfoDebugTypeBasic
<= dbg_inst
&&
274 dbg_inst
<= CommonDebugInfoDebugTypeTemplate
;
276 if (DoesDebugInfoOperandMatchExpectation(_
, expectation
, inst
, word_index
))
279 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
280 << ext_inst_name() << ": "
281 << "expected operand " << debug_inst_name
282 << " is not a valid debug type";
285 spv_result_t
ValidateClspvReflectionKernel(ValidationState_t
& _
,
286 const Instruction
* inst
,
288 const auto inst_name
= ReflectionInstructionName(_
, inst
);
289 const auto kernel_id
= inst
->GetOperandAs
<uint32_t>(4);
290 const auto kernel
= _
.FindDef(kernel_id
);
291 if (kernel
->opcode() != spv::Op::OpFunction
) {
292 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
293 << inst_name
<< " does not reference a function";
296 bool found_kernel
= false;
297 for (auto entry_point
: _
.entry_points()) {
298 if (entry_point
== kernel_id
) {
304 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
305 << inst_name
<< " does not reference an entry-point";
308 const auto* exec_models
= _
.GetExecutionModels(kernel_id
);
309 if (!exec_models
|| exec_models
->empty()) {
310 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
311 << inst_name
<< " does not reference an entry-point";
313 for (auto exec_model
: *exec_models
) {
314 if (exec_model
!= spv::ExecutionModel::GLCompute
) {
315 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
316 << inst_name
<< " must refer only to GLCompute entry-points";
320 auto name
= _
.FindDef(inst
->GetOperandAs
<uint32_t>(5));
321 if (!name
|| name
->opcode() != spv::Op::OpString
) {
322 return _
.diag(SPV_ERROR_INVALID_ID
, inst
) << "Name must be an OpString";
325 const std::string name_str
= name
->GetOperandAs
<std::string
>(1);
327 for (auto& desc
: _
.entry_point_descriptions(kernel_id
)) {
328 if (name_str
== desc
.name
) {
334 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
335 << "Name must match an entry-point for Kernel";
338 const auto num_operands
= inst
->operands().size();
339 if (version
< 5 && num_operands
> 6) {
340 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
341 << "Version " << version
<< " of the " << inst_name
342 << " instruction can only have 2 additional operands";
345 if (num_operands
> 6) {
346 const auto num_args_id
= inst
->GetOperandAs
<uint32_t>(6);
347 if (!IsUint32Constant(_
, num_args_id
)) {
348 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
349 << "NumArguments must be a 32-bit unsigned integer OpConstant";
353 if (num_operands
> 7) {
354 const auto flags_id
= inst
->GetOperandAs
<uint32_t>(7);
355 if (!IsUint32Constant(_
, flags_id
)) {
356 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
357 << "Flags must be a 32-bit unsigned integer OpConstant";
361 if (num_operands
> 8) {
362 const auto atts_id
= inst
->GetOperandAs
<uint32_t>(8);
363 if (_
.GetIdOpcode(atts_id
) != spv::Op::OpString
) {
364 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
365 << "Attributes must be an OpString";
372 spv_result_t
ValidateClspvReflectionArgumentInfo(ValidationState_t
& _
,
373 const Instruction
* inst
) {
374 const auto num_operands
= inst
->operands().size();
375 if (_
.GetIdOpcode(inst
->GetOperandAs
<uint32_t>(4)) != spv::Op::OpString
) {
376 return _
.diag(SPV_ERROR_INVALID_ID
, inst
) << "Name must be an OpString";
378 if (num_operands
> 5) {
379 if (_
.GetIdOpcode(inst
->GetOperandAs
<uint32_t>(5)) != spv::Op::OpString
) {
380 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
381 << "TypeName must be an OpString";
384 if (num_operands
> 6) {
385 if (!IsUint32Constant(_
, inst
->GetOperandAs
<uint32_t>(6))) {
386 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
387 << "AddressQualifier must be a 32-bit unsigned integer "
391 if (num_operands
> 7) {
392 if (!IsUint32Constant(_
, inst
->GetOperandAs
<uint32_t>(7))) {
393 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
394 << "AccessQualifier must be a 32-bit unsigned integer "
398 if (num_operands
> 8) {
399 if (!IsUint32Constant(_
, inst
->GetOperandAs
<uint32_t>(8))) {
400 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
401 << "TypeQualifier must be a 32-bit unsigned integer "
409 spv_result_t
ValidateKernelDecl(ValidationState_t
& _
, const Instruction
* inst
) {
410 const auto decl_id
= inst
->GetOperandAs
<uint32_t>(4);
411 const auto decl
= _
.FindDef(decl_id
);
412 if (!decl
|| !spvIsExtendedInstruction(decl
->opcode())) {
413 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
414 << "Kernel must be a Kernel extended instruction";
417 if (decl
->GetOperandAs
<uint32_t>(2) != inst
->GetOperandAs
<uint32_t>(2)) {
418 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
419 << "Kernel must be from the same extended instruction import";
422 const auto ext_inst
=
423 decl
->GetOperandAs
<NonSemanticClspvReflectionInstructions
>(3);
424 if (ext_inst
!= NonSemanticClspvReflectionKernel
) {
425 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
426 << "Kernel must be a Kernel extended instruction";
432 spv_result_t
ValidateArgInfo(ValidationState_t
& _
, const Instruction
* inst
,
433 uint32_t info_index
) {
434 auto info
= _
.FindDef(inst
->GetOperandAs
<uint32_t>(info_index
));
435 if (!info
|| !spvIsExtendedInstruction(info
->opcode())) {
436 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
437 << "ArgInfo must be an ArgumentInfo extended instruction";
440 if (info
->GetOperandAs
<uint32_t>(2) != inst
->GetOperandAs
<uint32_t>(2)) {
441 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
442 << "ArgInfo must be from the same extended instruction import";
445 auto ext_inst
= info
->GetOperandAs
<NonSemanticClspvReflectionInstructions
>(3);
446 if (ext_inst
!= NonSemanticClspvReflectionArgumentInfo
) {
447 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
448 << "ArgInfo must be an ArgumentInfo extended instruction";
454 spv_result_t
ValidateClspvReflectionArgumentBuffer(ValidationState_t
& _
,
455 const Instruction
* inst
) {
456 const auto num_operands
= inst
->operands().size();
457 if (auto error
= ValidateKernelDecl(_
, inst
)) {
461 if (!IsUint32Constant(_
, inst
->GetOperandAs
<uint32_t>(5))) {
462 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
463 << "Ordinal must be a 32-bit unsigned integer OpConstant";
466 if (!IsUint32Constant(_
, inst
->GetOperandAs
<uint32_t>(6))) {
467 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
468 << "DescriptorSet must be a 32-bit unsigned integer OpConstant";
471 if (!IsUint32Constant(_
, inst
->GetOperandAs
<uint32_t>(7))) {
472 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
473 << "Binding must be a 32-bit unsigned integer OpConstant";
476 if (num_operands
== 9) {
477 if (auto error
= ValidateArgInfo(_
, inst
, 8)) {
485 spv_result_t
ValidateClspvReflectionArgumentOffsetBuffer(
486 ValidationState_t
& _
, const Instruction
* inst
) {
487 const auto num_operands
= inst
->operands().size();
488 if (auto error
= ValidateKernelDecl(_
, inst
)) {
492 if (!IsUint32Constant(_
, inst
->GetOperandAs
<uint32_t>(5))) {
493 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
494 << "Ordinal must be a 32-bit unsigned integer OpConstant";
497 if (!IsUint32Constant(_
, inst
->GetOperandAs
<uint32_t>(6))) {
498 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
499 << "DescriptorSet must be a 32-bit unsigned integer OpConstant";
502 if (!IsUint32Constant(_
, inst
->GetOperandAs
<uint32_t>(7))) {
503 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
504 << "Binding must be a 32-bit unsigned integer OpConstant";
507 if (!IsUint32Constant(_
, inst
->GetOperandAs
<uint32_t>(8))) {
508 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
509 << "Offset must be a 32-bit unsigned integer OpConstant";
512 if (!IsUint32Constant(_
, inst
->GetOperandAs
<uint32_t>(9))) {
513 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
514 << "Size must be a 32-bit unsigned integer OpConstant";
517 if (num_operands
== 11) {
518 if (auto error
= ValidateArgInfo(_
, inst
, 10)) {
526 spv_result_t
ValidateClspvReflectionArgumentPushConstant(
527 ValidationState_t
& _
, const Instruction
* inst
) {
528 const auto num_operands
= inst
->operands().size();
529 if (auto error
= ValidateKernelDecl(_
, inst
)) {
533 if (!IsUint32Constant(_
, inst
->GetOperandAs
<uint32_t>(5))) {
534 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
535 << "Ordinal must be a 32-bit unsigned integer OpConstant";
538 if (!IsUint32Constant(_
, inst
->GetOperandAs
<uint32_t>(6))) {
539 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
540 << "Offset must be a 32-bit unsigned integer OpConstant";
543 if (!IsUint32Constant(_
, inst
->GetOperandAs
<uint32_t>(7))) {
544 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
545 << "Size must be a 32-bit unsigned integer OpConstant";
548 if (num_operands
== 9) {
549 if (auto error
= ValidateArgInfo(_
, inst
, 8)) {
557 spv_result_t
ValidateClspvReflectionArgumentWorkgroup(ValidationState_t
& _
,
558 const Instruction
* inst
) {
559 const auto num_operands
= inst
->operands().size();
560 if (auto error
= ValidateKernelDecl(_
, inst
)) {
564 if (!IsUint32Constant(_
, inst
->GetOperandAs
<uint32_t>(5))) {
565 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
566 << "Ordinal must be a 32-bit unsigned integer OpConstant";
569 if (!IsUint32Constant(_
, inst
->GetOperandAs
<uint32_t>(6))) {
570 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
571 << "SpecId must be a 32-bit unsigned integer OpConstant";
574 if (!IsUint32Constant(_
, inst
->GetOperandAs
<uint32_t>(7))) {
575 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
576 << "ElemSize must be a 32-bit unsigned integer OpConstant";
579 if (num_operands
== 9) {
580 if (auto error
= ValidateArgInfo(_
, inst
, 8)) {
588 spv_result_t
ValidateClspvReflectionSpecConstantTriple(
589 ValidationState_t
& _
, const Instruction
* inst
) {
590 if (!IsUint32Constant(_
, inst
->GetOperandAs
<uint32_t>(4))) {
591 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
592 << "X must be a 32-bit unsigned integer OpConstant";
595 if (!IsUint32Constant(_
, inst
->GetOperandAs
<uint32_t>(5))) {
596 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
597 << "Y must be a 32-bit unsigned integer OpConstant";
600 if (!IsUint32Constant(_
, inst
->GetOperandAs
<uint32_t>(6))) {
601 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
602 << "Z must be a 32-bit unsigned integer OpConstant";
608 spv_result_t
ValidateClspvReflectionSpecConstantWorkDim(
609 ValidationState_t
& _
, const Instruction
* inst
) {
610 if (!IsUint32Constant(_
, inst
->GetOperandAs
<uint32_t>(4))) {
611 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
612 << "Dim must be a 32-bit unsigned integer OpConstant";
618 spv_result_t
ValidateClspvReflectionPushConstant(ValidationState_t
& _
,
619 const Instruction
* inst
) {
620 if (!IsUint32Constant(_
, inst
->GetOperandAs
<uint32_t>(4))) {
621 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
622 << "Offset must be a 32-bit unsigned integer OpConstant";
625 if (!IsUint32Constant(_
, inst
->GetOperandAs
<uint32_t>(5))) {
626 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
627 << "Size must be a 32-bit unsigned integer OpConstant";
633 spv_result_t
ValidateClspvReflectionInitializedData(ValidationState_t
& _
,
634 const Instruction
* inst
) {
635 if (!IsUint32Constant(_
, inst
->GetOperandAs
<uint32_t>(4))) {
636 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
637 << "DescriptorSet must be a 32-bit unsigned integer OpConstant";
640 if (!IsUint32Constant(_
, inst
->GetOperandAs
<uint32_t>(5))) {
641 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
642 << "Binding must be a 32-bit unsigned integer OpConstant";
645 if (_
.GetIdOpcode(inst
->GetOperandAs
<uint32_t>(6)) != spv::Op::OpString
) {
646 return _
.diag(SPV_ERROR_INVALID_ID
, inst
) << "Data must be an OpString";
652 spv_result_t
ValidateClspvReflectionSampler(ValidationState_t
& _
,
653 const Instruction
* inst
) {
654 if (!IsUint32Constant(_
, inst
->GetOperandAs
<uint32_t>(4))) {
655 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
656 << "DescriptorSet must be a 32-bit unsigned integer OpConstant";
659 if (!IsUint32Constant(_
, inst
->GetOperandAs
<uint32_t>(5))) {
660 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
661 << "Binding must be a 32-bit unsigned integer OpConstant";
664 if (!IsUint32Constant(_
, inst
->GetOperandAs
<uint32_t>(6))) {
665 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
666 << "Mask must be a 32-bit unsigned integer OpConstant";
672 spv_result_t
ValidateClspvReflectionPropertyRequiredWorkgroupSize(
673 ValidationState_t
& _
, const Instruction
* inst
) {
674 if (auto error
= ValidateKernelDecl(_
, inst
)) {
678 if (!IsUint32Constant(_
, inst
->GetOperandAs
<uint32_t>(5))) {
679 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
680 << "X must be a 32-bit unsigned integer OpConstant";
683 if (!IsUint32Constant(_
, inst
->GetOperandAs
<uint32_t>(6))) {
684 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
685 << "Y must be a 32-bit unsigned integer OpConstant";
688 if (!IsUint32Constant(_
, inst
->GetOperandAs
<uint32_t>(7))) {
689 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
690 << "Z must be a 32-bit unsigned integer OpConstant";
696 spv_result_t
ValidateClspvReflectionSubgroupMaxSize(ValidationState_t
& _
,
697 const Instruction
* inst
) {
698 const auto size_id
= inst
->GetOperandAs
<uint32_t>(4);
699 if (!IsUint32Constant(_
, size_id
)) {
700 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
701 << "Size must be a 32-bit unsigned integer OpConstant";
707 spv_result_t
ValidateClspvReflectionPointerRelocation(ValidationState_t
& _
,
708 const Instruction
* inst
) {
709 if (!IsUint32Constant(_
, inst
->GetOperandAs
<uint32_t>(4))) {
710 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
711 << "ObjectOffset must be a 32-bit unsigned integer OpConstant";
714 if (!IsUint32Constant(_
, inst
->GetOperandAs
<uint32_t>(5))) {
715 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
716 << "PointerOffset must be a 32-bit unsigned integer OpConstant";
719 if (!IsUint32Constant(_
, inst
->GetOperandAs
<uint32_t>(6))) {
720 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
721 << "PointerSize must be a 32-bit unsigned integer OpConstant";
727 spv_result_t
ValidateClspvReflectionImageMetadataPushConstant(
728 ValidationState_t
& _
, const Instruction
* inst
) {
729 if (auto error
= ValidateKernelDecl(_
, inst
)) {
733 if (!IsUint32Constant(_
, inst
->GetOperandAs
<uint32_t>(5))) {
734 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
735 << "Ordinal must be a 32-bit unsigned integer OpConstant";
738 if (!IsUint32Constant(_
, inst
->GetOperandAs
<uint32_t>(6))) {
739 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
740 << "Offset must be a 32-bit unsigned integer OpConstant";
743 if (!IsUint32Constant(_
, inst
->GetOperandAs
<uint32_t>(7))) {
744 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
745 << "Size must be a 32-bit unsigned integer OpConstant";
751 spv_result_t
ValidateClspvReflectionImageMetadataUniform(
752 ValidationState_t
& _
, const Instruction
* inst
) {
753 if (auto error
= ValidateKernelDecl(_
, inst
)) {
757 if (!IsUint32Constant(_
, inst
->GetOperandAs
<uint32_t>(5))) {
758 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
759 << "Ordinal must be a 32-bit unsigned integer OpConstant";
762 if (!IsUint32Constant(_
, inst
->GetOperandAs
<uint32_t>(6))) {
763 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
764 << "DescriptorSet must be a 32-bit unsigned integer OpConstant";
767 if (!IsUint32Constant(_
, inst
->GetOperandAs
<uint32_t>(7))) {
768 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
769 << "Binding must be a 32-bit unsigned integer OpConstant";
772 if (!IsUint32Constant(_
, inst
->GetOperandAs
<uint32_t>(8))) {
773 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
774 << "Offset must be a 32-bit unsigned integer OpConstant";
777 if (!IsUint32Constant(_
, inst
->GetOperandAs
<uint32_t>(9))) {
778 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
779 << "Size must be a 32-bit unsigned integer OpConstant";
785 spv_result_t
ValidateClspvReflectionPushConstantData(ValidationState_t
& _
,
786 const Instruction
* inst
) {
787 if (!IsUint32Constant(_
, inst
->GetOperandAs
<uint32_t>(4))) {
788 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
789 << "Offset must be a 32-bit unsigned integer OpConstant";
792 if (!IsUint32Constant(_
, inst
->GetOperandAs
<uint32_t>(5))) {
793 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
794 << "Size must be a 32-bit unsigned integer OpConstant";
797 if (_
.GetIdOpcode(inst
->GetOperandAs
<uint32_t>(6)) != spv::Op::OpString
) {
798 return _
.diag(SPV_ERROR_INVALID_ID
, inst
) << "Data must be an OpString";
804 spv_result_t
ValidateClspvReflectionPrintfInfo(ValidationState_t
& _
,
805 const Instruction
* inst
) {
806 if (!IsUint32Constant(_
, inst
->GetOperandAs
<uint32_t>(4))) {
807 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
808 << "PrintfID must be a 32-bit unsigned integer OpConstant";
811 if (_
.GetIdOpcode(inst
->GetOperandAs
<uint32_t>(5)) != spv::Op::OpString
) {
812 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
813 << "FormatString must be an OpString";
816 for (size_t i
= 6; i
< inst
->operands().size(); ++i
) {
817 if (!IsUint32Constant(_
, inst
->GetOperandAs
<uint32_t>(i
))) {
818 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
819 << "ArgumentSizes must be a 32-bit unsigned integer OpConstant";
826 spv_result_t
ValidateClspvReflectionPrintfStorageBuffer(
827 ValidationState_t
& _
, const Instruction
* inst
) {
828 if (!IsUint32Constant(_
, inst
->GetOperandAs
<uint32_t>(4))) {
829 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
830 << "DescriptorSet must be a 32-bit unsigned integer OpConstant";
833 if (!IsUint32Constant(_
, inst
->GetOperandAs
<uint32_t>(5))) {
834 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
835 << "Binding must be a 32-bit unsigned integer OpConstant";
838 if (!IsUint32Constant(_
, inst
->GetOperandAs
<uint32_t>(6))) {
839 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
840 << "Size must be a 32-bit unsigned integer OpConstant";
846 spv_result_t
ValidateClspvReflectionPrintfPushConstant(
847 ValidationState_t
& _
, const Instruction
* inst
) {
848 if (!IsUint32Constant(_
, inst
->GetOperandAs
<uint32_t>(4))) {
849 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
850 << "Offset must be a 32-bit unsigned integer OpConstant";
853 if (!IsUint32Constant(_
, inst
->GetOperandAs
<uint32_t>(5))) {
854 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
855 << "Size must be a 32-bit unsigned integer OpConstant";
858 if (!IsUint32Constant(_
, inst
->GetOperandAs
<uint32_t>(6))) {
859 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
860 << "BufferSize must be a 32-bit unsigned integer OpConstant";
866 spv_result_t
ValidateClspvReflectionInstruction(ValidationState_t
& _
,
867 const Instruction
* inst
,
869 if (!_
.IsVoidType(inst
->type_id())) {
870 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
871 << "Return Type must be OpTypeVoid";
874 uint32_t required_version
= 0;
875 const auto ext_inst
=
876 inst
->GetOperandAs
<NonSemanticClspvReflectionInstructions
>(3);
878 case NonSemanticClspvReflectionKernel
:
879 case NonSemanticClspvReflectionArgumentInfo
:
880 case NonSemanticClspvReflectionArgumentStorageBuffer
:
881 case NonSemanticClspvReflectionArgumentUniform
:
882 case NonSemanticClspvReflectionArgumentPodStorageBuffer
:
883 case NonSemanticClspvReflectionArgumentPodUniform
:
884 case NonSemanticClspvReflectionArgumentPodPushConstant
:
885 case NonSemanticClspvReflectionArgumentSampledImage
:
886 case NonSemanticClspvReflectionArgumentStorageImage
:
887 case NonSemanticClspvReflectionArgumentSampler
:
888 case NonSemanticClspvReflectionArgumentWorkgroup
:
889 case NonSemanticClspvReflectionSpecConstantWorkgroupSize
:
890 case NonSemanticClspvReflectionSpecConstantGlobalOffset
:
891 case NonSemanticClspvReflectionSpecConstantWorkDim
:
892 case NonSemanticClspvReflectionPushConstantGlobalOffset
:
893 case NonSemanticClspvReflectionPushConstantEnqueuedLocalSize
:
894 case NonSemanticClspvReflectionPushConstantGlobalSize
:
895 case NonSemanticClspvReflectionPushConstantRegionOffset
:
896 case NonSemanticClspvReflectionPushConstantNumWorkgroups
:
897 case NonSemanticClspvReflectionPushConstantRegionGroupOffset
:
898 case NonSemanticClspvReflectionConstantDataStorageBuffer
:
899 case NonSemanticClspvReflectionConstantDataUniform
:
900 case NonSemanticClspvReflectionLiteralSampler
:
901 case NonSemanticClspvReflectionPropertyRequiredWorkgroupSize
:
902 required_version
= 1;
904 case NonSemanticClspvReflectionSpecConstantSubgroupMaxSize
:
905 required_version
= 2;
907 case NonSemanticClspvReflectionArgumentPointerPushConstant
:
908 case NonSemanticClspvReflectionArgumentPointerUniform
:
909 case NonSemanticClspvReflectionProgramScopeVariablesStorageBuffer
:
910 case NonSemanticClspvReflectionProgramScopeVariablePointerRelocation
:
911 case NonSemanticClspvReflectionImageArgumentInfoChannelOrderPushConstant
:
912 case NonSemanticClspvReflectionImageArgumentInfoChannelDataTypePushConstant
:
913 case NonSemanticClspvReflectionImageArgumentInfoChannelOrderUniform
:
914 case NonSemanticClspvReflectionImageArgumentInfoChannelDataTypeUniform
:
915 required_version
= 3;
917 case NonSemanticClspvReflectionArgumentStorageTexelBuffer
:
918 case NonSemanticClspvReflectionArgumentUniformTexelBuffer
:
919 required_version
= 4;
921 case NonSemanticClspvReflectionConstantDataPointerPushConstant
:
922 case NonSemanticClspvReflectionProgramScopeVariablePointerPushConstant
:
923 case NonSemanticClspvReflectionPrintfInfo
:
924 case NonSemanticClspvReflectionPrintfBufferStorageBuffer
:
925 case NonSemanticClspvReflectionPrintfBufferPointerPushConstant
:
926 required_version
= 5;
931 if (version
< required_version
) {
932 return _
.diag(SPV_ERROR_INVALID_ID
, inst
)
933 << ReflectionInstructionName(_
, inst
) << " requires version "
934 << required_version
<< ", but parsed version is " << version
;
938 case NonSemanticClspvReflectionKernel
:
939 return ValidateClspvReflectionKernel(_
, inst
, version
);
940 case NonSemanticClspvReflectionArgumentInfo
:
941 return ValidateClspvReflectionArgumentInfo(_
, inst
);
942 case NonSemanticClspvReflectionArgumentStorageBuffer
:
943 case NonSemanticClspvReflectionArgumentUniform
:
944 case NonSemanticClspvReflectionArgumentSampledImage
:
945 case NonSemanticClspvReflectionArgumentStorageImage
:
946 case NonSemanticClspvReflectionArgumentSampler
:
947 case NonSemanticClspvReflectionArgumentStorageTexelBuffer
:
948 case NonSemanticClspvReflectionArgumentUniformTexelBuffer
:
949 return ValidateClspvReflectionArgumentBuffer(_
, inst
);
950 case NonSemanticClspvReflectionArgumentPodStorageBuffer
:
951 case NonSemanticClspvReflectionArgumentPodUniform
:
952 case NonSemanticClspvReflectionArgumentPointerUniform
:
953 return ValidateClspvReflectionArgumentOffsetBuffer(_
, inst
);
954 case NonSemanticClspvReflectionArgumentPodPushConstant
:
955 case NonSemanticClspvReflectionArgumentPointerPushConstant
:
956 return ValidateClspvReflectionArgumentPushConstant(_
, inst
);
957 case NonSemanticClspvReflectionArgumentWorkgroup
:
958 return ValidateClspvReflectionArgumentWorkgroup(_
, inst
);
959 case NonSemanticClspvReflectionSpecConstantWorkgroupSize
:
960 case NonSemanticClspvReflectionSpecConstantGlobalOffset
:
961 return ValidateClspvReflectionSpecConstantTriple(_
, inst
);
962 case NonSemanticClspvReflectionSpecConstantWorkDim
:
963 return ValidateClspvReflectionSpecConstantWorkDim(_
, inst
);
964 case NonSemanticClspvReflectionPushConstantGlobalOffset
:
965 case NonSemanticClspvReflectionPushConstantEnqueuedLocalSize
:
966 case NonSemanticClspvReflectionPushConstantGlobalSize
:
967 case NonSemanticClspvReflectionPushConstantRegionOffset
:
968 case NonSemanticClspvReflectionPushConstantNumWorkgroups
:
969 case NonSemanticClspvReflectionPushConstantRegionGroupOffset
:
970 return ValidateClspvReflectionPushConstant(_
, inst
);
971 case NonSemanticClspvReflectionConstantDataStorageBuffer
:
972 case NonSemanticClspvReflectionConstantDataUniform
:
973 case NonSemanticClspvReflectionProgramScopeVariablesStorageBuffer
:
974 return ValidateClspvReflectionInitializedData(_
, inst
);
975 case NonSemanticClspvReflectionLiteralSampler
:
976 return ValidateClspvReflectionSampler(_
, inst
);
977 case NonSemanticClspvReflectionPropertyRequiredWorkgroupSize
:
978 return ValidateClspvReflectionPropertyRequiredWorkgroupSize(_
, inst
);
979 case NonSemanticClspvReflectionSpecConstantSubgroupMaxSize
:
980 return ValidateClspvReflectionSubgroupMaxSize(_
, inst
);
981 case NonSemanticClspvReflectionProgramScopeVariablePointerRelocation
:
982 return ValidateClspvReflectionPointerRelocation(_
, inst
);
983 case NonSemanticClspvReflectionImageArgumentInfoChannelOrderPushConstant
:
984 case NonSemanticClspvReflectionImageArgumentInfoChannelDataTypePushConstant
:
985 return ValidateClspvReflectionImageMetadataPushConstant(_
, inst
);
986 case NonSemanticClspvReflectionImageArgumentInfoChannelOrderUniform
:
987 case NonSemanticClspvReflectionImageArgumentInfoChannelDataTypeUniform
:
988 return ValidateClspvReflectionImageMetadataUniform(_
, inst
);
989 case NonSemanticClspvReflectionConstantDataPointerPushConstant
:
990 case NonSemanticClspvReflectionProgramScopeVariablePointerPushConstant
:
991 return ValidateClspvReflectionPushConstantData(_
, inst
);
992 case NonSemanticClspvReflectionPrintfInfo
:
993 return ValidateClspvReflectionPrintfInfo(_
, inst
);
994 case NonSemanticClspvReflectionPrintfBufferStorageBuffer
:
995 return ValidateClspvReflectionPrintfStorageBuffer(_
, inst
);
996 case NonSemanticClspvReflectionPrintfBufferPointerPushConstant
:
997 return ValidateClspvReflectionPrintfPushConstant(_
, inst
);
1005 bool IsConstIntScalarTypeWith32Or64Bits(ValidationState_t
& _
,
1006 Instruction
* instr
) {
1007 if (instr
->opcode() != spv::Op::OpConstant
) return false;
1008 if (!_
.IsIntScalarType(instr
->type_id())) return false;
1009 uint32_t size_in_bits
= _
.GetBitWidth(instr
->type_id());
1010 return size_in_bits
== 32 || size_in_bits
== 64;
1013 bool IsConstWithIntScalarType(ValidationState_t
& _
, const Instruction
* inst
,
1014 uint32_t word_index
) {
1015 auto* int_scalar_const
= _
.FindDef(inst
->word(word_index
));
1016 if (int_scalar_const
->opcode() == spv::Op::OpConstant
&&
1017 _
.IsIntScalarType(int_scalar_const
->type_id())) {
1023 bool IsDebugVariableWithIntScalarType(ValidationState_t
& _
,
1024 const Instruction
* inst
,
1025 uint32_t word_index
) {
1026 auto* dbg_int_scalar_var
= _
.FindDef(inst
->word(word_index
));
1027 if (CommonDebugInfoInstructions(dbg_int_scalar_var
->word(4)) ==
1028 CommonDebugInfoDebugLocalVariable
||
1029 CommonDebugInfoInstructions(dbg_int_scalar_var
->word(4)) ==
1030 CommonDebugInfoDebugGlobalVariable
) {
1031 auto* dbg_type
= _
.FindDef(dbg_int_scalar_var
->word(6));
1032 if (CommonDebugInfoInstructions(dbg_type
->word(4)) ==
1033 CommonDebugInfoDebugTypeBasic
) {
1034 const spv_ext_inst_type_t ext_inst_type
=
1035 spv_ext_inst_type_t(inst
->ext_inst_type());
1036 const bool vulkanDebugInfo
=
1037 ext_inst_type
== SPV_EXT_INST_TYPE_NONSEMANTIC_SHADER_DEBUGINFO_100
;
1038 uint32_t encoding
= dbg_type
->word(7);
1039 if (!vulkanDebugInfo
|| IsUint32Constant(_
, encoding
)) {
1040 auto ocl_encoding
= OpenCLDebugInfo100DebugBaseTypeAttributeEncoding(
1041 vulkanDebugInfo
? GetUint32Constant(_
, encoding
) : encoding
);
1042 if (ocl_encoding
== OpenCLDebugInfo100Signed
||
1043 ocl_encoding
== OpenCLDebugInfo100Unsigned
) {
1052 } // anonymous namespace
1054 spv_result_t
ValidateExtension(ValidationState_t
& _
, const Instruction
* inst
) {
1055 if (_
.version() < SPV_SPIRV_VERSION_WORD(1, 4)) {
1056 std::string extension
= GetExtensionString(&(inst
->c_inst()));
1058 ExtensionToString(kSPV_KHR_workgroup_memory_explicit_layout
) ||
1059 extension
== ExtensionToString(kSPV_EXT_mesh_shader
) ||
1060 extension
== ExtensionToString(kSPV_NV_shader_invocation_reorder
)) {
1061 return _
.diag(SPV_ERROR_WRONG_VERSION
, inst
)
1062 << extension
<< " extension requires SPIR-V version 1.4 or later.";
1069 spv_result_t
ValidateExtInstImport(ValidationState_t
& _
,
1070 const Instruction
* inst
) {
1071 const auto name_id
= 1;
1072 if (_
.version() <= SPV_SPIRV_VERSION_WORD(1, 5) &&
1073 !_
.HasExtension(kSPV_KHR_non_semantic_info
)) {
1074 const std::string name
= inst
->GetOperandAs
<std::string
>(name_id
);
1075 if (name
.find("NonSemantic.") == 0) {
1076 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1077 << "NonSemantic extended instruction sets cannot be declared "
1078 "without SPV_KHR_non_semantic_info.";
1085 spv_result_t
ValidateExtInst(ValidationState_t
& _
, const Instruction
* inst
) {
1086 const uint32_t result_type
= inst
->type_id();
1087 const uint32_t num_operands
= static_cast<uint32_t>(inst
->operands().size());
1089 const uint32_t ext_inst_set
= inst
->word(3);
1090 const uint32_t ext_inst_index
= inst
->word(4);
1091 const spv_ext_inst_type_t ext_inst_type
=
1092 spv_ext_inst_type_t(inst
->ext_inst_type());
1094 auto ext_inst_name
= [&_
, ext_inst_set
, ext_inst_type
, ext_inst_index
]() {
1095 spv_ext_inst_desc desc
= nullptr;
1096 if (_
.grammar().lookupExtInst(ext_inst_type
, ext_inst_index
, &desc
) !=
1099 return std::string("Unknown ExtInst");
1102 auto* import_inst
= _
.FindDef(ext_inst_set
);
1103 assert(import_inst
);
1105 std::ostringstream ss
;
1106 ss
<< import_inst
->GetOperandAs
<std::string
>(1);
1113 if (ext_inst_type
== SPV_EXT_INST_TYPE_GLSL_STD_450
) {
1114 const GLSLstd450 ext_inst_key
= GLSLstd450(ext_inst_index
);
1115 switch (ext_inst_key
) {
1116 case GLSLstd450Round
:
1117 case GLSLstd450RoundEven
:
1118 case GLSLstd450FAbs
:
1119 case GLSLstd450Trunc
:
1120 case GLSLstd450FSign
:
1121 case GLSLstd450Floor
:
1122 case GLSLstd450Ceil
:
1123 case GLSLstd450Fract
:
1124 case GLSLstd450Sqrt
:
1125 case GLSLstd450InverseSqrt
:
1126 case GLSLstd450FMin
:
1127 case GLSLstd450FMax
:
1128 case GLSLstd450FClamp
:
1129 case GLSLstd450FMix
:
1130 case GLSLstd450Step
:
1131 case GLSLstd450SmoothStep
:
1133 case GLSLstd450Normalize
:
1134 case GLSLstd450FaceForward
:
1135 case GLSLstd450Reflect
:
1136 case GLSLstd450NMin
:
1137 case GLSLstd450NMax
:
1138 case GLSLstd450NClamp
: {
1139 if (!_
.IsFloatScalarOrVectorType(result_type
)) {
1140 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1141 << ext_inst_name() << ": "
1142 << "expected Result Type to be a float scalar or vector type";
1145 for (uint32_t operand_index
= 4; operand_index
< num_operands
;
1147 const uint32_t operand_type
= _
.GetOperandTypeId(inst
, operand_index
);
1148 if (result_type
!= operand_type
) {
1149 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1150 << ext_inst_name() << ": "
1151 << "expected types of all operands to be equal to Result "
1158 case GLSLstd450SAbs
:
1159 case GLSLstd450SSign
:
1160 case GLSLstd450UMin
:
1161 case GLSLstd450SMin
:
1162 case GLSLstd450UMax
:
1163 case GLSLstd450SMax
:
1164 case GLSLstd450UClamp
:
1165 case GLSLstd450SClamp
:
1166 case GLSLstd450FindILsb
:
1167 case GLSLstd450FindUMsb
:
1168 case GLSLstd450FindSMsb
: {
1169 if (!_
.IsIntScalarOrVectorType(result_type
)) {
1170 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1171 << ext_inst_name() << ": "
1172 << "expected Result Type to be an int scalar or vector type";
1175 const uint32_t result_type_bit_width
= _
.GetBitWidth(result_type
);
1176 const uint32_t result_type_dimension
= _
.GetDimension(result_type
);
1178 for (uint32_t operand_index
= 4; operand_index
< num_operands
;
1180 const uint32_t operand_type
= _
.GetOperandTypeId(inst
, operand_index
);
1181 if (!operand_type
|| !_
.IsIntScalarOrVectorType(operand_type
)) {
1182 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1183 << ext_inst_name() << ": "
1184 << "expected all operands to be int scalars or vectors";
1187 if (result_type_dimension
!= _
.GetDimension(operand_type
)) {
1188 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1189 << ext_inst_name() << ": "
1190 << "expected all operands to have the same dimension as "
1194 if (result_type_bit_width
!= _
.GetBitWidth(operand_type
)) {
1195 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1196 << ext_inst_name() << ": "
1197 << "expected all operands to have the same bit width as "
1201 if (ext_inst_key
== GLSLstd450FindUMsb
||
1202 ext_inst_key
== GLSLstd450FindSMsb
) {
1203 if (result_type_bit_width
!= 32) {
1204 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1205 << ext_inst_name() << ": "
1206 << "this instruction is currently limited to 32-bit width "
1214 case GLSLstd450Radians
:
1215 case GLSLstd450Degrees
:
1219 case GLSLstd450Asin
:
1220 case GLSLstd450Acos
:
1221 case GLSLstd450Atan
:
1222 case GLSLstd450Sinh
:
1223 case GLSLstd450Cosh
:
1224 case GLSLstd450Tanh
:
1225 case GLSLstd450Asinh
:
1226 case GLSLstd450Acosh
:
1227 case GLSLstd450Atanh
:
1229 case GLSLstd450Exp2
:
1231 case GLSLstd450Log2
:
1232 case GLSLstd450Atan2
:
1233 case GLSLstd450Pow
: {
1234 if (!_
.IsFloatScalarOrVectorType(result_type
)) {
1235 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1236 << ext_inst_name() << ": "
1237 << "expected Result Type to be a 16 or 32-bit scalar or "
1238 "vector float type";
1241 const uint32_t result_type_bit_width
= _
.GetBitWidth(result_type
);
1242 if (result_type_bit_width
!= 16 && result_type_bit_width
!= 32) {
1243 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1244 << ext_inst_name() << ": "
1245 << "expected Result Type to be a 16 or 32-bit scalar or "
1246 "vector float type";
1249 for (uint32_t operand_index
= 4; operand_index
< num_operands
;
1251 const uint32_t operand_type
= _
.GetOperandTypeId(inst
, operand_index
);
1252 if (result_type
!= operand_type
) {
1253 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1254 << ext_inst_name() << ": "
1255 << "expected types of all operands to be equal to Result "
1262 case GLSLstd450Determinant
: {
1263 const uint32_t x_type
= _
.GetOperandTypeId(inst
, 4);
1264 uint32_t num_rows
= 0;
1265 uint32_t num_cols
= 0;
1266 uint32_t col_type
= 0;
1267 uint32_t component_type
= 0;
1268 if (!_
.GetMatrixTypeInfo(x_type
, &num_rows
, &num_cols
, &col_type
,
1270 num_rows
!= num_cols
) {
1271 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1272 << ext_inst_name() << ": "
1273 << "expected operand X to be a square matrix";
1276 if (result_type
!= component_type
) {
1277 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1278 << ext_inst_name() << ": "
1279 << "expected operand X component type to be equal to "
1285 case GLSLstd450MatrixInverse
: {
1286 uint32_t num_rows
= 0;
1287 uint32_t num_cols
= 0;
1288 uint32_t col_type
= 0;
1289 uint32_t component_type
= 0;
1290 if (!_
.GetMatrixTypeInfo(result_type
, &num_rows
, &num_cols
, &col_type
,
1292 num_rows
!= num_cols
) {
1293 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1294 << ext_inst_name() << ": "
1295 << "expected Result Type to be a square matrix";
1298 const uint32_t x_type
= _
.GetOperandTypeId(inst
, 4);
1299 if (result_type
!= x_type
) {
1300 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1301 << ext_inst_name() << ": "
1302 << "expected operand X type to be equal to Result Type";
1307 case GLSLstd450Modf
: {
1308 if (!_
.IsFloatScalarOrVectorType(result_type
)) {
1309 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1310 << ext_inst_name() << ": "
1311 << "expected Result Type to be a scalar or vector float type";
1314 const uint32_t x_type
= _
.GetOperandTypeId(inst
, 4);
1315 const uint32_t i_type
= _
.GetOperandTypeId(inst
, 5);
1317 if (x_type
!= result_type
) {
1318 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1319 << ext_inst_name() << ": "
1320 << "expected operand X type to be equal to Result Type";
1323 spv::StorageClass i_storage_class
;
1324 uint32_t i_data_type
= 0;
1325 if (!_
.GetPointerTypeInfo(i_type
, &i_data_type
, &i_storage_class
)) {
1326 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1327 << ext_inst_name() << ": "
1328 << "expected operand I to be a pointer";
1331 if (i_data_type
!= result_type
) {
1332 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1333 << ext_inst_name() << ": "
1334 << "expected operand I data type to be equal to Result Type";
1340 case GLSLstd450ModfStruct
: {
1341 std::vector
<uint32_t> result_types
;
1342 if (!_
.GetStructMemberTypes(result_type
, &result_types
) ||
1343 result_types
.size() != 2 ||
1344 !_
.IsFloatScalarOrVectorType(result_types
[0]) ||
1345 result_types
[1] != result_types
[0]) {
1346 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1347 << ext_inst_name() << ": "
1348 << "expected Result Type to be a struct with two identical "
1349 << "scalar or vector float type members";
1352 const uint32_t x_type
= _
.GetOperandTypeId(inst
, 4);
1353 if (x_type
!= result_types
[0]) {
1354 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1355 << ext_inst_name() << ": "
1356 << "expected operand X type to be equal to members of "
1357 << "Result Type struct";
1362 case GLSLstd450Frexp
: {
1363 if (!_
.IsFloatScalarOrVectorType(result_type
)) {
1364 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1365 << ext_inst_name() << ": "
1366 << "expected Result Type to be a scalar or vector float type";
1369 const uint32_t x_type
= _
.GetOperandTypeId(inst
, 4);
1370 const uint32_t exp_type
= _
.GetOperandTypeId(inst
, 5);
1372 if (x_type
!= result_type
) {
1373 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1374 << ext_inst_name() << ": "
1375 << "expected operand X type to be equal to Result Type";
1378 spv::StorageClass exp_storage_class
;
1379 uint32_t exp_data_type
= 0;
1380 if (!_
.GetPointerTypeInfo(exp_type
, &exp_data_type
,
1381 &exp_storage_class
)) {
1382 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1383 << ext_inst_name() << ": "
1384 << "expected operand Exp to be a pointer";
1387 if (!_
.IsIntScalarOrVectorType(exp_data_type
) ||
1388 (!_
.HasExtension(kSPV_AMD_gpu_shader_int16
) &&
1389 _
.GetBitWidth(exp_data_type
) != 32) ||
1390 (_
.HasExtension(kSPV_AMD_gpu_shader_int16
) &&
1391 _
.GetBitWidth(exp_data_type
) != 16 &&
1392 _
.GetBitWidth(exp_data_type
) != 32)) {
1393 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1394 << ext_inst_name() << ": "
1395 << "expected operand Exp data type to be a "
1396 << (_
.HasExtension(kSPV_AMD_gpu_shader_int16
)
1397 ? "16-bit or 32-bit "
1399 << "int scalar or vector type";
1402 if (_
.GetDimension(result_type
) != _
.GetDimension(exp_data_type
)) {
1403 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1404 << ext_inst_name() << ": "
1405 << "expected operand Exp data type to have the same component "
1406 << "number as Result Type";
1412 case GLSLstd450Ldexp
: {
1413 if (!_
.IsFloatScalarOrVectorType(result_type
)) {
1414 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1415 << ext_inst_name() << ": "
1416 << "expected Result Type to be a scalar or vector float type";
1419 const uint32_t x_type
= _
.GetOperandTypeId(inst
, 4);
1420 const uint32_t exp_type
= _
.GetOperandTypeId(inst
, 5);
1422 if (x_type
!= result_type
) {
1423 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1424 << ext_inst_name() << ": "
1425 << "expected operand X type to be equal to Result Type";
1428 if (!_
.IsIntScalarOrVectorType(exp_type
)) {
1429 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1430 << ext_inst_name() << ": "
1431 << "expected operand Exp to be a 32-bit int scalar "
1432 << "or vector type";
1435 if (_
.GetDimension(result_type
) != _
.GetDimension(exp_type
)) {
1436 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1437 << ext_inst_name() << ": "
1438 << "expected operand Exp to have the same component "
1439 << "number as Result Type";
1445 case GLSLstd450FrexpStruct
: {
1446 std::vector
<uint32_t> result_types
;
1447 if (!_
.GetStructMemberTypes(result_type
, &result_types
) ||
1448 result_types
.size() != 2 ||
1449 !_
.IsFloatScalarOrVectorType(result_types
[0]) ||
1450 !_
.IsIntScalarOrVectorType(result_types
[1]) ||
1451 (!_
.HasExtension(kSPV_AMD_gpu_shader_int16
) &&
1452 _
.GetBitWidth(result_types
[1]) != 32) ||
1453 (_
.HasExtension(kSPV_AMD_gpu_shader_int16
) &&
1454 _
.GetBitWidth(result_types
[1]) != 16 &&
1455 _
.GetBitWidth(result_types
[1]) != 32) ||
1456 _
.GetDimension(result_types
[0]) !=
1457 _
.GetDimension(result_types
[1])) {
1458 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1459 << ext_inst_name() << ": "
1460 << "expected Result Type to be a struct with two members, "
1461 << "first member a float scalar or vector, second member a "
1462 << (_
.HasExtension(kSPV_AMD_gpu_shader_int16
)
1463 ? "16-bit or 32-bit "
1465 << "int scalar or vector with the same number of "
1466 << "components as the first member";
1469 const uint32_t x_type
= _
.GetOperandTypeId(inst
, 4);
1470 if (x_type
!= result_types
[0]) {
1471 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1472 << ext_inst_name() << ": "
1473 << "expected operand X type to be equal to the first member "
1474 << "of Result Type struct";
1479 case GLSLstd450PackSnorm4x8
:
1480 case GLSLstd450PackUnorm4x8
: {
1481 if (!_
.IsIntScalarType(result_type
) ||
1482 _
.GetBitWidth(result_type
) != 32) {
1483 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1484 << ext_inst_name() << ": "
1485 << "expected Result Type to be 32-bit int scalar type";
1488 const uint32_t v_type
= _
.GetOperandTypeId(inst
, 4);
1489 if (!_
.IsFloatVectorType(v_type
) || _
.GetDimension(v_type
) != 4 ||
1490 _
.GetBitWidth(v_type
) != 32) {
1491 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1492 << ext_inst_name() << ": "
1493 << "expected operand V to be a 32-bit float vector of size 4";
1498 case GLSLstd450PackSnorm2x16
:
1499 case GLSLstd450PackUnorm2x16
:
1500 case GLSLstd450PackHalf2x16
: {
1501 if (!_
.IsIntScalarType(result_type
) ||
1502 _
.GetBitWidth(result_type
) != 32) {
1503 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1504 << ext_inst_name() << ": "
1505 << "expected Result Type to be 32-bit int scalar type";
1508 const uint32_t v_type
= _
.GetOperandTypeId(inst
, 4);
1509 if (!_
.IsFloatVectorType(v_type
) || _
.GetDimension(v_type
) != 2 ||
1510 _
.GetBitWidth(v_type
) != 32) {
1511 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1512 << ext_inst_name() << ": "
1513 << "expected operand V to be a 32-bit float vector of size 2";
1518 case GLSLstd450PackDouble2x32
: {
1519 if (!_
.IsFloatScalarType(result_type
) ||
1520 _
.GetBitWidth(result_type
) != 64) {
1521 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1522 << ext_inst_name() << ": "
1523 << "expected Result Type to be 64-bit float scalar type";
1526 const uint32_t v_type
= _
.GetOperandTypeId(inst
, 4);
1527 if (!_
.IsIntVectorType(v_type
) || _
.GetDimension(v_type
) != 2 ||
1528 _
.GetBitWidth(v_type
) != 32) {
1529 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1530 << ext_inst_name() << ": "
1531 << "expected operand V to be a 32-bit int vector of size 2";
1536 case GLSLstd450UnpackSnorm4x8
:
1537 case GLSLstd450UnpackUnorm4x8
: {
1538 if (!_
.IsFloatVectorType(result_type
) ||
1539 _
.GetDimension(result_type
) != 4 ||
1540 _
.GetBitWidth(result_type
) != 32) {
1541 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1542 << ext_inst_name() << ": "
1543 << "expected Result Type to be a 32-bit float vector of size "
1547 const uint32_t v_type
= _
.GetOperandTypeId(inst
, 4);
1548 if (!_
.IsIntScalarType(v_type
) || _
.GetBitWidth(v_type
) != 32) {
1549 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1550 << ext_inst_name() << ": "
1551 << "expected operand P to be a 32-bit int scalar";
1556 case GLSLstd450UnpackSnorm2x16
:
1557 case GLSLstd450UnpackUnorm2x16
:
1558 case GLSLstd450UnpackHalf2x16
: {
1559 if (!_
.IsFloatVectorType(result_type
) ||
1560 _
.GetDimension(result_type
) != 2 ||
1561 _
.GetBitWidth(result_type
) != 32) {
1562 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1563 << ext_inst_name() << ": "
1564 << "expected Result Type to be a 32-bit float vector of size "
1568 const uint32_t v_type
= _
.GetOperandTypeId(inst
, 4);
1569 if (!_
.IsIntScalarType(v_type
) || _
.GetBitWidth(v_type
) != 32) {
1570 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1571 << ext_inst_name() << ": "
1572 << "expected operand P to be a 32-bit int scalar";
1577 case GLSLstd450UnpackDouble2x32
: {
1578 if (!_
.IsIntVectorType(result_type
) ||
1579 _
.GetDimension(result_type
) != 2 ||
1580 _
.GetBitWidth(result_type
) != 32) {
1581 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1582 << ext_inst_name() << ": "
1583 << "expected Result Type to be a 32-bit int vector of size "
1587 const uint32_t v_type
= _
.GetOperandTypeId(inst
, 4);
1588 if (!_
.IsFloatScalarType(v_type
) || _
.GetBitWidth(v_type
) != 64) {
1589 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1590 << ext_inst_name() << ": "
1591 << "expected operand V to be a 64-bit float scalar";
1596 case GLSLstd450Length
: {
1597 if (!_
.IsFloatScalarType(result_type
)) {
1598 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1599 << ext_inst_name() << ": "
1600 << "expected Result Type to be a float scalar type";
1603 const uint32_t x_type
= _
.GetOperandTypeId(inst
, 4);
1604 if (!_
.IsFloatScalarOrVectorType(x_type
)) {
1605 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1606 << ext_inst_name() << ": "
1607 << "expected operand X to be of float scalar or vector type";
1610 if (result_type
!= _
.GetComponentType(x_type
)) {
1611 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1612 << ext_inst_name() << ": "
1613 << "expected operand X component type to be equal to Result "
1619 case GLSLstd450Distance
: {
1620 if (!_
.IsFloatScalarType(result_type
)) {
1621 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1622 << ext_inst_name() << ": "
1623 << "expected Result Type to be a float scalar type";
1626 const uint32_t p0_type
= _
.GetOperandTypeId(inst
, 4);
1627 if (!_
.IsFloatScalarOrVectorType(p0_type
)) {
1628 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1629 << ext_inst_name() << ": "
1630 << "expected operand P0 to be of float scalar or vector type";
1633 if (result_type
!= _
.GetComponentType(p0_type
)) {
1634 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1635 << ext_inst_name() << ": "
1636 << "expected operand P0 component type to be equal to "
1640 const uint32_t p1_type
= _
.GetOperandTypeId(inst
, 5);
1641 if (!_
.IsFloatScalarOrVectorType(p1_type
)) {
1642 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1643 << ext_inst_name() << ": "
1644 << "expected operand P1 to be of float scalar or vector type";
1647 if (result_type
!= _
.GetComponentType(p1_type
)) {
1648 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1649 << ext_inst_name() << ": "
1650 << "expected operand P1 component type to be equal to "
1654 if (_
.GetDimension(p0_type
) != _
.GetDimension(p1_type
)) {
1655 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1656 << ext_inst_name() << ": "
1657 << "expected operands P0 and P1 to have the same number of "
1663 case GLSLstd450Cross
: {
1664 if (!_
.IsFloatVectorType(result_type
)) {
1665 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1666 << ext_inst_name() << ": "
1667 << "expected Result Type to be a float vector type";
1670 if (_
.GetDimension(result_type
) != 3) {
1671 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1672 << ext_inst_name() << ": "
1673 << "expected Result Type to have 3 components";
1676 const uint32_t x_type
= _
.GetOperandTypeId(inst
, 4);
1677 const uint32_t y_type
= _
.GetOperandTypeId(inst
, 5);
1679 if (x_type
!= result_type
) {
1680 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1681 << ext_inst_name() << ": "
1682 << "expected operand X type to be equal to Result Type";
1685 if (y_type
!= result_type
) {
1686 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1687 << ext_inst_name() << ": "
1688 << "expected operand Y type to be equal to Result Type";
1693 case GLSLstd450Refract
: {
1694 if (!_
.IsFloatScalarOrVectorType(result_type
)) {
1695 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1696 << ext_inst_name() << ": "
1697 << "expected Result Type to be a float scalar or vector type";
1700 const uint32_t i_type
= _
.GetOperandTypeId(inst
, 4);
1701 const uint32_t n_type
= _
.GetOperandTypeId(inst
, 5);
1702 const uint32_t eta_type
= _
.GetOperandTypeId(inst
, 6);
1704 if (result_type
!= i_type
) {
1705 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1706 << ext_inst_name() << ": "
1707 << "expected operand I to be of type equal to Result Type";
1710 if (result_type
!= n_type
) {
1711 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1712 << ext_inst_name() << ": "
1713 << "expected operand N to be of type equal to Result Type";
1716 if (!_
.IsFloatScalarType(eta_type
)) {
1717 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1718 << ext_inst_name() << ": "
1719 << "expected operand Eta to be a float scalar";
1724 case GLSLstd450InterpolateAtCentroid
:
1725 case GLSLstd450InterpolateAtSample
:
1726 case GLSLstd450InterpolateAtOffset
: {
1727 if (!_
.HasCapability(spv::Capability::InterpolationFunction
)) {
1728 return _
.diag(SPV_ERROR_INVALID_CAPABILITY
, inst
)
1730 << " requires capability InterpolationFunction";
1733 if (!_
.IsFloatScalarOrVectorType(result_type
) ||
1734 _
.GetBitWidth(result_type
) != 32) {
1735 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1736 << ext_inst_name() << ": "
1737 << "expected Result Type to be a 32-bit float scalar "
1738 << "or vector type";
1741 // If HLSL legalization and first operand is an OpLoad, use load
1742 // pointer as the interpolant lvalue. Else use interpolate first
1744 uint32_t interp_id
= inst
->GetOperandAs
<uint32_t>(4);
1745 auto* interp_inst
= _
.FindDef(interp_id
);
1746 uint32_t interpolant_type
= (_
.options()->before_hlsl_legalization
&&
1747 interp_inst
->opcode() == spv::Op::OpLoad
)
1748 ? _
.GetOperandTypeId(interp_inst
, 2)
1749 : _
.GetOperandTypeId(inst
, 4);
1751 spv::StorageClass interpolant_storage_class
;
1752 uint32_t interpolant_data_type
= 0;
1753 if (!_
.GetPointerTypeInfo(interpolant_type
, &interpolant_data_type
,
1754 &interpolant_storage_class
)) {
1755 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1756 << ext_inst_name() << ": "
1757 << "expected Interpolant to be a pointer";
1760 if (result_type
!= interpolant_data_type
) {
1761 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1762 << ext_inst_name() << ": "
1763 << "expected Interpolant data type to be equal to Result Type";
1766 if (interpolant_storage_class
!= spv::StorageClass::Input
) {
1767 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1768 << ext_inst_name() << ": "
1769 << "expected Interpolant storage class to be Input";
1772 if (ext_inst_key
== GLSLstd450InterpolateAtSample
) {
1773 const uint32_t sample_type
= _
.GetOperandTypeId(inst
, 5);
1774 if (!_
.IsIntScalarType(sample_type
) ||
1775 _
.GetBitWidth(sample_type
) != 32) {
1776 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1777 << ext_inst_name() << ": "
1778 << "expected Sample to be 32-bit integer";
1782 if (ext_inst_key
== GLSLstd450InterpolateAtOffset
) {
1783 const uint32_t offset_type
= _
.GetOperandTypeId(inst
, 5);
1784 if (!_
.IsFloatVectorType(offset_type
) ||
1785 _
.GetDimension(offset_type
) != 2 ||
1786 _
.GetBitWidth(offset_type
) != 32) {
1787 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1788 << ext_inst_name() << ": "
1789 << "expected Offset to be a vector of 2 32-bit floats";
1793 _
.function(inst
->function()->id())
1794 ->RegisterExecutionModelLimitation(
1795 spv::ExecutionModel::Fragment
,
1797 std::string(" requires Fragment execution model"));
1801 case GLSLstd450IMix
: {
1802 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1803 << "Extended instruction GLSLstd450IMix is not supported";
1806 case GLSLstd450Bad
: {
1807 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1808 << "Encountered extended instruction GLSLstd450Bad";
1811 case GLSLstd450Count
: {
1816 } else if (ext_inst_type
== SPV_EXT_INST_TYPE_OPENCL_STD
) {
1817 const OpenCLLIB::Entrypoints ext_inst_key
=
1818 OpenCLLIB::Entrypoints(ext_inst_index
);
1819 switch (ext_inst_key
) {
1820 case OpenCLLIB::Acos
:
1821 case OpenCLLIB::Acosh
:
1822 case OpenCLLIB::Acospi
:
1823 case OpenCLLIB::Asin
:
1824 case OpenCLLIB::Asinh
:
1825 case OpenCLLIB::Asinpi
:
1826 case OpenCLLIB::Atan
:
1827 case OpenCLLIB::Atan2
:
1828 case OpenCLLIB::Atanh
:
1829 case OpenCLLIB::Atanpi
:
1830 case OpenCLLIB::Atan2pi
:
1831 case OpenCLLIB::Cbrt
:
1832 case OpenCLLIB::Ceil
:
1833 case OpenCLLIB::Copysign
:
1834 case OpenCLLIB::Cos
:
1835 case OpenCLLIB::Cosh
:
1836 case OpenCLLIB::Cospi
:
1837 case OpenCLLIB::Erfc
:
1838 case OpenCLLIB::Erf
:
1839 case OpenCLLIB::Exp
:
1840 case OpenCLLIB::Exp2
:
1841 case OpenCLLIB::Exp10
:
1842 case OpenCLLIB::Expm1
:
1843 case OpenCLLIB::Fabs
:
1844 case OpenCLLIB::Fdim
:
1845 case OpenCLLIB::Floor
:
1846 case OpenCLLIB::Fma
:
1847 case OpenCLLIB::Fmax
:
1848 case OpenCLLIB::Fmin
:
1849 case OpenCLLIB::Fmod
:
1850 case OpenCLLIB::Hypot
:
1851 case OpenCLLIB::Lgamma
:
1852 case OpenCLLIB::Log
:
1853 case OpenCLLIB::Log2
:
1854 case OpenCLLIB::Log10
:
1855 case OpenCLLIB::Log1p
:
1856 case OpenCLLIB::Logb
:
1857 case OpenCLLIB::Mad
:
1858 case OpenCLLIB::Maxmag
:
1859 case OpenCLLIB::Minmag
:
1860 case OpenCLLIB::Nextafter
:
1861 case OpenCLLIB::Pow
:
1862 case OpenCLLIB::Powr
:
1863 case OpenCLLIB::Remainder
:
1864 case OpenCLLIB::Rint
:
1865 case OpenCLLIB::Round
:
1866 case OpenCLLIB::Rsqrt
:
1867 case OpenCLLIB::Sin
:
1868 case OpenCLLIB::Sinh
:
1869 case OpenCLLIB::Sinpi
:
1870 case OpenCLLIB::Sqrt
:
1871 case OpenCLLIB::Tan
:
1872 case OpenCLLIB::Tanh
:
1873 case OpenCLLIB::Tanpi
:
1874 case OpenCLLIB::Tgamma
:
1875 case OpenCLLIB::Trunc
:
1876 case OpenCLLIB::Half_cos
:
1877 case OpenCLLIB::Half_divide
:
1878 case OpenCLLIB::Half_exp
:
1879 case OpenCLLIB::Half_exp2
:
1880 case OpenCLLIB::Half_exp10
:
1881 case OpenCLLIB::Half_log
:
1882 case OpenCLLIB::Half_log2
:
1883 case OpenCLLIB::Half_log10
:
1884 case OpenCLLIB::Half_powr
:
1885 case OpenCLLIB::Half_recip
:
1886 case OpenCLLIB::Half_rsqrt
:
1887 case OpenCLLIB::Half_sin
:
1888 case OpenCLLIB::Half_sqrt
:
1889 case OpenCLLIB::Half_tan
:
1890 case OpenCLLIB::Native_cos
:
1891 case OpenCLLIB::Native_divide
:
1892 case OpenCLLIB::Native_exp
:
1893 case OpenCLLIB::Native_exp2
:
1894 case OpenCLLIB::Native_exp10
:
1895 case OpenCLLIB::Native_log
:
1896 case OpenCLLIB::Native_log2
:
1897 case OpenCLLIB::Native_log10
:
1898 case OpenCLLIB::Native_powr
:
1899 case OpenCLLIB::Native_recip
:
1900 case OpenCLLIB::Native_rsqrt
:
1901 case OpenCLLIB::Native_sin
:
1902 case OpenCLLIB::Native_sqrt
:
1903 case OpenCLLIB::Native_tan
:
1904 case OpenCLLIB::FClamp
:
1905 case OpenCLLIB::Degrees
:
1906 case OpenCLLIB::FMax_common
:
1907 case OpenCLLIB::FMin_common
:
1908 case OpenCLLIB::Mix
:
1909 case OpenCLLIB::Radians
:
1910 case OpenCLLIB::Step
:
1911 case OpenCLLIB::Smoothstep
:
1912 case OpenCLLIB::Sign
: {
1913 if (!_
.IsFloatScalarOrVectorType(result_type
)) {
1914 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1915 << ext_inst_name() << ": "
1916 << "expected Result Type to be a float scalar or vector type";
1919 const uint32_t num_components
= _
.GetDimension(result_type
);
1920 if (num_components
> 4 && num_components
!= 8 && num_components
!= 16) {
1921 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1922 << ext_inst_name() << ": "
1923 << "expected Result Type to be a scalar or a vector with 2, "
1924 "3, 4, 8 or 16 components";
1927 for (uint32_t operand_index
= 4; operand_index
< num_operands
;
1929 const uint32_t operand_type
= _
.GetOperandTypeId(inst
, operand_index
);
1930 if (result_type
!= operand_type
) {
1931 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1932 << ext_inst_name() << ": "
1933 << "expected types of all operands to be equal to Result "
1940 case OpenCLLIB::Fract
:
1941 case OpenCLLIB::Modf
:
1942 case OpenCLLIB::Sincos
: {
1943 if (!_
.IsFloatScalarOrVectorType(result_type
)) {
1944 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1945 << ext_inst_name() << ": "
1946 << "expected Result Type to be a float scalar or vector type";
1949 const uint32_t num_components
= _
.GetDimension(result_type
);
1950 if (num_components
> 4 && num_components
!= 8 && num_components
!= 16) {
1951 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1952 << ext_inst_name() << ": "
1953 << "expected Result Type to be a scalar or a vector with 2, "
1954 "3, 4, 8 or 16 components";
1957 const uint32_t x_type
= _
.GetOperandTypeId(inst
, 4);
1958 if (result_type
!= x_type
) {
1959 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1960 << ext_inst_name() << ": "
1961 << "expected type of operand X to be equal to Result Type";
1964 const uint32_t p_type
= _
.GetOperandTypeId(inst
, 5);
1965 spv::StorageClass p_storage_class
;
1966 uint32_t p_data_type
= 0;
1967 if (!_
.GetPointerTypeInfo(p_type
, &p_data_type
, &p_storage_class
)) {
1968 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1969 << ext_inst_name() << ": "
1970 << "expected the last operand to be a pointer";
1973 if (p_storage_class
!= spv::StorageClass::Generic
&&
1974 p_storage_class
!= spv::StorageClass::CrossWorkgroup
&&
1975 p_storage_class
!= spv::StorageClass::Workgroup
&&
1976 p_storage_class
!= spv::StorageClass::Function
) {
1977 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1978 << ext_inst_name() << ": "
1979 << "expected storage class of the pointer to be Generic, "
1980 "CrossWorkgroup, Workgroup or Function";
1983 if (!_
.ContainsUntypedPointer(p_type
) && result_type
!= p_data_type
) {
1984 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1985 << ext_inst_name() << ": "
1986 << "expected data type of the pointer to be equal to Result "
1992 case OpenCLLIB::Frexp
:
1993 case OpenCLLIB::Lgamma_r
:
1994 case OpenCLLIB::Remquo
: {
1995 if (!_
.IsFloatScalarOrVectorType(result_type
)) {
1996 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
1997 << ext_inst_name() << ": "
1998 << "expected Result Type to be a float scalar or vector type";
2001 const uint32_t num_components
= _
.GetDimension(result_type
);
2002 if (num_components
> 4 && num_components
!= 8 && num_components
!= 16) {
2003 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2004 << ext_inst_name() << ": "
2005 << "expected Result Type to be a scalar or a vector with 2, "
2006 "3, 4, 8 or 16 components";
2009 uint32_t operand_index
= 4;
2010 const uint32_t x_type
= _
.GetOperandTypeId(inst
, operand_index
++);
2011 if (result_type
!= x_type
) {
2012 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2013 << ext_inst_name() << ": "
2014 << "expected type of operand X to be equal to Result Type";
2017 if (ext_inst_key
== OpenCLLIB::Remquo
) {
2018 const uint32_t y_type
= _
.GetOperandTypeId(inst
, operand_index
++);
2019 if (result_type
!= y_type
) {
2020 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2021 << ext_inst_name() << ": "
2022 << "expected type of operand Y to be equal to Result Type";
2026 const uint32_t p_type
= _
.GetOperandTypeId(inst
, operand_index
++);
2027 spv::StorageClass p_storage_class
;
2028 uint32_t p_data_type
= 0;
2029 if (!_
.GetPointerTypeInfo(p_type
, &p_data_type
, &p_storage_class
)) {
2030 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2031 << ext_inst_name() << ": "
2032 << "expected the last operand to be a pointer";
2035 if (p_storage_class
!= spv::StorageClass::Generic
&&
2036 p_storage_class
!= spv::StorageClass::CrossWorkgroup
&&
2037 p_storage_class
!= spv::StorageClass::Workgroup
&&
2038 p_storage_class
!= spv::StorageClass::Function
) {
2039 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2040 << ext_inst_name() << ": "
2041 << "expected storage class of the pointer to be Generic, "
2042 "CrossWorkgroup, Workgroup or Function";
2045 if ((!_
.IsIntScalarOrVectorType(p_data_type
) ||
2046 _
.GetBitWidth(p_data_type
) != 32) &&
2047 !_
.ContainsUntypedPointer(p_type
)) {
2048 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2049 << ext_inst_name() << ": "
2050 << "expected data type of the pointer to be a 32-bit int "
2051 "scalar or vector type";
2054 if (!_
.ContainsUntypedPointer(p_type
) &&
2055 _
.GetDimension(p_data_type
) != num_components
) {
2056 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2057 << ext_inst_name() << ": "
2058 << "expected data type of the pointer to have the same number "
2059 "of components as Result Type";
2064 case OpenCLLIB::Ilogb
: {
2065 if (!_
.IsIntScalarOrVectorType(result_type
) ||
2066 _
.GetBitWidth(result_type
) != 32) {
2067 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2068 << ext_inst_name() << ": "
2069 << "expected Result Type to be a 32-bit int scalar or vector "
2073 const uint32_t num_components
= _
.GetDimension(result_type
);
2074 if (num_components
> 4 && num_components
!= 8 && num_components
!= 16) {
2075 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2076 << ext_inst_name() << ": "
2077 << "expected Result Type to be a scalar or a vector with 2, "
2078 "3, 4, 8 or 16 components";
2081 const uint32_t x_type
= _
.GetOperandTypeId(inst
, 4);
2082 if (!_
.IsFloatScalarOrVectorType(x_type
)) {
2083 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2084 << ext_inst_name() << ": "
2085 << "expected operand X to be a float scalar or vector";
2088 if (_
.GetDimension(x_type
) != num_components
) {
2089 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2090 << ext_inst_name() << ": "
2091 << "expected operand X to have the same number of components "
2097 case OpenCLLIB::Ldexp
:
2098 case OpenCLLIB::Pown
:
2099 case OpenCLLIB::Rootn
: {
2100 if (!_
.IsFloatScalarOrVectorType(result_type
)) {
2101 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2102 << ext_inst_name() << ": "
2103 << "expected Result Type to be a float scalar or vector type";
2106 const uint32_t num_components
= _
.GetDimension(result_type
);
2107 if (num_components
> 4 && num_components
!= 8 && num_components
!= 16) {
2108 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2109 << ext_inst_name() << ": "
2110 << "expected Result Type to be a scalar or a vector with 2, "
2111 "3, 4, 8 or 16 components";
2114 const uint32_t x_type
= _
.GetOperandTypeId(inst
, 4);
2115 if (result_type
!= x_type
) {
2116 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2117 << ext_inst_name() << ": "
2118 << "expected type of operand X to be equal to Result Type";
2121 const uint32_t exp_type
= _
.GetOperandTypeId(inst
, 5);
2122 if (!_
.IsIntScalarOrVectorType(exp_type
) ||
2123 _
.GetBitWidth(exp_type
) != 32) {
2124 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2125 << ext_inst_name() << ": "
2126 << "expected the exponent to be a 32-bit int scalar or vector";
2129 if (_
.GetDimension(exp_type
) != num_components
) {
2130 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2131 << ext_inst_name() << ": "
2132 << "expected the exponent to have the same number of "
2133 "components as Result Type";
2138 case OpenCLLIB::Nan
: {
2139 if (!_
.IsFloatScalarOrVectorType(result_type
)) {
2140 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2141 << ext_inst_name() << ": "
2142 << "expected Result Type to be a float scalar or vector type";
2145 const uint32_t num_components
= _
.GetDimension(result_type
);
2146 if (num_components
> 4 && num_components
!= 8 && num_components
!= 16) {
2147 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2148 << ext_inst_name() << ": "
2149 << "expected Result Type to be a scalar or a vector with 2, "
2150 "3, 4, 8 or 16 components";
2153 const uint32_t nancode_type
= _
.GetOperandTypeId(inst
, 4);
2154 if (!_
.IsIntScalarOrVectorType(nancode_type
)) {
2155 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2156 << ext_inst_name() << ": "
2157 << "expected Nancode to be an int scalar or vector type";
2160 if (_
.GetDimension(nancode_type
) != num_components
) {
2161 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2162 << ext_inst_name() << ": "
2163 << "expected Nancode to have the same number of components as "
2167 if (_
.GetBitWidth(result_type
) != _
.GetBitWidth(nancode_type
)) {
2168 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2169 << ext_inst_name() << ": "
2170 << "expected Nancode to have the same bit width as Result "
2176 case OpenCLLIB::SAbs
:
2177 case OpenCLLIB::SAbs_diff
:
2178 case OpenCLLIB::SAdd_sat
:
2179 case OpenCLLIB::UAdd_sat
:
2180 case OpenCLLIB::SHadd
:
2181 case OpenCLLIB::UHadd
:
2182 case OpenCLLIB::SRhadd
:
2183 case OpenCLLIB::URhadd
:
2184 case OpenCLLIB::SClamp
:
2185 case OpenCLLIB::UClamp
:
2186 case OpenCLLIB::Clz
:
2187 case OpenCLLIB::Ctz
:
2188 case OpenCLLIB::SMad_hi
:
2189 case OpenCLLIB::UMad_sat
:
2190 case OpenCLLIB::SMad_sat
:
2191 case OpenCLLIB::SMax
:
2192 case OpenCLLIB::UMax
:
2193 case OpenCLLIB::SMin
:
2194 case OpenCLLIB::UMin
:
2195 case OpenCLLIB::SMul_hi
:
2196 case OpenCLLIB::Rotate
:
2197 case OpenCLLIB::SSub_sat
:
2198 case OpenCLLIB::USub_sat
:
2199 case OpenCLLIB::Popcount
:
2200 case OpenCLLIB::UAbs
:
2201 case OpenCLLIB::UAbs_diff
:
2202 case OpenCLLIB::UMul_hi
:
2203 case OpenCLLIB::UMad_hi
: {
2204 if (!_
.IsIntScalarOrVectorType(result_type
)) {
2205 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2206 << ext_inst_name() << ": "
2207 << "expected Result Type to be an int scalar or vector type";
2210 const uint32_t num_components
= _
.GetDimension(result_type
);
2211 if (num_components
> 4 && num_components
!= 8 && num_components
!= 16) {
2212 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2213 << ext_inst_name() << ": "
2214 << "expected Result Type to be a scalar or a vector with 2, "
2215 "3, 4, 8 or 16 components";
2218 for (uint32_t operand_index
= 4; operand_index
< num_operands
;
2220 const uint32_t operand_type
= _
.GetOperandTypeId(inst
, operand_index
);
2221 if (result_type
!= operand_type
) {
2222 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2223 << ext_inst_name() << ": "
2224 << "expected types of all operands to be equal to Result "
2231 case OpenCLLIB::U_Upsample
:
2232 case OpenCLLIB::S_Upsample
: {
2233 if (!_
.IsIntScalarOrVectorType(result_type
)) {
2234 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2235 << ext_inst_name() << ": "
2236 << "expected Result Type to be an int scalar or vector "
2240 const uint32_t result_num_components
= _
.GetDimension(result_type
);
2241 if (result_num_components
> 4 && result_num_components
!= 8 &&
2242 result_num_components
!= 16) {
2243 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2244 << ext_inst_name() << ": "
2245 << "expected Result Type to be a scalar or a vector with 2, "
2246 "3, 4, 8 or 16 components";
2249 const uint32_t result_bit_width
= _
.GetBitWidth(result_type
);
2250 if (result_bit_width
!= 16 && result_bit_width
!= 32 &&
2251 result_bit_width
!= 64) {
2252 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2253 << ext_inst_name() << ": "
2254 << "expected bit width of Result Type components to be 16, 32 "
2258 const uint32_t hi_type
= _
.GetOperandTypeId(inst
, 4);
2259 const uint32_t lo_type
= _
.GetOperandTypeId(inst
, 5);
2261 if (hi_type
!= lo_type
) {
2262 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2263 << ext_inst_name() << ": "
2264 << "expected Hi and Lo operands to have the same type";
2267 if (result_num_components
!= _
.GetDimension(hi_type
)) {
2268 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2269 << ext_inst_name() << ": "
2270 << "expected Hi and Lo operands to have the same number of "
2271 "components as Result Type";
2274 if (result_bit_width
!= 2 * _
.GetBitWidth(hi_type
)) {
2275 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2276 << ext_inst_name() << ": "
2277 << "expected bit width of components of Hi and Lo operands to "
2278 "be half of the bit width of components of Result Type";
2283 case OpenCLLIB::SMad24
:
2284 case OpenCLLIB::UMad24
:
2285 case OpenCLLIB::SMul24
:
2286 case OpenCLLIB::UMul24
: {
2287 if (!_
.IsIntScalarOrVectorType(result_type
) ||
2288 _
.GetBitWidth(result_type
) != 32) {
2289 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2290 << ext_inst_name() << ": "
2291 << "expected Result Type to be a 32-bit int scalar or vector "
2295 const uint32_t num_components
= _
.GetDimension(result_type
);
2296 if (num_components
> 4 && num_components
!= 8 && num_components
!= 16) {
2297 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2298 << ext_inst_name() << ": "
2299 << "expected Result Type to be a scalar or a vector with 2, "
2300 "3, 4, 8 or 16 components";
2303 for (uint32_t operand_index
= 4; operand_index
< num_operands
;
2305 const uint32_t operand_type
= _
.GetOperandTypeId(inst
, operand_index
);
2306 if (result_type
!= operand_type
) {
2307 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2308 << ext_inst_name() << ": "
2309 << "expected types of all operands to be equal to Result "
2316 case OpenCLLIB::Cross
: {
2317 if (!_
.IsFloatVectorType(result_type
)) {
2318 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2319 << ext_inst_name() << ": "
2320 << "expected Result Type to be a float vector type";
2323 const uint32_t num_components
= _
.GetDimension(result_type
);
2324 if (num_components
!= 3 && num_components
!= 4) {
2325 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2326 << ext_inst_name() << ": "
2327 << "expected Result Type to have 3 or 4 components";
2330 const uint32_t x_type
= _
.GetOperandTypeId(inst
, 4);
2331 const uint32_t y_type
= _
.GetOperandTypeId(inst
, 5);
2333 if (x_type
!= result_type
) {
2334 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2335 << ext_inst_name() << ": "
2336 << "expected operand X type to be equal to Result Type";
2339 if (y_type
!= result_type
) {
2340 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2341 << ext_inst_name() << ": "
2342 << "expected operand Y type to be equal to Result Type";
2347 case OpenCLLIB::Distance
:
2348 case OpenCLLIB::Fast_distance
: {
2349 if (!_
.IsFloatScalarType(result_type
)) {
2350 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2351 << ext_inst_name() << ": "
2352 << "expected Result Type to be a float scalar type";
2355 const uint32_t p0_type
= _
.GetOperandTypeId(inst
, 4);
2356 if (!_
.IsFloatScalarOrVectorType(p0_type
)) {
2357 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2358 << ext_inst_name() << ": "
2359 << "expected operand P0 to be of float scalar or vector type";
2362 const uint32_t num_components
= _
.GetDimension(p0_type
);
2363 if (num_components
> 4) {
2364 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2365 << ext_inst_name() << ": "
2366 << "expected operand P0 to have no more than 4 components";
2369 if (result_type
!= _
.GetComponentType(p0_type
)) {
2370 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2371 << ext_inst_name() << ": "
2372 << "expected operand P0 component type to be equal to "
2376 const uint32_t p1_type
= _
.GetOperandTypeId(inst
, 5);
2377 if (p0_type
!= p1_type
) {
2378 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2379 << ext_inst_name() << ": "
2380 << "expected operands P0 and P1 to be of the same type";
2385 case OpenCLLIB::Length
:
2386 case OpenCLLIB::Fast_length
: {
2387 if (!_
.IsFloatScalarType(result_type
)) {
2388 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2389 << ext_inst_name() << ": "
2390 << "expected Result Type to be a float scalar type";
2393 const uint32_t p_type
= _
.GetOperandTypeId(inst
, 4);
2394 if (!_
.IsFloatScalarOrVectorType(p_type
)) {
2395 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2396 << ext_inst_name() << ": "
2397 << "expected operand P to be a float scalar or vector";
2400 const uint32_t num_components
= _
.GetDimension(p_type
);
2401 if (num_components
> 4) {
2402 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2403 << ext_inst_name() << ": "
2404 << "expected operand P to have no more than 4 components";
2407 if (result_type
!= _
.GetComponentType(p_type
)) {
2408 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2409 << ext_inst_name() << ": "
2410 << "expected operand P component type to be equal to Result "
2416 case OpenCLLIB::Normalize
:
2417 case OpenCLLIB::Fast_normalize
: {
2418 if (!_
.IsFloatScalarOrVectorType(result_type
)) {
2419 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2420 << ext_inst_name() << ": "
2421 << "expected Result Type to be a float scalar or vector type";
2424 const uint32_t num_components
= _
.GetDimension(result_type
);
2425 if (num_components
> 4) {
2426 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2427 << ext_inst_name() << ": "
2428 << "expected Result Type to have no more than 4 components";
2431 const uint32_t p_type
= _
.GetOperandTypeId(inst
, 4);
2432 if (p_type
!= result_type
) {
2433 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2434 << ext_inst_name() << ": "
2435 << "expected operand P type to be equal to Result Type";
2440 case OpenCLLIB::Bitselect
: {
2441 if (!_
.IsFloatScalarOrVectorType(result_type
) &&
2442 !_
.IsIntScalarOrVectorType(result_type
)) {
2443 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2444 << ext_inst_name() << ": "
2445 << "expected Result Type to be an int or float scalar or "
2449 const uint32_t num_components
= _
.GetDimension(result_type
);
2450 if (num_components
> 4 && num_components
!= 8 && num_components
!= 16) {
2451 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2452 << ext_inst_name() << ": "
2453 << "expected Result Type to be a scalar or a vector with 2, "
2454 "3, 4, 8 or 16 components";
2457 for (uint32_t operand_index
= 4; operand_index
< num_operands
;
2459 const uint32_t operand_type
= _
.GetOperandTypeId(inst
, operand_index
);
2460 if (result_type
!= operand_type
) {
2461 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2462 << ext_inst_name() << ": "
2463 << "expected types of all operands to be equal to Result "
2470 case OpenCLLIB::Select
: {
2471 if (!_
.IsFloatScalarOrVectorType(result_type
) &&
2472 !_
.IsIntScalarOrVectorType(result_type
)) {
2473 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2474 << ext_inst_name() << ": "
2475 << "expected Result Type to be an int or float scalar or "
2479 const uint32_t num_components
= _
.GetDimension(result_type
);
2480 if (num_components
> 4 && num_components
!= 8 && num_components
!= 16) {
2481 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2482 << ext_inst_name() << ": "
2483 << "expected Result Type to be a scalar or a vector with 2, "
2484 "3, 4, 8 or 16 components";
2487 const uint32_t a_type
= _
.GetOperandTypeId(inst
, 4);
2488 const uint32_t b_type
= _
.GetOperandTypeId(inst
, 5);
2489 const uint32_t c_type
= _
.GetOperandTypeId(inst
, 6);
2491 if (result_type
!= a_type
) {
2492 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2493 << ext_inst_name() << ": "
2494 << "expected operand A type to be equal to Result Type";
2497 if (result_type
!= b_type
) {
2498 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2499 << ext_inst_name() << ": "
2500 << "expected operand B type to be equal to Result Type";
2503 if (!_
.IsIntScalarOrVectorType(c_type
)) {
2504 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2505 << ext_inst_name() << ": "
2506 << "expected operand C to be an int scalar or vector";
2509 if (num_components
!= _
.GetDimension(c_type
)) {
2510 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2511 << ext_inst_name() << ": "
2512 << "expected operand C to have the same number of components "
2516 if (_
.GetBitWidth(result_type
) != _
.GetBitWidth(c_type
)) {
2517 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2518 << ext_inst_name() << ": "
2519 << "expected operand C to have the same bit width as Result "
2525 case OpenCLLIB::Vloadn
: {
2526 if (!_
.IsFloatVectorType(result_type
) &&
2527 !_
.IsIntVectorType(result_type
)) {
2528 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2529 << ext_inst_name() << ": "
2530 << "expected Result Type to be an int or float vector type";
2533 const uint32_t num_components
= _
.GetDimension(result_type
);
2534 if (num_components
> 4 && num_components
!= 8 && num_components
!= 16) {
2535 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2536 << ext_inst_name() << ": "
2537 << "expected Result Type to have 2, 3, 4, 8 or 16 components";
2540 const uint32_t offset_type
= _
.GetOperandTypeId(inst
, 4);
2541 const uint32_t p_type
= _
.GetOperandTypeId(inst
, 5);
2543 const uint32_t size_t_bit_width
= GetSizeTBitWidth(_
);
2544 if (!size_t_bit_width
) {
2545 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2547 << " can only be used with physical addressing models";
2550 if (!_
.IsIntScalarType(offset_type
) ||
2551 _
.GetBitWidth(offset_type
) != size_t_bit_width
) {
2552 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2553 << ext_inst_name() << ": "
2554 << "expected operand Offset to be of type size_t ("
2556 << "-bit integer for the addressing model used in the module)";
2559 spv::StorageClass p_storage_class
;
2560 uint32_t p_data_type
= 0;
2561 if (!_
.GetPointerTypeInfo(p_type
, &p_data_type
, &p_storage_class
)) {
2562 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2563 << ext_inst_name() << ": "
2564 << "expected operand P to be a pointer";
2567 if (p_storage_class
!= spv::StorageClass::UniformConstant
&&
2568 p_storage_class
!= spv::StorageClass::Generic
&&
2569 p_storage_class
!= spv::StorageClass::CrossWorkgroup
&&
2570 p_storage_class
!= spv::StorageClass::Workgroup
&&
2571 p_storage_class
!= spv::StorageClass::Function
) {
2572 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2573 << ext_inst_name() << ": "
2574 << "expected operand P storage class to be UniformConstant, "
2575 "Generic, CrossWorkgroup, Workgroup or Function";
2578 if (_
.GetComponentType(result_type
) != p_data_type
) {
2579 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2580 << ext_inst_name() << ": "
2581 << "expected operand P data type to be equal to component "
2582 "type of Result Type";
2585 const uint32_t n_value
= inst
->word(7);
2586 if (num_components
!= n_value
) {
2587 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2588 << ext_inst_name() << ": "
2589 << "expected literal N to be equal to the number of "
2590 "components of Result Type";
2595 case OpenCLLIB::Vstoren
: {
2596 if (_
.GetIdOpcode(result_type
) != spv::Op::OpTypeVoid
) {
2597 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2598 << ext_inst_name() << ": expected Result Type to be void";
2601 const uint32_t data_type
= _
.GetOperandTypeId(inst
, 4);
2602 const uint32_t offset_type
= _
.GetOperandTypeId(inst
, 5);
2603 const uint32_t p_type
= _
.GetOperandTypeId(inst
, 6);
2605 if (!_
.IsFloatVectorType(data_type
) && !_
.IsIntVectorType(data_type
)) {
2606 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2607 << ext_inst_name() << ": "
2608 << "expected Data to be an int or float vector";
2611 const uint32_t num_components
= _
.GetDimension(data_type
);
2612 if (num_components
> 4 && num_components
!= 8 && num_components
!= 16) {
2613 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2614 << ext_inst_name() << ": "
2615 << "expected Data to have 2, 3, 4, 8 or 16 components";
2618 const uint32_t size_t_bit_width
= GetSizeTBitWidth(_
);
2619 if (!size_t_bit_width
) {
2620 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2622 << " can only be used with physical addressing models";
2625 if (!_
.IsIntScalarType(offset_type
) ||
2626 _
.GetBitWidth(offset_type
) != size_t_bit_width
) {
2627 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2628 << ext_inst_name() << ": "
2629 << "expected operand Offset to be of type size_t ("
2631 << "-bit integer for the addressing model used in the module)";
2634 spv::StorageClass p_storage_class
;
2635 uint32_t p_data_type
= 0;
2636 if (!_
.GetPointerTypeInfo(p_type
, &p_data_type
, &p_storage_class
)) {
2637 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2638 << ext_inst_name() << ": "
2639 << "expected operand P to be a pointer";
2642 if (p_storage_class
!= spv::StorageClass::Generic
&&
2643 p_storage_class
!= spv::StorageClass::CrossWorkgroup
&&
2644 p_storage_class
!= spv::StorageClass::Workgroup
&&
2645 p_storage_class
!= spv::StorageClass::Function
) {
2646 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2647 << ext_inst_name() << ": "
2648 << "expected operand P storage class to be Generic, "
2649 "CrossWorkgroup, Workgroup or Function";
2652 if (_
.GetComponentType(data_type
) != p_data_type
) {
2653 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2654 << ext_inst_name() << ": "
2655 << "expected operand P data type to be equal to the type of "
2656 "operand Data components";
2661 case OpenCLLIB::Vload_half
: {
2662 if (!_
.IsFloatScalarType(result_type
)) {
2663 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2664 << ext_inst_name() << ": "
2665 << "expected Result Type to be a float scalar type";
2668 const uint32_t offset_type
= _
.GetOperandTypeId(inst
, 4);
2669 const uint32_t p_type
= _
.GetOperandTypeId(inst
, 5);
2671 const uint32_t size_t_bit_width
= GetSizeTBitWidth(_
);
2672 if (!size_t_bit_width
) {
2673 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2675 << " can only be used with physical addressing models";
2678 if (!_
.IsIntScalarType(offset_type
) ||
2679 _
.GetBitWidth(offset_type
) != size_t_bit_width
) {
2680 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2681 << ext_inst_name() << ": "
2682 << "expected operand Offset to be of type size_t ("
2684 << "-bit integer for the addressing model used in the module)";
2687 spv::StorageClass p_storage_class
;
2688 uint32_t p_data_type
= 0;
2689 if (!_
.GetPointerTypeInfo(p_type
, &p_data_type
, &p_storage_class
)) {
2690 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2691 << ext_inst_name() << ": "
2692 << "expected operand P to be a pointer";
2695 if (p_storage_class
!= spv::StorageClass::UniformConstant
&&
2696 p_storage_class
!= spv::StorageClass::Generic
&&
2697 p_storage_class
!= spv::StorageClass::CrossWorkgroup
&&
2698 p_storage_class
!= spv::StorageClass::Workgroup
&&
2699 p_storage_class
!= spv::StorageClass::Function
) {
2700 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2701 << ext_inst_name() << ": "
2702 << "expected operand P storage class to be UniformConstant, "
2703 "Generic, CrossWorkgroup, Workgroup or Function";
2706 if ((!_
.IsFloatScalarType(p_data_type
) ||
2707 _
.GetBitWidth(p_data_type
) != 16) &&
2708 !_
.ContainsUntypedPointer(p_type
)) {
2709 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2710 << ext_inst_name() << ": "
2711 << "expected operand P data type to be 16-bit float scalar";
2716 case OpenCLLIB::Vload_halfn
:
2717 case OpenCLLIB::Vloada_halfn
: {
2718 if (!_
.IsFloatVectorType(result_type
)) {
2719 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2720 << ext_inst_name() << ": "
2721 << "expected Result Type to be a float vector type";
2724 const uint32_t num_components
= _
.GetDimension(result_type
);
2725 if (num_components
> 4 && num_components
!= 8 && num_components
!= 16) {
2726 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2727 << ext_inst_name() << ": "
2728 << "expected Result Type to have 2, 3, 4, 8 or 16 components";
2731 const uint32_t offset_type
= _
.GetOperandTypeId(inst
, 4);
2732 const uint32_t p_type
= _
.GetOperandTypeId(inst
, 5);
2734 const uint32_t size_t_bit_width
= GetSizeTBitWidth(_
);
2735 if (!size_t_bit_width
) {
2736 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2738 << " can only be used with physical addressing models";
2741 if (!_
.IsIntScalarType(offset_type
) ||
2742 _
.GetBitWidth(offset_type
) != size_t_bit_width
) {
2743 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2744 << ext_inst_name() << ": "
2745 << "expected operand Offset to be of type size_t ("
2747 << "-bit integer for the addressing model used in the module)";
2750 spv::StorageClass p_storage_class
;
2751 uint32_t p_data_type
= 0;
2752 if (!_
.GetPointerTypeInfo(p_type
, &p_data_type
, &p_storage_class
)) {
2753 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2754 << ext_inst_name() << ": "
2755 << "expected operand P to be a pointer";
2758 if (p_storage_class
!= spv::StorageClass::UniformConstant
&&
2759 p_storage_class
!= spv::StorageClass::Generic
&&
2760 p_storage_class
!= spv::StorageClass::CrossWorkgroup
&&
2761 p_storage_class
!= spv::StorageClass::Workgroup
&&
2762 p_storage_class
!= spv::StorageClass::Function
) {
2763 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2764 << ext_inst_name() << ": "
2765 << "expected operand P storage class to be UniformConstant, "
2766 "Generic, CrossWorkgroup, Workgroup or Function";
2769 if ((!_
.IsFloatScalarType(p_data_type
) ||
2770 _
.GetBitWidth(p_data_type
) != 16) &&
2771 !_
.ContainsUntypedPointer(p_type
)) {
2772 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2773 << ext_inst_name() << ": "
2774 << "expected operand P data type to be 16-bit float scalar";
2777 const uint32_t n_value
= inst
->word(7);
2778 if (num_components
!= n_value
) {
2779 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2780 << ext_inst_name() << ": "
2781 << "expected literal N to be equal to the number of "
2782 "components of Result Type";
2787 case OpenCLLIB::Vstore_half
:
2788 case OpenCLLIB::Vstore_half_r
:
2789 case OpenCLLIB::Vstore_halfn
:
2790 case OpenCLLIB::Vstore_halfn_r
:
2791 case OpenCLLIB::Vstorea_halfn
:
2792 case OpenCLLIB::Vstorea_halfn_r
: {
2793 if (_
.GetIdOpcode(result_type
) != spv::Op::OpTypeVoid
) {
2794 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2795 << ext_inst_name() << ": expected Result Type to be void";
2798 const uint32_t data_type
= _
.GetOperandTypeId(inst
, 4);
2799 const uint32_t offset_type
= _
.GetOperandTypeId(inst
, 5);
2800 const uint32_t p_type
= _
.GetOperandTypeId(inst
, 6);
2801 const uint32_t data_type_bit_width
= _
.GetBitWidth(data_type
);
2803 if (ext_inst_key
== OpenCLLIB::Vstore_half
||
2804 ext_inst_key
== OpenCLLIB::Vstore_half_r
) {
2805 if (!_
.IsFloatScalarType(data_type
) ||
2806 (data_type_bit_width
!= 32 && data_type_bit_width
!= 64)) {
2807 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2808 << ext_inst_name() << ": "
2809 << "expected Data to be a 32 or 64-bit float scalar";
2812 if (!_
.IsFloatVectorType(data_type
) ||
2813 (data_type_bit_width
!= 32 && data_type_bit_width
!= 64)) {
2814 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2815 << ext_inst_name() << ": "
2816 << "expected Data to be a 32 or 64-bit float vector";
2819 const uint32_t num_components
= _
.GetDimension(data_type
);
2820 if (num_components
> 4 && num_components
!= 8 &&
2821 num_components
!= 16) {
2822 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2823 << ext_inst_name() << ": "
2824 << "expected Data to have 2, 3, 4, 8 or 16 components";
2828 const uint32_t size_t_bit_width
= GetSizeTBitWidth(_
);
2829 if (!size_t_bit_width
) {
2830 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2832 << " can only be used with physical addressing models";
2835 if (!_
.IsIntScalarType(offset_type
) ||
2836 _
.GetBitWidth(offset_type
) != size_t_bit_width
) {
2837 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2838 << ext_inst_name() << ": "
2839 << "expected operand Offset to be of type size_t ("
2841 << "-bit integer for the addressing model used in the module)";
2844 spv::StorageClass p_storage_class
;
2845 uint32_t p_data_type
= 0;
2846 if (!_
.GetPointerTypeInfo(p_type
, &p_data_type
, &p_storage_class
)) {
2847 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2848 << ext_inst_name() << ": "
2849 << "expected operand P to be a pointer";
2852 if (p_storage_class
!= spv::StorageClass::Generic
&&
2853 p_storage_class
!= spv::StorageClass::CrossWorkgroup
&&
2854 p_storage_class
!= spv::StorageClass::Workgroup
&&
2855 p_storage_class
!= spv::StorageClass::Function
) {
2856 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2857 << ext_inst_name() << ": "
2858 << "expected operand P storage class to be Generic, "
2859 "CrossWorkgroup, Workgroup or Function";
2862 if ((!_
.IsFloatScalarType(p_data_type
) ||
2863 _
.GetBitWidth(p_data_type
) != 16) &&
2864 !_
.ContainsUntypedPointer(p_type
)) {
2865 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2866 << ext_inst_name() << ": "
2867 << "expected operand P data type to be 16-bit float scalar";
2870 // Rounding mode enum is checked by assembler.
2874 case OpenCLLIB::Shuffle
:
2875 case OpenCLLIB::Shuffle2
: {
2876 if (!_
.IsFloatVectorType(result_type
) &&
2877 !_
.IsIntVectorType(result_type
)) {
2878 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2879 << ext_inst_name() << ": "
2880 << "expected Result Type to be an int or float vector type";
2883 const uint32_t result_num_components
= _
.GetDimension(result_type
);
2884 if (result_num_components
!= 2 && result_num_components
!= 4 &&
2885 result_num_components
!= 8 && result_num_components
!= 16) {
2886 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2887 << ext_inst_name() << ": "
2888 << "expected Result Type to have 2, 4, 8 or 16 components";
2891 uint32_t operand_index
= 4;
2892 const uint32_t x_type
= _
.GetOperandTypeId(inst
, operand_index
++);
2894 if (ext_inst_key
== OpenCLLIB::Shuffle2
) {
2895 const uint32_t y_type
= _
.GetOperandTypeId(inst
, operand_index
++);
2896 if (x_type
!= y_type
) {
2897 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2898 << ext_inst_name() << ": "
2899 << "expected operands X and Y to be of the same type";
2903 const uint32_t shuffle_mask_type
=
2904 _
.GetOperandTypeId(inst
, operand_index
++);
2906 if (!_
.IsFloatVectorType(x_type
) && !_
.IsIntVectorType(x_type
)) {
2907 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2908 << ext_inst_name() << ": "
2909 << "expected operand X to be an int or float vector";
2912 const uint32_t x_num_components
= _
.GetDimension(x_type
);
2913 if (x_num_components
!= 2 && x_num_components
!= 4 &&
2914 x_num_components
!= 8 && x_num_components
!= 16) {
2915 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2916 << ext_inst_name() << ": "
2917 << "expected operand X to have 2, 4, 8 or 16 components";
2920 const uint32_t result_component_type
= _
.GetComponentType(result_type
);
2922 if (result_component_type
!= _
.GetComponentType(x_type
)) {
2923 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2924 << ext_inst_name() << ": "
2925 << "expected operand X and Result Type to have equal "
2929 if (!_
.IsIntVectorType(shuffle_mask_type
)) {
2930 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2931 << ext_inst_name() << ": "
2932 << "expected operand Shuffle Mask to be an int vector";
2935 if (result_num_components
!= _
.GetDimension(shuffle_mask_type
)) {
2936 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2937 << ext_inst_name() << ": "
2938 << "expected operand Shuffle Mask to have the same number of "
2939 "components as Result Type";
2942 if (_
.GetBitWidth(result_component_type
) !=
2943 _
.GetBitWidth(shuffle_mask_type
)) {
2944 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2945 << ext_inst_name() << ": "
2946 << "expected operand Shuffle Mask components to have the same "
2947 "bit width as Result Type components";
2952 case OpenCLLIB::Printf
: {
2953 if (!_
.IsIntScalarType(result_type
) ||
2954 _
.GetBitWidth(result_type
) != 32) {
2955 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2956 << ext_inst_name() << ": "
2957 << "expected Result Type to be a 32-bit int type";
2960 const uint32_t format_type
= _
.GetOperandTypeId(inst
, 4);
2961 spv::StorageClass format_storage_class
;
2962 uint32_t format_data_type
= 0;
2963 if (!_
.GetPointerTypeInfo(format_type
, &format_data_type
,
2964 &format_storage_class
)) {
2965 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2966 << ext_inst_name() << ": "
2967 << "expected operand Format to be a pointer";
2971 Extension::kSPV_EXT_relaxed_printf_string_address_space
)) {
2972 if (format_storage_class
!= spv::StorageClass::UniformConstant
&&
2973 // Extension SPV_EXT_relaxed_printf_string_address_space allows
2974 // format strings in Global, Local, Private and Generic address
2978 format_storage_class
!= spv::StorageClass::CrossWorkgroup
&&
2980 format_storage_class
!= spv::StorageClass::Workgroup
&&
2982 format_storage_class
!= spv::StorageClass::Function
&&
2984 format_storage_class
!= spv::StorageClass::Generic
) {
2985 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2986 << ext_inst_name() << ": "
2987 << "expected Format storage class to be UniformConstant, "
2988 "Crossworkgroup, Workgroup, Function, or Generic";
2991 if (format_storage_class
!= spv::StorageClass::UniformConstant
) {
2992 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
2993 << ext_inst_name() << ": "
2994 << "expected Format storage class to be UniformConstant";
2998 // If pointer points to an array, get the type of an element
2999 if (_
.IsIntArrayType(format_data_type
))
3000 format_data_type
= _
.GetComponentType(format_data_type
);
3002 if ((!_
.IsIntScalarType(format_data_type
) ||
3003 _
.GetBitWidth(format_data_type
) != 8) &&
3004 !_
.ContainsUntypedPointer(format_type
)) {
3005 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
3006 << ext_inst_name() << ": "
3007 << "expected Format data type to be 8-bit int";
3012 case OpenCLLIB::Prefetch
: {
3013 if (_
.GetIdOpcode(result_type
) != spv::Op::OpTypeVoid
) {
3014 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
3015 << ext_inst_name() << ": expected Result Type to be void";
3018 const uint32_t p_type
= _
.GetOperandTypeId(inst
, 4);
3019 const uint32_t num_elements_type
= _
.GetOperandTypeId(inst
, 5);
3021 spv::StorageClass p_storage_class
;
3022 uint32_t p_data_type
= 0;
3023 if (!_
.GetPointerTypeInfo(p_type
, &p_data_type
, &p_storage_class
)) {
3024 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
3025 << ext_inst_name() << ": "
3026 << "expected operand Ptr to be a pointer";
3029 if (p_storage_class
!= spv::StorageClass::CrossWorkgroup
) {
3030 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
3031 << ext_inst_name() << ": "
3032 << "expected operand Ptr storage class to be CrossWorkgroup";
3035 if (!_
.IsFloatScalarOrVectorType(p_data_type
) &&
3036 !_
.IsIntScalarOrVectorType(p_data_type
)) {
3037 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
3038 << ext_inst_name() << ": "
3039 << "expected Ptr data type to be int or float scalar or "
3043 const uint32_t num_components
= _
.GetDimension(p_data_type
);
3044 if (num_components
> 4 && num_components
!= 8 && num_components
!= 16) {
3045 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
3046 << ext_inst_name() << ": "
3047 << "expected Result Type to be a scalar or a vector with 2, "
3048 "3, 4, 8 or 16 components";
3051 const uint32_t size_t_bit_width
= GetSizeTBitWidth(_
);
3052 if (!size_t_bit_width
) {
3053 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
3055 << " can only be used with physical addressing models";
3058 if (!_
.IsIntScalarType(num_elements_type
) ||
3059 _
.GetBitWidth(num_elements_type
) != size_t_bit_width
) {
3060 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
3061 << ext_inst_name() << ": "
3062 << "expected operand Num Elements to be of type size_t ("
3064 << "-bit integer for the addressing model used in the module)";
3069 } else if (ext_inst_type
== SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100
||
3071 SPV_EXT_INST_TYPE_NONSEMANTIC_SHADER_DEBUGINFO_100
) {
3072 if (!_
.IsVoidType(result_type
)) {
3073 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
3074 << ext_inst_name() << ": "
3075 << "expected result type must be a result id of "
3079 const bool vulkanDebugInfo
=
3080 ext_inst_type
== SPV_EXT_INST_TYPE_NONSEMANTIC_SHADER_DEBUGINFO_100
;
3082 auto num_words
= inst
->words().size();
3084 // Handle any non-common NonSemanticShaderDebugInfo instructions.
3085 if (vulkanDebugInfo
) {
3086 const NonSemanticShaderDebugInfo100Instructions ext_inst_key
=
3087 NonSemanticShaderDebugInfo100Instructions(ext_inst_index
);
3088 switch (ext_inst_key
) {
3089 // The following block of instructions will be handled by the common
3091 case NonSemanticShaderDebugInfo100DebugInfoNone
:
3092 case NonSemanticShaderDebugInfo100DebugCompilationUnit
:
3093 case NonSemanticShaderDebugInfo100DebugTypeBasic
:
3094 case NonSemanticShaderDebugInfo100DebugTypePointer
:
3095 case NonSemanticShaderDebugInfo100DebugTypeQualifier
:
3096 case NonSemanticShaderDebugInfo100DebugTypeArray
:
3097 case NonSemanticShaderDebugInfo100DebugTypeVector
:
3098 case NonSemanticShaderDebugInfo100DebugTypedef
:
3099 case NonSemanticShaderDebugInfo100DebugTypeFunction
:
3100 case NonSemanticShaderDebugInfo100DebugTypeEnum
:
3101 case NonSemanticShaderDebugInfo100DebugTypeComposite
:
3102 case NonSemanticShaderDebugInfo100DebugTypeMember
:
3103 case NonSemanticShaderDebugInfo100DebugTypeInheritance
:
3104 case NonSemanticShaderDebugInfo100DebugTypePtrToMember
:
3105 case NonSemanticShaderDebugInfo100DebugTypeTemplate
:
3106 case NonSemanticShaderDebugInfo100DebugTypeTemplateParameter
:
3107 case NonSemanticShaderDebugInfo100DebugTypeTemplateTemplateParameter
:
3108 case NonSemanticShaderDebugInfo100DebugTypeTemplateParameterPack
:
3109 case NonSemanticShaderDebugInfo100DebugGlobalVariable
:
3110 case NonSemanticShaderDebugInfo100DebugFunctionDeclaration
:
3111 case NonSemanticShaderDebugInfo100DebugFunction
:
3112 case NonSemanticShaderDebugInfo100DebugLexicalBlock
:
3113 case NonSemanticShaderDebugInfo100DebugLexicalBlockDiscriminator
:
3114 case NonSemanticShaderDebugInfo100DebugScope
:
3115 case NonSemanticShaderDebugInfo100DebugNoScope
:
3116 case NonSemanticShaderDebugInfo100DebugInlinedAt
:
3117 case NonSemanticShaderDebugInfo100DebugLocalVariable
:
3118 case NonSemanticShaderDebugInfo100DebugInlinedVariable
:
3119 case NonSemanticShaderDebugInfo100DebugDeclare
:
3120 case NonSemanticShaderDebugInfo100DebugValue
:
3121 case NonSemanticShaderDebugInfo100DebugOperation
:
3122 case NonSemanticShaderDebugInfo100DebugExpression
:
3123 case NonSemanticShaderDebugInfo100DebugMacroDef
:
3124 case NonSemanticShaderDebugInfo100DebugMacroUndef
:
3125 case NonSemanticShaderDebugInfo100DebugImportedEntity
:
3126 case NonSemanticShaderDebugInfo100DebugSource
:
3128 case NonSemanticShaderDebugInfo100DebugTypeMatrix
: {
3129 CHECK_DEBUG_OPERAND("Vector Type", CommonDebugInfoDebugTypeVector
, 5);
3131 CHECK_CONST_UINT_OPERAND("Vector Count", 6);
3133 uint32_t vector_count
= inst
->word(6);
3135 if (!_
.EvalConstantValUint64(vector_count
, &const_val
)) {
3136 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
3138 << ": Vector Count must be 32-bit integer OpConstant";
3141 vector_count
= const_val
& 0xffffffff;
3142 if (!vector_count
|| vector_count
> 4) {
3143 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
3144 << ext_inst_name() << ": Vector Count must be positive "
3145 << "integer less than or equal to 4";
3149 // TODO: Add validation rules for remaining cases as well.
3150 case NonSemanticShaderDebugInfo100DebugFunctionDefinition
:
3151 case NonSemanticShaderDebugInfo100DebugSourceContinued
:
3152 case NonSemanticShaderDebugInfo100DebugLine
:
3153 case NonSemanticShaderDebugInfo100DebugNoLine
:
3154 case NonSemanticShaderDebugInfo100DebugBuildIdentifier
:
3155 case NonSemanticShaderDebugInfo100DebugStoragePath
:
3156 case NonSemanticShaderDebugInfo100DebugEntryPoint
:
3158 case NonSemanticShaderDebugInfo100InstructionsMax
:
3164 // Handle any non-common OpenCL insts, then common
3165 if (ext_inst_type
!= SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100
||
3166 OpenCLDebugInfo100Instructions(ext_inst_index
) !=
3167 OpenCLDebugInfo100DebugModuleINTEL
) {
3168 const CommonDebugInfoInstructions ext_inst_key
=
3169 CommonDebugInfoInstructions(ext_inst_index
);
3170 switch (ext_inst_key
) {
3171 case CommonDebugInfoDebugInfoNone
:
3172 case CommonDebugInfoDebugNoScope
:
3174 // The binary parser validates the opcode for DebugInfoNone,
3175 // DebugNoScope, DebugOperation. We just check the parameters to
3176 // DebugOperation are properly constants for vulkan debug info.
3177 case CommonDebugInfoDebugOperation
: {
3178 CHECK_CONST_UINT_OPERAND("Operation", 5);
3179 for (uint32_t i
= 6; i
< num_words
; ++i
) {
3180 CHECK_CONST_UINT_OPERAND("Operand", i
);
3184 case CommonDebugInfoDebugCompilationUnit
: {
3185 CHECK_CONST_UINT_OPERAND("Version", 5);
3186 CHECK_CONST_UINT_OPERAND("DWARF Version", 6);
3187 CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource
, 7);
3188 CHECK_CONST_UINT_OPERAND("Language", 8);
3191 case CommonDebugInfoDebugSource
: {
3192 CHECK_OPERAND("File", spv::Op::OpString
, 5);
3193 if (num_words
== 7) CHECK_OPERAND("Text", spv::Op::OpString
, 6);
3196 case CommonDebugInfoDebugTypeBasic
: {
3197 CHECK_OPERAND("Name", spv::Op::OpString
, 5);
3198 CHECK_OPERAND("Size", spv::Op::OpConstant
, 6);
3199 CHECK_CONST_UINT_OPERAND("Encoding", 7);
3202 case CommonDebugInfoDebugTypePointer
: {
3203 auto validate_base_type
= ValidateOperandDebugType(
3204 _
, "Base Type", inst
, 5, ext_inst_name
, false);
3205 if (validate_base_type
!= SPV_SUCCESS
) return validate_base_type
;
3206 CHECK_CONST_UINT_OPERAND("Storage Class", 6);
3207 CHECK_CONST_UINT_OPERAND("Flags", 7);
3210 case CommonDebugInfoDebugTypeQualifier
: {
3211 auto validate_base_type
= ValidateOperandDebugType(
3212 _
, "Base Type", inst
, 5, ext_inst_name
, false);
3213 if (validate_base_type
!= SPV_SUCCESS
) return validate_base_type
;
3214 CHECK_CONST_UINT_OPERAND("Type Qualifier", 6);
3217 case CommonDebugInfoDebugTypeVector
: {
3218 auto validate_base_type
=
3219 ValidateOperandBaseType(_
, inst
, 5, ext_inst_name
);
3220 if (validate_base_type
!= SPV_SUCCESS
) return validate_base_type
;
3222 CHECK_CONST_UINT_OPERAND("Component Count", 6);
3223 uint32_t component_count
= inst
->word(6);
3224 if (vulkanDebugInfo
) {
3226 if (!_
.EvalConstantValUint64(component_count
, &const_val
)) {
3227 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
3229 << ": Component Count must be 32-bit integer OpConstant";
3231 component_count
= const_val
& 0xffffffff;
3234 if (!component_count
|| component_count
> 4) {
3235 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
3236 << ext_inst_name() << ": Component Count must be positive "
3237 << "integer less than or equal to 4";
3241 case CommonDebugInfoDebugTypeArray
: {
3242 auto validate_base_type
= ValidateOperandDebugType(
3243 _
, "Base Type", inst
, 5, ext_inst_name
, false);
3244 if (validate_base_type
!= SPV_SUCCESS
) return validate_base_type
;
3245 for (uint32_t i
= 6; i
< num_words
; ++i
) {
3246 bool invalid
= false;
3247 auto* component_count
= _
.FindDef(inst
->word(i
));
3248 if (IsConstIntScalarTypeWith32Or64Bits(_
, component_count
)) {
3249 // TODO: We need a spec discussion for the runtime array for
3251 if (!vulkanDebugInfo
&& !component_count
->word(3)) {
3254 } else if (component_count
->words().size() > 6 &&
3255 (CommonDebugInfoInstructions(component_count
->word(4)) ==
3256 CommonDebugInfoDebugLocalVariable
||
3257 CommonDebugInfoInstructions(component_count
->word(4)) ==
3258 CommonDebugInfoDebugGlobalVariable
)) {
3259 auto* component_count_type
= _
.FindDef(component_count
->word(6));
3260 if (component_count_type
->words().size() > 7) {
3261 uint32_t encoding
= component_count_type
->word(7);
3262 if (CommonDebugInfoInstructions(component_count_type
->word(
3263 4)) != CommonDebugInfoDebugTypeBasic
||
3264 (vulkanDebugInfo
&& !IsUint32Constant(_
, encoding
)) ||
3265 OpenCLDebugInfo100DebugBaseTypeAttributeEncoding(
3267 ? GetUint32Constant(_
, encoding
)
3268 : encoding
) != OpenCLDebugInfo100Unsigned
) {
3271 // DebugTypeBasic for DebugLocalVariable/DebugGlobalVariable
3272 // must have Unsigned encoding and 32 or 64 as its size in
3274 Instruction
* size_in_bits
=
3275 _
.FindDef(component_count_type
->word(6));
3276 if (!_
.IsIntScalarType(size_in_bits
->type_id()) ||
3277 (size_in_bits
->word(3) != 32 &&
3278 size_in_bits
->word(3) != 64)) {
3289 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
3290 << ext_inst_name() << ": Component Count must be "
3291 << "OpConstant with a 32- or 64-bits integer scalar type "
3293 << "DebugGlobalVariable or DebugLocalVariable with a 32- "
3295 << "64-bits unsigned integer scalar type";
3300 case CommonDebugInfoDebugTypedef
: {
3301 CHECK_OPERAND("Name", spv::Op::OpString
, 5);
3302 auto validate_base_type
=
3303 ValidateOperandBaseType(_
, inst
, 6, ext_inst_name
);
3304 if (validate_base_type
!= SPV_SUCCESS
) return validate_base_type
;
3305 CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource
, 7);
3306 CHECK_CONST_UINT_OPERAND("Line", 8);
3307 CHECK_CONST_UINT_OPERAND("Column", 9);
3308 auto validate_parent
=
3309 ValidateOperandLexicalScope(_
, "Parent", inst
, 10, ext_inst_name
);
3310 if (validate_parent
!= SPV_SUCCESS
) return validate_parent
;
3313 case CommonDebugInfoDebugTypeFunction
: {
3314 CHECK_CONST_UINT_OPERAND("Flags", 5);
3315 auto* return_type
= _
.FindDef(inst
->word(6));
3316 // TODO: We need a spec discussion that we have to allow return and
3317 // parameter types of a DebugTypeFunction to have template parameter.
3318 if (return_type
->opcode() != spv::Op::OpTypeVoid
) {
3319 auto validate_return
= ValidateOperandDebugType(
3320 _
, "Return Type", inst
, 6, ext_inst_name
, true);
3321 if (validate_return
!= SPV_SUCCESS
) return validate_return
;
3323 for (uint32_t word_index
= 7; word_index
< num_words
; ++word_index
) {
3324 auto validate_param
= ValidateOperandDebugType(
3325 _
, "Parameter Types", inst
, word_index
, ext_inst_name
, true);
3326 if (validate_param
!= SPV_SUCCESS
) return validate_param
;
3330 case CommonDebugInfoDebugTypeEnum
: {
3331 CHECK_OPERAND("Name", spv::Op::OpString
, 5);
3332 if (!DoesDebugInfoOperandMatchExpectation(
3334 [](CommonDebugInfoInstructions dbg_inst
) {
3335 return dbg_inst
== CommonDebugInfoDebugInfoNone
;
3338 auto validate_underlying_type
= ValidateOperandDebugType(
3339 _
, "Underlying Types", inst
, 6, ext_inst_name
, false);
3340 if (validate_underlying_type
!= SPV_SUCCESS
)
3341 return validate_underlying_type
;
3343 CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource
, 7);
3344 CHECK_CONST_UINT_OPERAND("Line", 8);
3345 CHECK_CONST_UINT_OPERAND("Column", 9);
3346 auto validate_parent
=
3347 ValidateOperandLexicalScope(_
, "Parent", inst
, 10, ext_inst_name
);
3348 if (validate_parent
!= SPV_SUCCESS
) return validate_parent
;
3349 CHECK_OPERAND("Size", spv::Op::OpConstant
, 11);
3350 auto* size
= _
.FindDef(inst
->word(11));
3351 if (!_
.IsIntScalarType(size
->type_id()) || !size
->word(3)) {
3352 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
3353 << ext_inst_name() << ": expected operand Size is a "
3354 << "positive integer";
3356 CHECK_CONST_UINT_OPERAND("Flags", 12);
3357 for (uint32_t word_index
= 13; word_index
+ 1 < num_words
;
3359 CHECK_OPERAND("Value", spv::Op::OpConstant
, word_index
);
3360 CHECK_OPERAND("Name", spv::Op::OpString
, word_index
+ 1);
3364 case CommonDebugInfoDebugTypeComposite
: {
3365 CHECK_OPERAND("Name", spv::Op::OpString
, 5);
3366 CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource
, 7);
3367 CHECK_CONST_UINT_OPERAND("Line", 8);
3368 CHECK_CONST_UINT_OPERAND("Column", 9);
3369 auto validate_parent
=
3370 ValidateOperandLexicalScope(_
, "Parent", inst
, 10, ext_inst_name
);
3371 if (validate_parent
!= SPV_SUCCESS
) return validate_parent
;
3372 CHECK_OPERAND("Linkage Name", spv::Op::OpString
, 11);
3373 if (!DoesDebugInfoOperandMatchExpectation(
3375 [](CommonDebugInfoInstructions dbg_inst
) {
3376 return dbg_inst
== CommonDebugInfoDebugInfoNone
;
3379 CHECK_OPERAND("Size", spv::Op::OpConstant
, 12);
3381 CHECK_CONST_UINT_OPERAND("Flags", 13);
3382 for (uint32_t word_index
= 14; word_index
< num_words
; ++word_index
) {
3383 if (!DoesDebugInfoOperandMatchExpectation(
3385 [](CommonDebugInfoInstructions dbg_inst
) {
3386 return dbg_inst
== CommonDebugInfoDebugTypeMember
||
3387 dbg_inst
== CommonDebugInfoDebugFunction
||
3388 dbg_inst
== CommonDebugInfoDebugTypeInheritance
;
3390 inst
, word_index
)) {
3391 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
3392 << ext_inst_name() << ": "
3393 << "expected operand Members "
3394 << "must be DebugTypeMember, DebugFunction, or "
3395 "DebugTypeInheritance";
3400 case CommonDebugInfoDebugTypeMember
: {
3401 CHECK_OPERAND("Name", spv::Op::OpString
, 5);
3402 // TODO: We need a spec discussion that we have to allow member types
3403 // to have template parameter.
3404 auto validate_type
=
3405 ValidateOperandDebugType(_
, "Type", inst
, 6, ext_inst_name
, true);
3406 if (validate_type
!= SPV_SUCCESS
) return validate_type
;
3407 CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource
, 7);
3408 CHECK_CONST_UINT_OPERAND("Line", 8);
3409 CHECK_CONST_UINT_OPERAND("Column", 9);
3410 // NonSemantic.Shader.DebugInfo doesn't have the Parent operand
3411 if (vulkanDebugInfo
) {
3412 CHECK_OPERAND("Offset", spv::Op::OpConstant
, 10);
3413 CHECK_OPERAND("Size", spv::Op::OpConstant
, 11);
3414 CHECK_CONST_UINT_OPERAND("Flags", 12);
3415 if (num_words
== 14)
3416 CHECK_OPERAND("Value", spv::Op::OpConstant
, 13);
3418 CHECK_DEBUG_OPERAND("Parent", CommonDebugInfoDebugTypeComposite
,
3420 CHECK_OPERAND("Offset", spv::Op::OpConstant
, 11);
3421 CHECK_OPERAND("Size", spv::Op::OpConstant
, 12);
3422 CHECK_CONST_UINT_OPERAND("Flags", 13);
3423 if (num_words
== 15)
3424 CHECK_OPERAND("Value", spv::Op::OpConstant
, 14);
3428 case CommonDebugInfoDebugTypeInheritance
: {
3429 CHECK_DEBUG_OPERAND("Child", CommonDebugInfoDebugTypeComposite
, 5);
3430 auto* debug_inst
= _
.FindDef(inst
->word(5));
3431 auto composite_type
=
3432 OpenCLDebugInfo100DebugCompositeType(debug_inst
->word(6));
3433 if (composite_type
!= OpenCLDebugInfo100Class
&&
3434 composite_type
!= OpenCLDebugInfo100Structure
) {
3435 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
3436 << ext_inst_name() << ": "
3437 << "expected operand Child must be class or struct debug "
3440 CHECK_DEBUG_OPERAND("Parent", CommonDebugInfoDebugTypeComposite
, 6);
3441 debug_inst
= _
.FindDef(inst
->word(6));
3443 OpenCLDebugInfo100DebugCompositeType(debug_inst
->word(6));
3444 if (composite_type
!= OpenCLDebugInfo100Class
&&
3445 composite_type
!= OpenCLDebugInfo100Structure
) {
3446 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
3447 << ext_inst_name() << ": "
3448 << "expected operand Parent must be class or struct debug "
3451 CHECK_OPERAND("Offset", spv::Op::OpConstant
, 7);
3452 CHECK_OPERAND("Size", spv::Op::OpConstant
, 8);
3453 CHECK_CONST_UINT_OPERAND("Flags", 9);
3456 case CommonDebugInfoDebugFunction
: {
3457 CHECK_OPERAND("Name", spv::Op::OpString
, 5);
3458 auto validate_type
= ValidateOperandDebugType(_
, "Type", inst
, 6,
3459 ext_inst_name
, false);
3460 if (validate_type
!= SPV_SUCCESS
) return validate_type
;
3461 CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource
, 7);
3462 CHECK_CONST_UINT_OPERAND("Line", 8);
3463 CHECK_CONST_UINT_OPERAND("Column", 9);
3464 auto validate_parent
=
3465 ValidateOperandLexicalScope(_
, "Parent", inst
, 10, ext_inst_name
);
3466 if (validate_parent
!= SPV_SUCCESS
) return validate_parent
;
3467 CHECK_OPERAND("Linkage Name", spv::Op::OpString
, 11);
3468 CHECK_CONST_UINT_OPERAND("Flags", 12);
3469 CHECK_CONST_UINT_OPERAND("Scope Line", 13);
3470 // NonSemantic.Shader.DebugInfo.100 doesn't include a reference to the
3472 if (vulkanDebugInfo
) {
3473 if (num_words
== 15) {
3474 CHECK_DEBUG_OPERAND("Declaration",
3475 CommonDebugInfoDebugFunctionDeclaration
, 14);
3478 if (!DoesDebugInfoOperandMatchExpectation(
3480 [](CommonDebugInfoInstructions dbg_inst
) {
3481 return dbg_inst
== CommonDebugInfoDebugInfoNone
;
3484 CHECK_OPERAND("Function", spv::Op::OpFunction
, 14);
3486 if (num_words
== 16) {
3487 CHECK_DEBUG_OPERAND("Declaration",
3488 CommonDebugInfoDebugFunctionDeclaration
, 15);
3493 case CommonDebugInfoDebugFunctionDeclaration
: {
3494 CHECK_OPERAND("Name", spv::Op::OpString
, 5);
3495 auto validate_type
= ValidateOperandDebugType(_
, "Type", inst
, 6,
3496 ext_inst_name
, false);
3497 if (validate_type
!= SPV_SUCCESS
) return validate_type
;
3498 CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource
, 7);
3499 CHECK_CONST_UINT_OPERAND("Line", 8);
3500 CHECK_CONST_UINT_OPERAND("Column", 9);
3501 auto validate_parent
=
3502 ValidateOperandLexicalScope(_
, "Parent", inst
, 10, ext_inst_name
);
3503 if (validate_parent
!= SPV_SUCCESS
) return validate_parent
;
3504 CHECK_OPERAND("Linkage Name", spv::Op::OpString
, 11);
3505 CHECK_CONST_UINT_OPERAND("Flags", 12);
3508 case CommonDebugInfoDebugLexicalBlock
: {
3509 CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource
, 5);
3510 CHECK_CONST_UINT_OPERAND("Line", 6);
3511 CHECK_CONST_UINT_OPERAND("Column", 7);
3512 auto validate_parent
=
3513 ValidateOperandLexicalScope(_
, "Parent", inst
, 8, ext_inst_name
);
3514 if (validate_parent
!= SPV_SUCCESS
) return validate_parent
;
3515 if (num_words
== 10) CHECK_OPERAND("Name", spv::Op::OpString
, 9);
3518 case CommonDebugInfoDebugScope
: {
3519 auto validate_scope
=
3520 ValidateOperandLexicalScope(_
, "Scope", inst
, 5, ext_inst_name
);
3521 if (validate_scope
!= SPV_SUCCESS
) return validate_scope
;
3522 if (num_words
== 7) {
3523 CHECK_DEBUG_OPERAND("Inlined At", CommonDebugInfoDebugInlinedAt
, 6);
3527 case CommonDebugInfoDebugLocalVariable
: {
3528 CHECK_OPERAND("Name", spv::Op::OpString
, 5);
3529 // TODO: We need a spec discussion that we have to allow local
3530 // variable types to have template parameter.
3531 auto validate_type
=
3532 ValidateOperandDebugType(_
, "Type", inst
, 6, ext_inst_name
, true);
3533 if (validate_type
!= SPV_SUCCESS
) return validate_type
;
3534 CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource
, 7);
3535 CHECK_CONST_UINT_OPERAND("Line", 8);
3536 CHECK_CONST_UINT_OPERAND("Column", 9);
3537 auto validate_parent
=
3538 ValidateOperandLexicalScope(_
, "Parent", inst
, 10, ext_inst_name
);
3539 if (validate_parent
!= SPV_SUCCESS
) return validate_parent
;
3540 CHECK_CONST_UINT_OPERAND("Flags", 11);
3541 if (num_words
== 13) {
3542 CHECK_CONST_UINT_OPERAND("ArgNumber", 12);
3546 case CommonDebugInfoDebugDeclare
: {
3547 CHECK_DEBUG_OPERAND("Local Variable",
3548 CommonDebugInfoDebugLocalVariable
, 5);
3549 auto* operand
= _
.FindDef(inst
->word(6));
3550 if (operand
->opcode() != spv::Op::OpVariable
&&
3551 operand
->opcode() != spv::Op::OpFunctionParameter
) {
3552 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
3553 << ext_inst_name() << ": "
3554 << "expected operand Variable must be a result id of "
3555 "OpVariable or OpFunctionParameter";
3558 CHECK_DEBUG_OPERAND("Expression", CommonDebugInfoDebugExpression
, 7);
3560 if (vulkanDebugInfo
) {
3561 for (uint32_t word_index
= 8; word_index
< num_words
;
3563 auto index_inst
= _
.FindDef(inst
->word(word_index
));
3564 auto type_id
= index_inst
!= nullptr ? index_inst
->type_id() : 0;
3565 if (type_id
== 0 || !IsIntScalar(_
, type_id
, false, false))
3566 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
3567 << ext_inst_name() << ": "
3568 << "expected index must be scalar integer";
3573 case CommonDebugInfoDebugExpression
: {
3574 for (uint32_t word_index
= 5; word_index
< num_words
; ++word_index
) {
3575 CHECK_DEBUG_OPERAND("Operation", CommonDebugInfoDebugOperation
,
3580 case CommonDebugInfoDebugTypeTemplate
: {
3581 if (!DoesDebugInfoOperandMatchExpectation(
3583 [](CommonDebugInfoInstructions dbg_inst
) {
3584 return dbg_inst
== CommonDebugInfoDebugTypeComposite
||
3585 dbg_inst
== CommonDebugInfoDebugFunction
;
3588 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
3589 << ext_inst_name() << ": "
3590 << "expected operand Target must be DebugTypeComposite "
3591 << "or DebugFunction";
3593 for (uint32_t word_index
= 6; word_index
< num_words
; ++word_index
) {
3594 if (!DoesDebugInfoOperandMatchExpectation(
3596 [](CommonDebugInfoInstructions dbg_inst
) {
3598 CommonDebugInfoDebugTypeTemplateParameter
||
3600 CommonDebugInfoDebugTypeTemplateTemplateParameter
;
3602 inst
, word_index
)) {
3603 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
3604 << ext_inst_name() << ": "
3605 << "expected operand Parameters must be "
3606 << "DebugTypeTemplateParameter or "
3607 << "DebugTypeTemplateTemplateParameter";
3612 case CommonDebugInfoDebugTypeTemplateParameter
: {
3613 CHECK_OPERAND("Name", spv::Op::OpString
, 5);
3614 auto validate_actual_type
= ValidateOperandDebugType(
3615 _
, "Actual Type", inst
, 6, ext_inst_name
, false);
3616 if (validate_actual_type
!= SPV_SUCCESS
) return validate_actual_type
;
3617 if (!DoesDebugInfoOperandMatchExpectation(
3619 [](CommonDebugInfoInstructions dbg_inst
) {
3620 return dbg_inst
== CommonDebugInfoDebugInfoNone
;
3623 CHECK_OPERAND("Value", spv::Op::OpConstant
, 7);
3625 CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource
, 8);
3626 CHECK_CONST_UINT_OPERAND("Line", 9);
3627 CHECK_CONST_UINT_OPERAND("Column", 10);
3630 case CommonDebugInfoDebugGlobalVariable
: {
3631 CHECK_OPERAND("Name", spv::Op::OpString
, 5);
3632 auto validate_type
= ValidateOperandDebugType(_
, "Type", inst
, 6,
3633 ext_inst_name
, false);
3634 if (validate_type
!= SPV_SUCCESS
) return validate_type
;
3635 CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource
, 7);
3636 CHECK_CONST_UINT_OPERAND("Line", 8);
3637 CHECK_CONST_UINT_OPERAND("Column", 9);
3638 auto validate_scope
=
3639 ValidateOperandLexicalScope(_
, "Scope", inst
, 10, ext_inst_name
);
3640 if (validate_scope
!= SPV_SUCCESS
) return validate_scope
;
3641 CHECK_OPERAND("Linkage Name", spv::Op::OpString
, 11);
3642 if (!DoesDebugInfoOperandMatchExpectation(
3644 [](CommonDebugInfoInstructions dbg_inst
) {
3645 return dbg_inst
== CommonDebugInfoDebugInfoNone
;
3648 auto* operand
= _
.FindDef(inst
->word(12));
3649 if (operand
->opcode() != spv::Op::OpVariable
&&
3650 operand
->opcode() != spv::Op::OpConstant
) {
3651 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
3652 << ext_inst_name() << ": "
3653 << "expected operand Variable must be a result id of "
3654 "OpVariable or OpConstant or DebugInfoNone";
3657 if (num_words
== 15) {
3658 CHECK_DEBUG_OPERAND("Static Member Declaration",
3659 CommonDebugInfoDebugTypeMember
, 14);
3663 case CommonDebugInfoDebugInlinedAt
: {
3664 CHECK_CONST_UINT_OPERAND("Line", 5);
3665 auto validate_scope
=
3666 ValidateOperandLexicalScope(_
, "Scope", inst
, 6, ext_inst_name
);
3667 if (validate_scope
!= SPV_SUCCESS
) return validate_scope
;
3668 if (num_words
== 8) {
3669 CHECK_DEBUG_OPERAND("Inlined", CommonDebugInfoDebugInlinedAt
, 7);
3673 case CommonDebugInfoDebugValue
: {
3674 CHECK_DEBUG_OPERAND("Local Variable",
3675 CommonDebugInfoDebugLocalVariable
, 5);
3676 CHECK_DEBUG_OPERAND("Expression", CommonDebugInfoDebugExpression
, 7);
3678 for (uint32_t word_index
= 8; word_index
< num_words
; ++word_index
) {
3679 // TODO: The following code simply checks if it is a const int
3680 // scalar or a DebugLocalVariable or DebugGlobalVariable, but we
3681 // have to check it using the same validation for Indexes of
3683 if (!IsConstWithIntScalarType(_
, inst
, word_index
) &&
3684 !IsDebugVariableWithIntScalarType(_
, inst
, word_index
)) {
3685 return _
.diag(SPV_ERROR_INVALID_DATA
, inst
)
3686 << ext_inst_name() << ": expected operand Indexes is "
3687 << "OpConstant, DebugGlobalVariable, or "
3688 << "type is OpConstant with an integer scalar type";
3694 // TODO: Add validation rules for remaining cases as well.
3695 case CommonDebugInfoDebugTypePtrToMember
:
3696 case CommonDebugInfoDebugTypeTemplateTemplateParameter
:
3697 case CommonDebugInfoDebugTypeTemplateParameterPack
:
3698 case CommonDebugInfoDebugLexicalBlockDiscriminator
:
3699 case CommonDebugInfoDebugInlinedVariable
:
3700 case CommonDebugInfoDebugMacroDef
:
3701 case CommonDebugInfoDebugMacroUndef
:
3702 case CommonDebugInfoDebugImportedEntity
:
3704 case CommonDebugInfoInstructionsMax
:
3709 } else if (ext_inst_type
== SPV_EXT_INST_TYPE_NONSEMANTIC_CLSPVREFLECTION
) {
3710 auto import_inst
= _
.FindDef(inst
->GetOperandAs
<uint32_t>(2));
3711 const std::string name
= import_inst
->GetOperandAs
<std::string
>(1);
3712 const std::string reflection
= "NonSemantic.ClspvReflection.";
3714 auto version_string
= name
.substr(reflection
.size());
3715 if (version_string
.empty()) {
3716 return _
.diag(SPV_ERROR_INVALID_DATA
, import_inst
)
3717 << "Missing NonSemantic.ClspvReflection import version";
3719 uint32_t version
= static_cast<uint32_t>(
3720 std::strtoul(version_string
.c_str(), &end_ptr
, 10));
3721 if (end_ptr
&& *end_ptr
!= '\0') {
3722 return _
.diag(SPV_ERROR_INVALID_DATA
, import_inst
)
3723 << "NonSemantic.ClspvReflection import does not encode the "
3724 "version correctly";
3726 if (version
== 0 || version
> NonSemanticClspvReflectionRevision
) {
3727 return _
.diag(SPV_ERROR_INVALID_DATA
, import_inst
)
3728 << "Unknown NonSemantic.ClspvReflection import version";
3731 return ValidateClspvReflectionInstruction(_
, inst
, version
);
3737 spv_result_t
ExtensionPass(ValidationState_t
& _
, const Instruction
* inst
) {
3738 const spv::Op opcode
= inst
->opcode();
3739 if (opcode
== spv::Op::OpExtension
) return ValidateExtension(_
, inst
);
3740 if (opcode
== spv::Op::OpExtInstImport
) return ValidateExtInstImport(_
, inst
);
3741 if (spvIsExtendedInstruction(opcode
)) return ValidateExtInst(_
, inst
);
3747 } // namespace spvtools