• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2018 Google Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 // Validates correctness of extension SPIR-V instructions.
16 #include <cstdlib>
17 #include <sstream>
18 #include <string>
19 #include <vector>
20 
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"
33 
34 namespace spvtools {
35 namespace val {
36 namespace {
37 
ReflectionInstructionName(ValidationState_t & _,const Instruction * inst)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 ||
43       !desc) {
44     return std::string("Unknown ExtInst");
45   }
46   std::ostringstream ss;
47   ss << desc->name;
48 
49   return ss.str();
50 }
51 
GetSizeTBitWidth(const ValidationState_t & _)52 uint32_t GetSizeTBitWidth(const ValidationState_t& _) {
53   if (_.addressing_model() == spv::AddressingModel::Physical32) return 32;
54 
55   if (_.addressing_model() == spv::AddressingModel::Physical64) return 64;
56 
57   return 0;
58 }
59 
IsIntScalar(ValidationState_t & _,uint32_t id,bool must_len32,bool must_unsigned)60 bool IsIntScalar(ValidationState_t& _, uint32_t id, bool must_len32,
61                  bool must_unsigned) {
62   auto type = _.FindDef(id);
63   if (!type || type->opcode() != spv::Op::OpTypeInt) {
64     return false;
65   }
66 
67   if (must_len32 && type->GetOperandAs<uint32_t>(1) != 32) {
68     return false;
69   }
70 
71   return !must_unsigned || type->GetOperandAs<uint32_t>(2) == 0;
72 }
73 
IsUint32Constant(ValidationState_t & _,uint32_t id)74 bool IsUint32Constant(ValidationState_t& _, uint32_t id) {
75   auto inst = _.FindDef(id);
76   if (!inst || inst->opcode() != spv::Op::OpConstant) {
77     return false;
78   }
79 
80   return IsIntScalar(_, inst->type_id(), true, true);
81 }
82 
GetUint32Constant(ValidationState_t & _,uint32_t id)83 uint32_t GetUint32Constant(ValidationState_t& _, uint32_t id) {
84   auto inst = _.FindDef(id);
85   return inst->word(3);
86 }
87 
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|.
ValidateOperandForDebugInfo(ValidationState_t & _,const std::string & operand_name,spv::Op expected_opcode,const Instruction * inst,uint32_t word_index,const std::function<std::string ()> & ext_inst_name)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 ||
98         !desc) {
99       return _.diag(SPV_ERROR_INVALID_DATA, inst)
100              << ext_inst_name() << ": "
101              << "expected operand " << operand_name << " is invalid";
102     }
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;
107   }
108   return SPV_SUCCESS;
109 }
110 
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.
ValidateUint32ConstantOperandForDebugInfo(ValidationState_t & _,const std::string & operand_name,const Instruction * inst,uint32_t word_index,const std::function<std::string ()> & ext_inst_name)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";
123   }
124   return SPV_SUCCESS;
125 }
126 
127 #define CHECK_OPERAND(NAME, opcode, index)                                  \
128   do {                                                                      \
129     auto result = ValidateOperandForDebugInfo(_, NAME, opcode, inst, index, \
130                                               ext_inst_name);               \
131     if (result != SPV_SUCCESS) return result;                               \
132   } while (0)
133 
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;                \
139   }
140 
141 // True if the operand of a debug info instruction |inst| at |word_index|
142 // satisfies |expectation| that is given as a function. Otherwise,
143 // returns false.
DoesDebugInfoOperandMatchExpectation(const ValidationState_t & _,const std::function<bool (CommonDebugInfoInstructions)> & expectation,const Instruction * inst,uint32_t word_index)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 (debug_inst->opcode() != spv::Op::OpExtInst ||
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)))) {
155     return false;
156   }
157   return true;
158 }
159 
160 // Overload for NonSemanticShaderDebugInfo100Instructions.
DoesDebugInfoOperandMatchExpectation(const ValidationState_t & _,const std::function<bool (NonSemanticShaderDebugInfo100Instructions)> & expectation,const Instruction * inst,uint32_t word_index)161 bool DoesDebugInfoOperandMatchExpectation(
162     const ValidationState_t& _,
163     const std::function<bool(NonSemanticShaderDebugInfo100Instructions)>&
164         expectation,
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 (debug_inst->opcode() != spv::Op::OpExtInst ||
169       (debug_inst->ext_inst_type() !=
170        SPV_EXT_INST_TYPE_NONSEMANTIC_SHADER_DEBUGINFO_100) ||
171       !expectation(
172           NonSemanticShaderDebugInfo100Instructions(debug_inst->word(4)))) {
173     return false;
174   }
175   return true;
176 }
177 
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|.
ValidateDebugInfoOperand(ValidationState_t & _,const std::string & debug_inst_name,CommonDebugInfoInstructions expected_debug_inst,const Instruction * inst,uint32_t word_index,const std::function<std::string ()> & ext_inst_name)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;
188       };
189   if (DoesDebugInfoOperandMatchExpectation(_, expectation, inst, word_index))
190     return SPV_SUCCESS;
191 
192   spv_ext_inst_desc desc = nullptr;
193   if (_.grammar().lookupExtInst(inst->ext_inst_type(), expected_debug_inst,
194                                 &desc) != SPV_SUCCESS ||
195       !desc) {
196     return _.diag(SPV_ERROR_INVALID_DATA, inst)
197            << ext_inst_name() << ": "
198            << "expected operand " << debug_inst_name << " is invalid";
199   }
200   return _.diag(SPV_ERROR_INVALID_DATA, inst)
201          << ext_inst_name() << ": "
202          << "expected operand " << debug_inst_name << " must be a result id of "
203          << desc->name;
204 }
205 
206 #define CHECK_DEBUG_OPERAND(NAME, debug_opcode, index)                         \
207   do {                                                                         \
208     auto result = ValidateDebugInfoOperand(_, NAME, debug_opcode, inst, index, \
209                                            ext_inst_name);                     \
210     if (result != SPV_SUCCESS) return result;                                  \
211   } while (0)
212 
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.
ValidateOperandBaseType(ValidationState_t & _,const Instruction * inst,uint32_t word_index,const std::function<std::string ()> & ext_inst_name)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);
220 }
221 
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.
ValidateOperandLexicalScope(ValidationState_t & _,const std::string & debug_inst_name,const Instruction * inst,uint32_t word_index,const std::function<std::string ()> & ext_inst_name)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;
236       };
237   if (DoesDebugInfoOperandMatchExpectation(_, expectation, inst, word_index))
238     return SPV_SUCCESS;
239 
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";
244 }
245 
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.
ValidateOperandDebugType(ValidationState_t & _,const std::string & debug_inst_name,const Instruction * inst,uint32_t word_index,const std::function<std::string ()> & ext_inst_name,bool allow_template_param)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;
260         };
261     if (DoesDebugInfoOperandMatchExpectation(_, expectation, inst, word_index))
262       return SPV_SUCCESS;
263   }
264 
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)) {
271           return true;
272         }
273         return CommonDebugInfoDebugTypeBasic <= dbg_inst &&
274                dbg_inst <= CommonDebugInfoDebugTypeTemplate;
275       };
276   if (DoesDebugInfoOperandMatchExpectation(_, expectation, inst, word_index))
277     return SPV_SUCCESS;
278 
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";
283 }
284 
ValidateClspvReflectionKernel(ValidationState_t & _,const Instruction * inst,uint32_t version)285 spv_result_t ValidateClspvReflectionKernel(ValidationState_t& _,
286                                            const Instruction* inst,
287                                            uint32_t version) {
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";
294   }
295 
296   bool found_kernel = false;
297   for (auto entry_point : _.entry_points()) {
298     if (entry_point == kernel_id) {
299       found_kernel = true;
300       break;
301     }
302   }
303   if (!found_kernel) {
304     return _.diag(SPV_ERROR_INVALID_ID, inst)
305            << inst_name << " does not reference an entry-point";
306   }
307 
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";
312   }
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";
317     }
318   }
319 
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";
323   }
324 
325   const std::string name_str = name->GetOperandAs<std::string>(1);
326   bool found = false;
327   for (auto& desc : _.entry_point_descriptions(kernel_id)) {
328     if (name_str == desc.name) {
329       found = true;
330       break;
331     }
332   }
333   if (!found) {
334     return _.diag(SPV_ERROR_INVALID_ID, inst)
335            << "Name must match an entry-point for Kernel";
336   }
337 
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";
343   }
344 
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";
350     }
351   }
352 
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";
358     }
359   }
360 
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";
366     }
367   }
368 
369   return SPV_SUCCESS;
370 }
371 
ValidateClspvReflectionArgumentInfo(ValidationState_t & _,const Instruction * inst)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";
377   }
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";
382     }
383   }
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 "
388                 "OpConstant";
389     }
390   }
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 "
395                 "OpConstant";
396     }
397   }
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 "
402                 "OpConstant";
403     }
404   }
405 
406   return SPV_SUCCESS;
407 }
408 
ValidateKernelDecl(ValidationState_t & _,const Instruction * inst)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 || decl->opcode() != spv::Op::OpExtInst) {
413     return _.diag(SPV_ERROR_INVALID_ID, inst)
414            << "Kernel must be a Kernel extended instruction";
415   }
416 
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";
420   }
421 
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";
427   }
428 
429   return SPV_SUCCESS;
430 }
431 
ValidateArgInfo(ValidationState_t & _,const Instruction * inst,uint32_t info_index)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 || info->opcode() != spv::Op::OpExtInst) {
436     return _.diag(SPV_ERROR_INVALID_ID, inst)
437            << "ArgInfo must be an ArgumentInfo extended instruction";
438   }
439 
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";
443   }
444 
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";
449   }
450 
451   return SPV_SUCCESS;
452 }
453 
ValidateClspvReflectionArgumentBuffer(ValidationState_t & _,const Instruction * inst)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)) {
458     return error;
459   }
460 
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";
464   }
465 
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";
469   }
470 
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";
474   }
475 
476   if (num_operands == 9) {
477     if (auto error = ValidateArgInfo(_, inst, 8)) {
478       return error;
479     }
480   }
481 
482   return SPV_SUCCESS;
483 }
484 
ValidateClspvReflectionArgumentOffsetBuffer(ValidationState_t & _,const Instruction * inst)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)) {
489     return error;
490   }
491 
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";
495   }
496 
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";
500   }
501 
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";
505   }
506 
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";
510   }
511 
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";
515   }
516 
517   if (num_operands == 11) {
518     if (auto error = ValidateArgInfo(_, inst, 10)) {
519       return error;
520     }
521   }
522 
523   return SPV_SUCCESS;
524 }
525 
ValidateClspvReflectionArgumentPushConstant(ValidationState_t & _,const Instruction * inst)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)) {
530     return error;
531   }
532 
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";
536   }
537 
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";
541   }
542 
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";
546   }
547 
548   if (num_operands == 9) {
549     if (auto error = ValidateArgInfo(_, inst, 8)) {
550       return error;
551     }
552   }
553 
554   return SPV_SUCCESS;
555 }
556 
ValidateClspvReflectionArgumentWorkgroup(ValidationState_t & _,const Instruction * inst)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)) {
561     return error;
562   }
563 
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";
567   }
568 
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";
572   }
573 
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";
577   }
578 
579   if (num_operands == 9) {
580     if (auto error = ValidateArgInfo(_, inst, 8)) {
581       return error;
582     }
583   }
584 
585   return SPV_SUCCESS;
586 }
587 
ValidateClspvReflectionSpecConstantTriple(ValidationState_t & _,const Instruction * inst)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";
593   }
594 
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";
598   }
599 
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";
603   }
604 
605   return SPV_SUCCESS;
606 }
607 
ValidateClspvReflectionSpecConstantWorkDim(ValidationState_t & _,const Instruction * inst)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";
613   }
614 
615   return SPV_SUCCESS;
616 }
617 
ValidateClspvReflectionPushConstant(ValidationState_t & _,const Instruction * inst)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";
623   }
624 
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";
628   }
629 
630   return SPV_SUCCESS;
631 }
632 
ValidateClspvReflectionInitializedData(ValidationState_t & _,const Instruction * inst)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";
638   }
639 
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";
643   }
644 
645   if (_.GetIdOpcode(inst->GetOperandAs<uint32_t>(6)) != spv::Op::OpString) {
646     return _.diag(SPV_ERROR_INVALID_ID, inst) << "Data must be an OpString";
647   }
648 
649   return SPV_SUCCESS;
650 }
651 
ValidateClspvReflectionSampler(ValidationState_t & _,const Instruction * inst)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";
657   }
658 
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";
662   }
663 
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";
667   }
668 
669   return SPV_SUCCESS;
670 }
671 
ValidateClspvReflectionPropertyRequiredWorkgroupSize(ValidationState_t & _,const Instruction * inst)672 spv_result_t ValidateClspvReflectionPropertyRequiredWorkgroupSize(
673     ValidationState_t& _, const Instruction* inst) {
674   if (auto error = ValidateKernelDecl(_, inst)) {
675     return error;
676   }
677 
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";
681   }
682 
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";
686   }
687 
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";
691   }
692 
693   return SPV_SUCCESS;
694 }
695 
ValidateClspvReflectionSubgroupMaxSize(ValidationState_t & _,const Instruction * inst)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";
702   }
703 
704   return SPV_SUCCESS;
705 }
706 
ValidateClspvReflectionPointerRelocation(ValidationState_t & _,const Instruction * inst)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";
712   }
713 
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";
717   }
718 
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";
722   }
723 
724   return SPV_SUCCESS;
725 }
726 
ValidateClspvReflectionImageMetadataPushConstant(ValidationState_t & _,const Instruction * inst)727 spv_result_t ValidateClspvReflectionImageMetadataPushConstant(
728     ValidationState_t& _, const Instruction* inst) {
729   if (auto error = ValidateKernelDecl(_, inst)) {
730     return error;
731   }
732 
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";
736   }
737 
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";
741   }
742 
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";
746   }
747 
748   return SPV_SUCCESS;
749 }
750 
ValidateClspvReflectionImageMetadataUniform(ValidationState_t & _,const Instruction * inst)751 spv_result_t ValidateClspvReflectionImageMetadataUniform(
752     ValidationState_t& _, const Instruction* inst) {
753   if (auto error = ValidateKernelDecl(_, inst)) {
754     return error;
755   }
756 
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";
760   }
761 
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";
765   }
766 
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";
770   }
771 
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";
775   }
776 
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";
780   }
781 
782   return SPV_SUCCESS;
783 }
784 
ValidateClspvReflectionPushConstantData(ValidationState_t & _,const Instruction * inst)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";
790   }
791 
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";
795   }
796 
797   if (_.GetIdOpcode(inst->GetOperandAs<uint32_t>(6)) != spv::Op::OpString) {
798     return _.diag(SPV_ERROR_INVALID_ID, inst) << "Data must be an OpString";
799   }
800 
801   return SPV_SUCCESS;
802 }
803 
ValidateClspvReflectionPrintfInfo(ValidationState_t & _,const Instruction * inst)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";
809   }
810 
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";
814   }
815 
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";
820     }
821   }
822 
823   return SPV_SUCCESS;
824 }
825 
ValidateClspvReflectionPrintfStorageBuffer(ValidationState_t & _,const Instruction * inst)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";
831   }
832 
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";
836   }
837 
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";
841   }
842 
843   return SPV_SUCCESS;
844 }
845 
ValidateClspvReflectionPrintfPushConstant(ValidationState_t & _,const Instruction * inst)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";
851   }
852 
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";
856   }
857 
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";
861   }
862 
863   return SPV_SUCCESS;
864 }
865 
ValidateClspvReflectionInstruction(ValidationState_t & _,const Instruction * inst,uint32_t version)866 spv_result_t ValidateClspvReflectionInstruction(ValidationState_t& _,
867                                                 const Instruction* inst,
868                                                 uint32_t version) {
869   if (!_.IsVoidType(inst->type_id())) {
870     return _.diag(SPV_ERROR_INVALID_ID, inst)
871            << "Return Type must be OpTypeVoid";
872   }
873 
874   uint32_t required_version = 0;
875   const auto ext_inst =
876       inst->GetOperandAs<NonSemanticClspvReflectionInstructions>(3);
877   switch (ext_inst) {
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;
903       break;
904     case NonSemanticClspvReflectionSpecConstantSubgroupMaxSize:
905       required_version = 2;
906       break;
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;
916       break;
917     case NonSemanticClspvReflectionArgumentStorageTexelBuffer:
918     case NonSemanticClspvReflectionArgumentUniformTexelBuffer:
919       required_version = 4;
920       break;
921     case NonSemanticClspvReflectionConstantDataPointerPushConstant:
922     case NonSemanticClspvReflectionProgramScopeVariablePointerPushConstant:
923     case NonSemanticClspvReflectionPrintfInfo:
924     case NonSemanticClspvReflectionPrintfBufferStorageBuffer:
925     case NonSemanticClspvReflectionPrintfBufferPointerPushConstant:
926       required_version = 5;
927       break;
928     default:
929       break;
930   }
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;
935   }
936 
937   switch (ext_inst) {
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);
998     default:
999       break;
1000   }
1001 
1002   return SPV_SUCCESS;
1003 }
1004 
IsConstIntScalarTypeWith32Or64Bits(ValidationState_t & _,Instruction * instr)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;
1011 }
1012 
IsConstWithIntScalarType(ValidationState_t & _,const Instruction * inst,uint32_t word_index)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())) {
1018     return true;
1019   }
1020   return false;
1021 }
1022 
IsDebugVariableWithIntScalarType(ValidationState_t & _,const Instruction * inst,uint32_t word_index)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) {
1044           return true;
1045         }
1046       }
1047     }
1048   }
1049   return false;
1050 }
1051 
1052 }  // anonymous namespace
1053 
ValidateExtension(ValidationState_t & _,const Instruction * inst)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()));
1057     if (extension ==
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.";
1063     }
1064   }
1065 
1066   return SPV_SUCCESS;
1067 }
1068 
ValidateExtInstImport(ValidationState_t & _,const Instruction * inst)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.";
1079     }
1080   }
1081 
1082   return SPV_SUCCESS;
1083 }
1084 
ValidateExtInst(ValidationState_t & _,const Instruction * inst)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());
1088 
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());
1093 
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) !=
1097             SPV_SUCCESS ||
1098         !desc) {
1099       return std::string("Unknown ExtInst");
1100     }
1101 
1102     auto* import_inst = _.FindDef(ext_inst_set);
1103     assert(import_inst);
1104 
1105     std::ostringstream ss;
1106     ss << import_inst->GetOperandAs<std::string>(1);
1107     ss << " ";
1108     ss << desc->name;
1109 
1110     return ss.str();
1111   };
1112 
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:
1132       case GLSLstd450Fma:
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";
1143         }
1144 
1145         for (uint32_t operand_index = 4; operand_index < num_operands;
1146              ++operand_index) {
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 "
1152                       "Type";
1153           }
1154         }
1155         break;
1156       }
1157 
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";
1173         }
1174 
1175         const uint32_t result_type_bit_width = _.GetBitWidth(result_type);
1176         const uint32_t result_type_dimension = _.GetDimension(result_type);
1177 
1178         for (uint32_t operand_index = 4; operand_index < num_operands;
1179              ++operand_index) {
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";
1185           }
1186 
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 "
1191                    << "Result Type";
1192           }
1193 
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 "
1198                    << "Result Type";
1199           }
1200 
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 "
1207                      << "components";
1208             }
1209           }
1210         }
1211         break;
1212       }
1213 
1214       case GLSLstd450Radians:
1215       case GLSLstd450Degrees:
1216       case GLSLstd450Sin:
1217       case GLSLstd450Cos:
1218       case GLSLstd450Tan:
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:
1228       case GLSLstd450Exp:
1229       case GLSLstd450Exp2:
1230       case GLSLstd450Log:
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";
1239         }
1240 
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";
1247         }
1248 
1249         for (uint32_t operand_index = 4; operand_index < num_operands;
1250              ++operand_index) {
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 "
1256                       "Type";
1257           }
1258         }
1259         break;
1260       }
1261 
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,
1269                                  &component_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";
1274         }
1275 
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 "
1280                  << "Result Type";
1281         }
1282         break;
1283       }
1284 
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,
1291                                  &component_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";
1296         }
1297 
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";
1303         }
1304         break;
1305       }
1306 
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";
1312         }
1313 
1314         const uint32_t x_type = _.GetOperandTypeId(inst, 4);
1315         const uint32_t i_type = _.GetOperandTypeId(inst, 5);
1316 
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";
1321         }
1322 
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";
1329         }
1330 
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";
1335         }
1336 
1337         break;
1338       }
1339 
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";
1350         }
1351 
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";
1358         }
1359         break;
1360       }
1361 
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";
1367         }
1368 
1369         const uint32_t x_type = _.GetOperandTypeId(inst, 4);
1370         const uint32_t exp_type = _.GetOperandTypeId(inst, 5);
1371 
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";
1376         }
1377 
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";
1385         }
1386 
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 "
1398                          : "32-bit ")
1399                  << "int scalar or vector type";
1400         }
1401 
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";
1407         }
1408 
1409         break;
1410       }
1411 
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";
1417         }
1418 
1419         const uint32_t x_type = _.GetOperandTypeId(inst, 4);
1420         const uint32_t exp_type = _.GetOperandTypeId(inst, 5);
1421 
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";
1426         }
1427 
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";
1433         }
1434 
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";
1440         }
1441 
1442         break;
1443       }
1444 
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 "
1464                          : "32-bit ")
1465                  << "int scalar or vector with the same number of "
1466                  << "components as the first member";
1467         }
1468 
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";
1475         }
1476         break;
1477       }
1478 
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";
1486         }
1487 
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";
1494         }
1495         break;
1496       }
1497 
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";
1506         }
1507 
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";
1514         }
1515         break;
1516       }
1517 
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";
1524         }
1525 
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";
1532         }
1533         break;
1534       }
1535 
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 "
1544                     "4";
1545         }
1546 
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";
1552         }
1553         break;
1554       }
1555 
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 "
1565                     "2";
1566         }
1567 
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";
1573         }
1574         break;
1575       }
1576 
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 "
1584                     "2";
1585         }
1586 
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";
1592         }
1593         break;
1594       }
1595 
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";
1601         }
1602 
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";
1608         }
1609 
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 "
1614                     "Type";
1615         }
1616         break;
1617       }
1618 
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";
1624         }
1625 
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";
1631         }
1632 
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 "
1637                  << "Result Type";
1638         }
1639 
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";
1645         }
1646 
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 "
1651                  << "Result Type";
1652         }
1653 
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 "
1658                  << "components";
1659         }
1660         break;
1661       }
1662 
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";
1668         }
1669 
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";
1674         }
1675 
1676         const uint32_t x_type = _.GetOperandTypeId(inst, 4);
1677         const uint32_t y_type = _.GetOperandTypeId(inst, 5);
1678 
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";
1683         }
1684 
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";
1689         }
1690         break;
1691       }
1692 
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";
1698         }
1699 
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);
1703 
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";
1708         }
1709 
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";
1714         }
1715 
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";
1720         }
1721         break;
1722       }
1723 
1724       case GLSLstd450InterpolateAtCentroid:
1725       case GLSLstd450InterpolateAtSample:
1726       case GLSLstd450InterpolateAtOffset: {
1727         if (!_.HasCapability(spv::Capability::InterpolationFunction)) {
1728           return _.diag(SPV_ERROR_INVALID_CAPABILITY, inst)
1729                  << ext_inst_name()
1730                  << " requires capability InterpolationFunction";
1731         }
1732 
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";
1739         }
1740 
1741         // If HLSL legalization and first operand is an OpLoad, use load
1742         // pointer as the interpolant lvalue. Else use interpolate first
1743         // operand.
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);
1750 
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";
1758         }
1759 
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";
1764         }
1765 
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";
1770         }
1771 
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";
1779           }
1780         }
1781 
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";
1790           }
1791         }
1792 
1793         _.function(inst->function()->id())
1794             ->RegisterExecutionModelLimitation(
1795                 spv::ExecutionModel::Fragment,
1796                 ext_inst_name() +
1797                     std::string(" requires Fragment execution model"));
1798         break;
1799       }
1800 
1801       case GLSLstd450IMix: {
1802         return _.diag(SPV_ERROR_INVALID_DATA, inst)
1803                << "Extended instruction GLSLstd450IMix is not supported";
1804       }
1805 
1806       case GLSLstd450Bad: {
1807         return _.diag(SPV_ERROR_INVALID_DATA, inst)
1808                << "Encountered extended instruction GLSLstd450Bad";
1809       }
1810 
1811       case GLSLstd450Count: {
1812         assert(0);
1813         break;
1814       }
1815     }
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";
1917         }
1918 
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";
1925         }
1926 
1927         for (uint32_t operand_index = 4; operand_index < num_operands;
1928              ++operand_index) {
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 "
1934                       "Type";
1935           }
1936         }
1937         break;
1938       }
1939 
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";
1947         }
1948 
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";
1955         }
1956 
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";
1962         }
1963 
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";
1971         }
1972 
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";
1981         }
1982 
1983         if (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 "
1987                     "Type";
1988         }
1989         break;
1990       }
1991 
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";
1999         }
2000 
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";
2007         }
2008 
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";
2015         }
2016 
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";
2023           }
2024         }
2025 
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";
2033         }
2034 
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";
2043         }
2044 
2045         if (!_.IsIntScalarOrVectorType(p_data_type) ||
2046             _.GetBitWidth(p_data_type) != 32) {
2047           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2048                  << ext_inst_name() << ": "
2049                  << "expected data type of the pointer to be a 32-bit int "
2050                     "scalar or vector type";
2051         }
2052 
2053         if (_.GetDimension(p_data_type) != num_components) {
2054           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2055                  << ext_inst_name() << ": "
2056                  << "expected data type of the pointer to have the same number "
2057                     "of components as Result Type";
2058         }
2059         break;
2060       }
2061 
2062       case OpenCLLIB::Ilogb: {
2063         if (!_.IsIntScalarOrVectorType(result_type) ||
2064             _.GetBitWidth(result_type) != 32) {
2065           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2066                  << ext_inst_name() << ": "
2067                  << "expected Result Type to be a 32-bit int scalar or vector "
2068                     "type";
2069         }
2070 
2071         const uint32_t num_components = _.GetDimension(result_type);
2072         if (num_components > 4 && num_components != 8 && num_components != 16) {
2073           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2074                  << ext_inst_name() << ": "
2075                  << "expected Result Type to be a scalar or a vector with 2, "
2076                     "3, 4, 8 or 16 components";
2077         }
2078 
2079         const uint32_t x_type = _.GetOperandTypeId(inst, 4);
2080         if (!_.IsFloatScalarOrVectorType(x_type)) {
2081           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2082                  << ext_inst_name() << ": "
2083                  << "expected operand X to be a float scalar or vector";
2084         }
2085 
2086         if (_.GetDimension(x_type) != num_components) {
2087           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2088                  << ext_inst_name() << ": "
2089                  << "expected operand X to have the same number of components "
2090                     "as Result Type";
2091         }
2092         break;
2093       }
2094 
2095       case OpenCLLIB::Ldexp:
2096       case OpenCLLIB::Pown:
2097       case OpenCLLIB::Rootn: {
2098         if (!_.IsFloatScalarOrVectorType(result_type)) {
2099           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2100                  << ext_inst_name() << ": "
2101                  << "expected Result Type to be a float scalar or vector type";
2102         }
2103 
2104         const uint32_t num_components = _.GetDimension(result_type);
2105         if (num_components > 4 && num_components != 8 && num_components != 16) {
2106           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2107                  << ext_inst_name() << ": "
2108                  << "expected Result Type to be a scalar or a vector with 2, "
2109                     "3, 4, 8 or 16 components";
2110         }
2111 
2112         const uint32_t x_type = _.GetOperandTypeId(inst, 4);
2113         if (result_type != x_type) {
2114           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2115                  << ext_inst_name() << ": "
2116                  << "expected type of operand X to be equal to Result Type";
2117         }
2118 
2119         const uint32_t exp_type = _.GetOperandTypeId(inst, 5);
2120         if (!_.IsIntScalarOrVectorType(exp_type) ||
2121             _.GetBitWidth(exp_type) != 32) {
2122           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2123                  << ext_inst_name() << ": "
2124                  << "expected the exponent to be a 32-bit int scalar or vector";
2125         }
2126 
2127         if (_.GetDimension(exp_type) != num_components) {
2128           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2129                  << ext_inst_name() << ": "
2130                  << "expected the exponent to have the same number of "
2131                     "components as Result Type";
2132         }
2133         break;
2134       }
2135 
2136       case OpenCLLIB::Nan: {
2137         if (!_.IsFloatScalarOrVectorType(result_type)) {
2138           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2139                  << ext_inst_name() << ": "
2140                  << "expected Result Type to be a float scalar or vector type";
2141         }
2142 
2143         const uint32_t num_components = _.GetDimension(result_type);
2144         if (num_components > 4 && num_components != 8 && num_components != 16) {
2145           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2146                  << ext_inst_name() << ": "
2147                  << "expected Result Type to be a scalar or a vector with 2, "
2148                     "3, 4, 8 or 16 components";
2149         }
2150 
2151         const uint32_t nancode_type = _.GetOperandTypeId(inst, 4);
2152         if (!_.IsIntScalarOrVectorType(nancode_type)) {
2153           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2154                  << ext_inst_name() << ": "
2155                  << "expected Nancode to be an int scalar or vector type";
2156         }
2157 
2158         if (_.GetDimension(nancode_type) != num_components) {
2159           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2160                  << ext_inst_name() << ": "
2161                  << "expected Nancode to have the same number of components as "
2162                     "Result Type";
2163         }
2164 
2165         if (_.GetBitWidth(result_type) != _.GetBitWidth(nancode_type)) {
2166           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2167                  << ext_inst_name() << ": "
2168                  << "expected Nancode to have the same bit width as Result "
2169                     "Type";
2170         }
2171         break;
2172       }
2173 
2174       case OpenCLLIB::SAbs:
2175       case OpenCLLIB::SAbs_diff:
2176       case OpenCLLIB::SAdd_sat:
2177       case OpenCLLIB::UAdd_sat:
2178       case OpenCLLIB::SHadd:
2179       case OpenCLLIB::UHadd:
2180       case OpenCLLIB::SRhadd:
2181       case OpenCLLIB::URhadd:
2182       case OpenCLLIB::SClamp:
2183       case OpenCLLIB::UClamp:
2184       case OpenCLLIB::Clz:
2185       case OpenCLLIB::Ctz:
2186       case OpenCLLIB::SMad_hi:
2187       case OpenCLLIB::UMad_sat:
2188       case OpenCLLIB::SMad_sat:
2189       case OpenCLLIB::SMax:
2190       case OpenCLLIB::UMax:
2191       case OpenCLLIB::SMin:
2192       case OpenCLLIB::UMin:
2193       case OpenCLLIB::SMul_hi:
2194       case OpenCLLIB::Rotate:
2195       case OpenCLLIB::SSub_sat:
2196       case OpenCLLIB::USub_sat:
2197       case OpenCLLIB::Popcount:
2198       case OpenCLLIB::UAbs:
2199       case OpenCLLIB::UAbs_diff:
2200       case OpenCLLIB::UMul_hi:
2201       case OpenCLLIB::UMad_hi: {
2202         if (!_.IsIntScalarOrVectorType(result_type)) {
2203           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2204                  << ext_inst_name() << ": "
2205                  << "expected Result Type to be an int scalar or vector type";
2206         }
2207 
2208         const uint32_t num_components = _.GetDimension(result_type);
2209         if (num_components > 4 && num_components != 8 && num_components != 16) {
2210           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2211                  << ext_inst_name() << ": "
2212                  << "expected Result Type to be a scalar or a vector with 2, "
2213                     "3, 4, 8 or 16 components";
2214         }
2215 
2216         for (uint32_t operand_index = 4; operand_index < num_operands;
2217              ++operand_index) {
2218           const uint32_t operand_type = _.GetOperandTypeId(inst, operand_index);
2219           if (result_type != operand_type) {
2220             return _.diag(SPV_ERROR_INVALID_DATA, inst)
2221                    << ext_inst_name() << ": "
2222                    << "expected types of all operands to be equal to Result "
2223                       "Type";
2224           }
2225         }
2226         break;
2227       }
2228 
2229       case OpenCLLIB::U_Upsample:
2230       case OpenCLLIB::S_Upsample: {
2231         if (!_.IsIntScalarOrVectorType(result_type)) {
2232           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2233                  << ext_inst_name() << ": "
2234                  << "expected Result Type to be an int scalar or vector "
2235                     "type";
2236         }
2237 
2238         const uint32_t result_num_components = _.GetDimension(result_type);
2239         if (result_num_components > 4 && result_num_components != 8 &&
2240             result_num_components != 16) {
2241           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2242                  << ext_inst_name() << ": "
2243                  << "expected Result Type to be a scalar or a vector with 2, "
2244                     "3, 4, 8 or 16 components";
2245         }
2246 
2247         const uint32_t result_bit_width = _.GetBitWidth(result_type);
2248         if (result_bit_width != 16 && result_bit_width != 32 &&
2249             result_bit_width != 64) {
2250           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2251                  << ext_inst_name() << ": "
2252                  << "expected bit width of Result Type components to be 16, 32 "
2253                     "or 64";
2254         }
2255 
2256         const uint32_t hi_type = _.GetOperandTypeId(inst, 4);
2257         const uint32_t lo_type = _.GetOperandTypeId(inst, 5);
2258 
2259         if (hi_type != lo_type) {
2260           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2261                  << ext_inst_name() << ": "
2262                  << "expected Hi and Lo operands to have the same type";
2263         }
2264 
2265         if (result_num_components != _.GetDimension(hi_type)) {
2266           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2267                  << ext_inst_name() << ": "
2268                  << "expected Hi and Lo operands to have the same number of "
2269                     "components as Result Type";
2270         }
2271 
2272         if (result_bit_width != 2 * _.GetBitWidth(hi_type)) {
2273           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2274                  << ext_inst_name() << ": "
2275                  << "expected bit width of components of Hi and Lo operands to "
2276                     "be half of the bit width of components of Result Type";
2277         }
2278         break;
2279       }
2280 
2281       case OpenCLLIB::SMad24:
2282       case OpenCLLIB::UMad24:
2283       case OpenCLLIB::SMul24:
2284       case OpenCLLIB::UMul24: {
2285         if (!_.IsIntScalarOrVectorType(result_type) ||
2286             _.GetBitWidth(result_type) != 32) {
2287           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2288                  << ext_inst_name() << ": "
2289                  << "expected Result Type to be a 32-bit int scalar or vector "
2290                     "type";
2291         }
2292 
2293         const uint32_t num_components = _.GetDimension(result_type);
2294         if (num_components > 4 && num_components != 8 && num_components != 16) {
2295           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2296                  << ext_inst_name() << ": "
2297                  << "expected Result Type to be a scalar or a vector with 2, "
2298                     "3, 4, 8 or 16 components";
2299         }
2300 
2301         for (uint32_t operand_index = 4; operand_index < num_operands;
2302              ++operand_index) {
2303           const uint32_t operand_type = _.GetOperandTypeId(inst, operand_index);
2304           if (result_type != operand_type) {
2305             return _.diag(SPV_ERROR_INVALID_DATA, inst)
2306                    << ext_inst_name() << ": "
2307                    << "expected types of all operands to be equal to Result "
2308                       "Type";
2309           }
2310         }
2311         break;
2312       }
2313 
2314       case OpenCLLIB::Cross: {
2315         if (!_.IsFloatVectorType(result_type)) {
2316           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2317                  << ext_inst_name() << ": "
2318                  << "expected Result Type to be a float vector type";
2319         }
2320 
2321         const uint32_t num_components = _.GetDimension(result_type);
2322         if (num_components != 3 && num_components != 4) {
2323           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2324                  << ext_inst_name() << ": "
2325                  << "expected Result Type to have 3 or 4 components";
2326         }
2327 
2328         const uint32_t x_type = _.GetOperandTypeId(inst, 4);
2329         const uint32_t y_type = _.GetOperandTypeId(inst, 5);
2330 
2331         if (x_type != result_type) {
2332           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2333                  << ext_inst_name() << ": "
2334                  << "expected operand X type to be equal to Result Type";
2335         }
2336 
2337         if (y_type != result_type) {
2338           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2339                  << ext_inst_name() << ": "
2340                  << "expected operand Y type to be equal to Result Type";
2341         }
2342         break;
2343       }
2344 
2345       case OpenCLLIB::Distance:
2346       case OpenCLLIB::Fast_distance: {
2347         if (!_.IsFloatScalarType(result_type)) {
2348           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2349                  << ext_inst_name() << ": "
2350                  << "expected Result Type to be a float scalar type";
2351         }
2352 
2353         const uint32_t p0_type = _.GetOperandTypeId(inst, 4);
2354         if (!_.IsFloatScalarOrVectorType(p0_type)) {
2355           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2356                  << ext_inst_name() << ": "
2357                  << "expected operand P0 to be of float scalar or vector type";
2358         }
2359 
2360         const uint32_t num_components = _.GetDimension(p0_type);
2361         if (num_components > 4) {
2362           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2363                  << ext_inst_name() << ": "
2364                  << "expected operand P0 to have no more than 4 components";
2365         }
2366 
2367         if (result_type != _.GetComponentType(p0_type)) {
2368           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2369                  << ext_inst_name() << ": "
2370                  << "expected operand P0 component type to be equal to "
2371                  << "Result Type";
2372         }
2373 
2374         const uint32_t p1_type = _.GetOperandTypeId(inst, 5);
2375         if (p0_type != p1_type) {
2376           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2377                  << ext_inst_name() << ": "
2378                  << "expected operands P0 and P1 to be of the same type";
2379         }
2380         break;
2381       }
2382 
2383       case OpenCLLIB::Length:
2384       case OpenCLLIB::Fast_length: {
2385         if (!_.IsFloatScalarType(result_type)) {
2386           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2387                  << ext_inst_name() << ": "
2388                  << "expected Result Type to be a float scalar type";
2389         }
2390 
2391         const uint32_t p_type = _.GetOperandTypeId(inst, 4);
2392         if (!_.IsFloatScalarOrVectorType(p_type)) {
2393           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2394                  << ext_inst_name() << ": "
2395                  << "expected operand P to be a float scalar or vector";
2396         }
2397 
2398         const uint32_t num_components = _.GetDimension(p_type);
2399         if (num_components > 4) {
2400           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2401                  << ext_inst_name() << ": "
2402                  << "expected operand P to have no more than 4 components";
2403         }
2404 
2405         if (result_type != _.GetComponentType(p_type)) {
2406           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2407                  << ext_inst_name() << ": "
2408                  << "expected operand P component type to be equal to Result "
2409                     "Type";
2410         }
2411         break;
2412       }
2413 
2414       case OpenCLLIB::Normalize:
2415       case OpenCLLIB::Fast_normalize: {
2416         if (!_.IsFloatScalarOrVectorType(result_type)) {
2417           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2418                  << ext_inst_name() << ": "
2419                  << "expected Result Type to be a float scalar or vector type";
2420         }
2421 
2422         const uint32_t num_components = _.GetDimension(result_type);
2423         if (num_components > 4) {
2424           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2425                  << ext_inst_name() << ": "
2426                  << "expected Result Type to have no more than 4 components";
2427         }
2428 
2429         const uint32_t p_type = _.GetOperandTypeId(inst, 4);
2430         if (p_type != result_type) {
2431           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2432                  << ext_inst_name() << ": "
2433                  << "expected operand P type to be equal to Result Type";
2434         }
2435         break;
2436       }
2437 
2438       case OpenCLLIB::Bitselect: {
2439         if (!_.IsFloatScalarOrVectorType(result_type) &&
2440             !_.IsIntScalarOrVectorType(result_type)) {
2441           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2442                  << ext_inst_name() << ": "
2443                  << "expected Result Type to be an int or float scalar or "
2444                     "vector type";
2445         }
2446 
2447         const uint32_t num_components = _.GetDimension(result_type);
2448         if (num_components > 4 && num_components != 8 && num_components != 16) {
2449           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2450                  << ext_inst_name() << ": "
2451                  << "expected Result Type to be a scalar or a vector with 2, "
2452                     "3, 4, 8 or 16 components";
2453         }
2454 
2455         for (uint32_t operand_index = 4; operand_index < num_operands;
2456              ++operand_index) {
2457           const uint32_t operand_type = _.GetOperandTypeId(inst, operand_index);
2458           if (result_type != operand_type) {
2459             return _.diag(SPV_ERROR_INVALID_DATA, inst)
2460                    << ext_inst_name() << ": "
2461                    << "expected types of all operands to be equal to Result "
2462                       "Type";
2463           }
2464         }
2465         break;
2466       }
2467 
2468       case OpenCLLIB::Select: {
2469         if (!_.IsFloatScalarOrVectorType(result_type) &&
2470             !_.IsIntScalarOrVectorType(result_type)) {
2471           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2472                  << ext_inst_name() << ": "
2473                  << "expected Result Type to be an int or float scalar or "
2474                     "vector type";
2475         }
2476 
2477         const uint32_t num_components = _.GetDimension(result_type);
2478         if (num_components > 4 && num_components != 8 && num_components != 16) {
2479           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2480                  << ext_inst_name() << ": "
2481                  << "expected Result Type to be a scalar or a vector with 2, "
2482                     "3, 4, 8 or 16 components";
2483         }
2484 
2485         const uint32_t a_type = _.GetOperandTypeId(inst, 4);
2486         const uint32_t b_type = _.GetOperandTypeId(inst, 5);
2487         const uint32_t c_type = _.GetOperandTypeId(inst, 6);
2488 
2489         if (result_type != a_type) {
2490           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2491                  << ext_inst_name() << ": "
2492                  << "expected operand A type to be equal to Result Type";
2493         }
2494 
2495         if (result_type != b_type) {
2496           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2497                  << ext_inst_name() << ": "
2498                  << "expected operand B type to be equal to Result Type";
2499         }
2500 
2501         if (!_.IsIntScalarOrVectorType(c_type)) {
2502           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2503                  << ext_inst_name() << ": "
2504                  << "expected operand C to be an int scalar or vector";
2505         }
2506 
2507         if (num_components != _.GetDimension(c_type)) {
2508           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2509                  << ext_inst_name() << ": "
2510                  << "expected operand C to have the same number of components "
2511                     "as Result Type";
2512         }
2513 
2514         if (_.GetBitWidth(result_type) != _.GetBitWidth(c_type)) {
2515           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2516                  << ext_inst_name() << ": "
2517                  << "expected operand C to have the same bit width as Result "
2518                     "Type";
2519         }
2520         break;
2521       }
2522 
2523       case OpenCLLIB::Vloadn: {
2524         if (!_.IsFloatVectorType(result_type) &&
2525             !_.IsIntVectorType(result_type)) {
2526           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2527                  << ext_inst_name() << ": "
2528                  << "expected Result Type to be an int or float vector type";
2529         }
2530 
2531         const uint32_t num_components = _.GetDimension(result_type);
2532         if (num_components > 4 && num_components != 8 && num_components != 16) {
2533           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2534                  << ext_inst_name() << ": "
2535                  << "expected Result Type to have 2, 3, 4, 8 or 16 components";
2536         }
2537 
2538         const uint32_t offset_type = _.GetOperandTypeId(inst, 4);
2539         const uint32_t p_type = _.GetOperandTypeId(inst, 5);
2540 
2541         const uint32_t size_t_bit_width = GetSizeTBitWidth(_);
2542         if (!size_t_bit_width) {
2543           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2544                  << ext_inst_name()
2545                  << " can only be used with physical addressing models";
2546         }
2547 
2548         if (!_.IsIntScalarType(offset_type) ||
2549             _.GetBitWidth(offset_type) != size_t_bit_width) {
2550           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2551                  << ext_inst_name() << ": "
2552                  << "expected operand Offset to be of type size_t ("
2553                  << size_t_bit_width
2554                  << "-bit integer for the addressing model used in the module)";
2555         }
2556 
2557         spv::StorageClass p_storage_class;
2558         uint32_t p_data_type = 0;
2559         if (!_.GetPointerTypeInfo(p_type, &p_data_type, &p_storage_class)) {
2560           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2561                  << ext_inst_name() << ": "
2562                  << "expected operand P to be a pointer";
2563         }
2564 
2565         if (p_storage_class != spv::StorageClass::UniformConstant &&
2566             p_storage_class != spv::StorageClass::Generic &&
2567             p_storage_class != spv::StorageClass::CrossWorkgroup &&
2568             p_storage_class != spv::StorageClass::Workgroup &&
2569             p_storage_class != spv::StorageClass::Function) {
2570           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2571                  << ext_inst_name() << ": "
2572                  << "expected operand P storage class to be UniformConstant, "
2573                     "Generic, CrossWorkgroup, Workgroup or Function";
2574         }
2575 
2576         if (_.GetComponentType(result_type) != p_data_type) {
2577           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2578                  << ext_inst_name() << ": "
2579                  << "expected operand P data type to be equal to component "
2580                     "type of Result Type";
2581         }
2582 
2583         const uint32_t n_value = inst->word(7);
2584         if (num_components != n_value) {
2585           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2586                  << ext_inst_name() << ": "
2587                  << "expected literal N to be equal to the number of "
2588                     "components of Result Type";
2589         }
2590         break;
2591       }
2592 
2593       case OpenCLLIB::Vstoren: {
2594         if (_.GetIdOpcode(result_type) != spv::Op::OpTypeVoid) {
2595           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2596                  << ext_inst_name() << ": expected Result Type to be void";
2597         }
2598 
2599         const uint32_t data_type = _.GetOperandTypeId(inst, 4);
2600         const uint32_t offset_type = _.GetOperandTypeId(inst, 5);
2601         const uint32_t p_type = _.GetOperandTypeId(inst, 6);
2602 
2603         if (!_.IsFloatVectorType(data_type) && !_.IsIntVectorType(data_type)) {
2604           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2605                  << ext_inst_name() << ": "
2606                  << "expected Data to be an int or float vector";
2607         }
2608 
2609         const uint32_t num_components = _.GetDimension(data_type);
2610         if (num_components > 4 && num_components != 8 && num_components != 16) {
2611           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2612                  << ext_inst_name() << ": "
2613                  << "expected Data to have 2, 3, 4, 8 or 16 components";
2614         }
2615 
2616         const uint32_t size_t_bit_width = GetSizeTBitWidth(_);
2617         if (!size_t_bit_width) {
2618           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2619                  << ext_inst_name()
2620                  << " can only be used with physical addressing models";
2621         }
2622 
2623         if (!_.IsIntScalarType(offset_type) ||
2624             _.GetBitWidth(offset_type) != size_t_bit_width) {
2625           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2626                  << ext_inst_name() << ": "
2627                  << "expected operand Offset to be of type size_t ("
2628                  << size_t_bit_width
2629                  << "-bit integer for the addressing model used in the module)";
2630         }
2631 
2632         spv::StorageClass p_storage_class;
2633         uint32_t p_data_type = 0;
2634         if (!_.GetPointerTypeInfo(p_type, &p_data_type, &p_storage_class)) {
2635           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2636                  << ext_inst_name() << ": "
2637                  << "expected operand P to be a pointer";
2638         }
2639 
2640         if (p_storage_class != spv::StorageClass::Generic &&
2641             p_storage_class != spv::StorageClass::CrossWorkgroup &&
2642             p_storage_class != spv::StorageClass::Workgroup &&
2643             p_storage_class != spv::StorageClass::Function) {
2644           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2645                  << ext_inst_name() << ": "
2646                  << "expected operand P storage class to be Generic, "
2647                     "CrossWorkgroup, Workgroup or Function";
2648         }
2649 
2650         if (_.GetComponentType(data_type) != p_data_type) {
2651           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2652                  << ext_inst_name() << ": "
2653                  << "expected operand P data type to be equal to the type of "
2654                     "operand Data components";
2655         }
2656         break;
2657       }
2658 
2659       case OpenCLLIB::Vload_half: {
2660         if (!_.IsFloatScalarType(result_type)) {
2661           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2662                  << ext_inst_name() << ": "
2663                  << "expected Result Type to be a float scalar type";
2664         }
2665 
2666         const uint32_t offset_type = _.GetOperandTypeId(inst, 4);
2667         const uint32_t p_type = _.GetOperandTypeId(inst, 5);
2668 
2669         const uint32_t size_t_bit_width = GetSizeTBitWidth(_);
2670         if (!size_t_bit_width) {
2671           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2672                  << ext_inst_name()
2673                  << " can only be used with physical addressing models";
2674         }
2675 
2676         if (!_.IsIntScalarType(offset_type) ||
2677             _.GetBitWidth(offset_type) != size_t_bit_width) {
2678           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2679                  << ext_inst_name() << ": "
2680                  << "expected operand Offset to be of type size_t ("
2681                  << size_t_bit_width
2682                  << "-bit integer for the addressing model used in the module)";
2683         }
2684 
2685         spv::StorageClass p_storage_class;
2686         uint32_t p_data_type = 0;
2687         if (!_.GetPointerTypeInfo(p_type, &p_data_type, &p_storage_class)) {
2688           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2689                  << ext_inst_name() << ": "
2690                  << "expected operand P to be a pointer";
2691         }
2692 
2693         if (p_storage_class != spv::StorageClass::UniformConstant &&
2694             p_storage_class != spv::StorageClass::Generic &&
2695             p_storage_class != spv::StorageClass::CrossWorkgroup &&
2696             p_storage_class != spv::StorageClass::Workgroup &&
2697             p_storage_class != spv::StorageClass::Function) {
2698           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2699                  << ext_inst_name() << ": "
2700                  << "expected operand P storage class to be UniformConstant, "
2701                     "Generic, CrossWorkgroup, Workgroup or Function";
2702         }
2703 
2704         if (!_.IsFloatScalarType(p_data_type) ||
2705             _.GetBitWidth(p_data_type) != 16) {
2706           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2707                  << ext_inst_name() << ": "
2708                  << "expected operand P data type to be 16-bit float scalar";
2709         }
2710         break;
2711       }
2712 
2713       case OpenCLLIB::Vload_halfn:
2714       case OpenCLLIB::Vloada_halfn: {
2715         if (!_.IsFloatVectorType(result_type)) {
2716           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2717                  << ext_inst_name() << ": "
2718                  << "expected Result Type to be a float vector type";
2719         }
2720 
2721         const uint32_t num_components = _.GetDimension(result_type);
2722         if (num_components > 4 && num_components != 8 && num_components != 16) {
2723           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2724                  << ext_inst_name() << ": "
2725                  << "expected Result Type to have 2, 3, 4, 8 or 16 components";
2726         }
2727 
2728         const uint32_t offset_type = _.GetOperandTypeId(inst, 4);
2729         const uint32_t p_type = _.GetOperandTypeId(inst, 5);
2730 
2731         const uint32_t size_t_bit_width = GetSizeTBitWidth(_);
2732         if (!size_t_bit_width) {
2733           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2734                  << ext_inst_name()
2735                  << " can only be used with physical addressing models";
2736         }
2737 
2738         if (!_.IsIntScalarType(offset_type) ||
2739             _.GetBitWidth(offset_type) != size_t_bit_width) {
2740           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2741                  << ext_inst_name() << ": "
2742                  << "expected operand Offset to be of type size_t ("
2743                  << size_t_bit_width
2744                  << "-bit integer for the addressing model used in the module)";
2745         }
2746 
2747         spv::StorageClass p_storage_class;
2748         uint32_t p_data_type = 0;
2749         if (!_.GetPointerTypeInfo(p_type, &p_data_type, &p_storage_class)) {
2750           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2751                  << ext_inst_name() << ": "
2752                  << "expected operand P to be a pointer";
2753         }
2754 
2755         if (p_storage_class != spv::StorageClass::UniformConstant &&
2756             p_storage_class != spv::StorageClass::Generic &&
2757             p_storage_class != spv::StorageClass::CrossWorkgroup &&
2758             p_storage_class != spv::StorageClass::Workgroup &&
2759             p_storage_class != spv::StorageClass::Function) {
2760           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2761                  << ext_inst_name() << ": "
2762                  << "expected operand P storage class to be UniformConstant, "
2763                     "Generic, CrossWorkgroup, Workgroup or Function";
2764         }
2765 
2766         if (!_.IsFloatScalarType(p_data_type) ||
2767             _.GetBitWidth(p_data_type) != 16) {
2768           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2769                  << ext_inst_name() << ": "
2770                  << "expected operand P data type to be 16-bit float scalar";
2771         }
2772 
2773         const uint32_t n_value = inst->word(7);
2774         if (num_components != n_value) {
2775           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2776                  << ext_inst_name() << ": "
2777                  << "expected literal N to be equal to the number of "
2778                     "components of Result Type";
2779         }
2780         break;
2781       }
2782 
2783       case OpenCLLIB::Vstore_half:
2784       case OpenCLLIB::Vstore_half_r:
2785       case OpenCLLIB::Vstore_halfn:
2786       case OpenCLLIB::Vstore_halfn_r:
2787       case OpenCLLIB::Vstorea_halfn:
2788       case OpenCLLIB::Vstorea_halfn_r: {
2789         if (_.GetIdOpcode(result_type) != spv::Op::OpTypeVoid) {
2790           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2791                  << ext_inst_name() << ": expected Result Type to be void";
2792         }
2793 
2794         const uint32_t data_type = _.GetOperandTypeId(inst, 4);
2795         const uint32_t offset_type = _.GetOperandTypeId(inst, 5);
2796         const uint32_t p_type = _.GetOperandTypeId(inst, 6);
2797         const uint32_t data_type_bit_width = _.GetBitWidth(data_type);
2798 
2799         if (ext_inst_key == OpenCLLIB::Vstore_half ||
2800             ext_inst_key == OpenCLLIB::Vstore_half_r) {
2801           if (!_.IsFloatScalarType(data_type) ||
2802               (data_type_bit_width != 32 && data_type_bit_width != 64)) {
2803             return _.diag(SPV_ERROR_INVALID_DATA, inst)
2804                    << ext_inst_name() << ": "
2805                    << "expected Data to be a 32 or 64-bit float scalar";
2806           }
2807         } else {
2808           if (!_.IsFloatVectorType(data_type) ||
2809               (data_type_bit_width != 32 && data_type_bit_width != 64)) {
2810             return _.diag(SPV_ERROR_INVALID_DATA, inst)
2811                    << ext_inst_name() << ": "
2812                    << "expected Data to be a 32 or 64-bit float vector";
2813           }
2814 
2815           const uint32_t num_components = _.GetDimension(data_type);
2816           if (num_components > 4 && num_components != 8 &&
2817               num_components != 16) {
2818             return _.diag(SPV_ERROR_INVALID_DATA, inst)
2819                    << ext_inst_name() << ": "
2820                    << "expected Data to have 2, 3, 4, 8 or 16 components";
2821           }
2822         }
2823 
2824         const uint32_t size_t_bit_width = GetSizeTBitWidth(_);
2825         if (!size_t_bit_width) {
2826           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2827                  << ext_inst_name()
2828                  << " can only be used with physical addressing models";
2829         }
2830 
2831         if (!_.IsIntScalarType(offset_type) ||
2832             _.GetBitWidth(offset_type) != size_t_bit_width) {
2833           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2834                  << ext_inst_name() << ": "
2835                  << "expected operand Offset to be of type size_t ("
2836                  << size_t_bit_width
2837                  << "-bit integer for the addressing model used in the module)";
2838         }
2839 
2840         spv::StorageClass p_storage_class;
2841         uint32_t p_data_type = 0;
2842         if (!_.GetPointerTypeInfo(p_type, &p_data_type, &p_storage_class)) {
2843           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2844                  << ext_inst_name() << ": "
2845                  << "expected operand P to be a pointer";
2846         }
2847 
2848         if (p_storage_class != spv::StorageClass::Generic &&
2849             p_storage_class != spv::StorageClass::CrossWorkgroup &&
2850             p_storage_class != spv::StorageClass::Workgroup &&
2851             p_storage_class != spv::StorageClass::Function) {
2852           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2853                  << ext_inst_name() << ": "
2854                  << "expected operand P storage class to be Generic, "
2855                     "CrossWorkgroup, Workgroup or Function";
2856         }
2857 
2858         if (!_.IsFloatScalarType(p_data_type) ||
2859             _.GetBitWidth(p_data_type) != 16) {
2860           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2861                  << ext_inst_name() << ": "
2862                  << "expected operand P data type to be 16-bit float scalar";
2863         }
2864 
2865         // Rounding mode enum is checked by assembler.
2866         break;
2867       }
2868 
2869       case OpenCLLIB::Shuffle:
2870       case OpenCLLIB::Shuffle2: {
2871         if (!_.IsFloatVectorType(result_type) &&
2872             !_.IsIntVectorType(result_type)) {
2873           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2874                  << ext_inst_name() << ": "
2875                  << "expected Result Type to be an int or float vector type";
2876         }
2877 
2878         const uint32_t result_num_components = _.GetDimension(result_type);
2879         if (result_num_components != 2 && result_num_components != 4 &&
2880             result_num_components != 8 && result_num_components != 16) {
2881           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2882                  << ext_inst_name() << ": "
2883                  << "expected Result Type to have 2, 4, 8 or 16 components";
2884         }
2885 
2886         uint32_t operand_index = 4;
2887         const uint32_t x_type = _.GetOperandTypeId(inst, operand_index++);
2888 
2889         if (ext_inst_key == OpenCLLIB::Shuffle2) {
2890           const uint32_t y_type = _.GetOperandTypeId(inst, operand_index++);
2891           if (x_type != y_type) {
2892             return _.diag(SPV_ERROR_INVALID_DATA, inst)
2893                    << ext_inst_name() << ": "
2894                    << "expected operands X and Y to be of the same type";
2895           }
2896         }
2897 
2898         const uint32_t shuffle_mask_type =
2899             _.GetOperandTypeId(inst, operand_index++);
2900 
2901         if (!_.IsFloatVectorType(x_type) && !_.IsIntVectorType(x_type)) {
2902           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2903                  << ext_inst_name() << ": "
2904                  << "expected operand X to be an int or float vector";
2905         }
2906 
2907         const uint32_t x_num_components = _.GetDimension(x_type);
2908         if (x_num_components != 2 && x_num_components != 4 &&
2909             x_num_components != 8 && x_num_components != 16) {
2910           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2911                  << ext_inst_name() << ": "
2912                  << "expected operand X to have 2, 4, 8 or 16 components";
2913         }
2914 
2915         const uint32_t result_component_type = _.GetComponentType(result_type);
2916 
2917         if (result_component_type != _.GetComponentType(x_type)) {
2918           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2919                  << ext_inst_name() << ": "
2920                  << "expected operand X and Result Type to have equal "
2921                     "component types";
2922         }
2923 
2924         if (!_.IsIntVectorType(shuffle_mask_type)) {
2925           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2926                  << ext_inst_name() << ": "
2927                  << "expected operand Shuffle Mask to be an int vector";
2928         }
2929 
2930         if (result_num_components != _.GetDimension(shuffle_mask_type)) {
2931           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2932                  << ext_inst_name() << ": "
2933                  << "expected operand Shuffle Mask to have the same number of "
2934                     "components as Result Type";
2935         }
2936 
2937         if (_.GetBitWidth(result_component_type) !=
2938             _.GetBitWidth(shuffle_mask_type)) {
2939           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2940                  << ext_inst_name() << ": "
2941                  << "expected operand Shuffle Mask components to have the same "
2942                     "bit width as Result Type components";
2943         }
2944         break;
2945       }
2946 
2947       case OpenCLLIB::Printf: {
2948         if (!_.IsIntScalarType(result_type) ||
2949             _.GetBitWidth(result_type) != 32) {
2950           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2951                  << ext_inst_name() << ": "
2952                  << "expected Result Type to be a 32-bit int type";
2953         }
2954 
2955         const uint32_t format_type = _.GetOperandTypeId(inst, 4);
2956         spv::StorageClass format_storage_class;
2957         uint32_t format_data_type = 0;
2958         if (!_.GetPointerTypeInfo(format_type, &format_data_type,
2959                                   &format_storage_class)) {
2960           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2961                  << ext_inst_name() << ": "
2962                  << "expected operand Format to be a pointer";
2963         }
2964 
2965         if (format_storage_class != spv::StorageClass::UniformConstant) {
2966           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2967                  << ext_inst_name() << ": "
2968                  << "expected Format storage class to be UniformConstant";
2969         }
2970 
2971         if (!_.IsIntScalarType(format_data_type) ||
2972             _.GetBitWidth(format_data_type) != 8) {
2973           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2974                  << ext_inst_name() << ": "
2975                  << "expected Format data type to be 8-bit int";
2976         }
2977         break;
2978       }
2979 
2980       case OpenCLLIB::Prefetch: {
2981         if (_.GetIdOpcode(result_type) != spv::Op::OpTypeVoid) {
2982           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2983                  << ext_inst_name() << ": expected Result Type to be void";
2984         }
2985 
2986         const uint32_t p_type = _.GetOperandTypeId(inst, 4);
2987         const uint32_t num_elements_type = _.GetOperandTypeId(inst, 5);
2988 
2989         spv::StorageClass p_storage_class;
2990         uint32_t p_data_type = 0;
2991         if (!_.GetPointerTypeInfo(p_type, &p_data_type, &p_storage_class)) {
2992           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2993                  << ext_inst_name() << ": "
2994                  << "expected operand Ptr to be a pointer";
2995         }
2996 
2997         if (p_storage_class != spv::StorageClass::CrossWorkgroup) {
2998           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2999                  << ext_inst_name() << ": "
3000                  << "expected operand Ptr storage class to be CrossWorkgroup";
3001         }
3002 
3003         if (!_.IsFloatScalarOrVectorType(p_data_type) &&
3004             !_.IsIntScalarOrVectorType(p_data_type)) {
3005           return _.diag(SPV_ERROR_INVALID_DATA, inst)
3006                  << ext_inst_name() << ": "
3007                  << "expected Ptr data type to be int or float scalar or "
3008                     "vector";
3009         }
3010 
3011         const uint32_t num_components = _.GetDimension(p_data_type);
3012         if (num_components > 4 && num_components != 8 && num_components != 16) {
3013           return _.diag(SPV_ERROR_INVALID_DATA, inst)
3014                  << ext_inst_name() << ": "
3015                  << "expected Result Type to be a scalar or a vector with 2, "
3016                     "3, 4, 8 or 16 components";
3017         }
3018 
3019         const uint32_t size_t_bit_width = GetSizeTBitWidth(_);
3020         if (!size_t_bit_width) {
3021           return _.diag(SPV_ERROR_INVALID_DATA, inst)
3022                  << ext_inst_name()
3023                  << " can only be used with physical addressing models";
3024         }
3025 
3026         if (!_.IsIntScalarType(num_elements_type) ||
3027             _.GetBitWidth(num_elements_type) != size_t_bit_width) {
3028           return _.diag(SPV_ERROR_INVALID_DATA, inst)
3029                  << ext_inst_name() << ": "
3030                  << "expected operand Num Elements to be of type size_t ("
3031                  << size_t_bit_width
3032                  << "-bit integer for the addressing model used in the module)";
3033         }
3034         break;
3035       }
3036     }
3037   } else if (ext_inst_type == SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100 ||
3038              ext_inst_type ==
3039                  SPV_EXT_INST_TYPE_NONSEMANTIC_SHADER_DEBUGINFO_100) {
3040     if (!_.IsVoidType(result_type)) {
3041       return _.diag(SPV_ERROR_INVALID_DATA, inst)
3042              << ext_inst_name() << ": "
3043              << "expected result type must be a result id of "
3044              << "OpTypeVoid";
3045     }
3046 
3047     const bool vulkanDebugInfo =
3048         ext_inst_type == SPV_EXT_INST_TYPE_NONSEMANTIC_SHADER_DEBUGINFO_100;
3049 
3050     auto num_words = inst->words().size();
3051 
3052     // Handle any non-common NonSemanticShaderDebugInfo instructions.
3053     if (vulkanDebugInfo) {
3054       const NonSemanticShaderDebugInfo100Instructions ext_inst_key =
3055           NonSemanticShaderDebugInfo100Instructions(ext_inst_index);
3056       switch (ext_inst_key) {
3057         // The following block of instructions will be handled by the common
3058         // validation.
3059         case NonSemanticShaderDebugInfo100DebugInfoNone:
3060         case NonSemanticShaderDebugInfo100DebugCompilationUnit:
3061         case NonSemanticShaderDebugInfo100DebugTypeBasic:
3062         case NonSemanticShaderDebugInfo100DebugTypePointer:
3063         case NonSemanticShaderDebugInfo100DebugTypeQualifier:
3064         case NonSemanticShaderDebugInfo100DebugTypeArray:
3065         case NonSemanticShaderDebugInfo100DebugTypeVector:
3066         case NonSemanticShaderDebugInfo100DebugTypedef:
3067         case NonSemanticShaderDebugInfo100DebugTypeFunction:
3068         case NonSemanticShaderDebugInfo100DebugTypeEnum:
3069         case NonSemanticShaderDebugInfo100DebugTypeComposite:
3070         case NonSemanticShaderDebugInfo100DebugTypeMember:
3071         case NonSemanticShaderDebugInfo100DebugTypeInheritance:
3072         case NonSemanticShaderDebugInfo100DebugTypePtrToMember:
3073         case NonSemanticShaderDebugInfo100DebugTypeTemplate:
3074         case NonSemanticShaderDebugInfo100DebugTypeTemplateParameter:
3075         case NonSemanticShaderDebugInfo100DebugTypeTemplateTemplateParameter:
3076         case NonSemanticShaderDebugInfo100DebugTypeTemplateParameterPack:
3077         case NonSemanticShaderDebugInfo100DebugGlobalVariable:
3078         case NonSemanticShaderDebugInfo100DebugFunctionDeclaration:
3079         case NonSemanticShaderDebugInfo100DebugFunction:
3080         case NonSemanticShaderDebugInfo100DebugLexicalBlock:
3081         case NonSemanticShaderDebugInfo100DebugLexicalBlockDiscriminator:
3082         case NonSemanticShaderDebugInfo100DebugScope:
3083         case NonSemanticShaderDebugInfo100DebugNoScope:
3084         case NonSemanticShaderDebugInfo100DebugInlinedAt:
3085         case NonSemanticShaderDebugInfo100DebugLocalVariable:
3086         case NonSemanticShaderDebugInfo100DebugInlinedVariable:
3087         case NonSemanticShaderDebugInfo100DebugDeclare:
3088         case NonSemanticShaderDebugInfo100DebugValue:
3089         case NonSemanticShaderDebugInfo100DebugOperation:
3090         case NonSemanticShaderDebugInfo100DebugExpression:
3091         case NonSemanticShaderDebugInfo100DebugMacroDef:
3092         case NonSemanticShaderDebugInfo100DebugMacroUndef:
3093         case NonSemanticShaderDebugInfo100DebugImportedEntity:
3094         case NonSemanticShaderDebugInfo100DebugSource:
3095           break;
3096         case NonSemanticShaderDebugInfo100DebugTypeMatrix: {
3097           CHECK_DEBUG_OPERAND("Vector Type", CommonDebugInfoDebugTypeVector, 5);
3098 
3099           CHECK_CONST_UINT_OPERAND("Vector Count", 6);
3100 
3101           uint32_t vector_count = inst->word(6);
3102           uint64_t const_val;
3103           if (!_.GetConstantValUint64(vector_count, &const_val)) {
3104             return _.diag(SPV_ERROR_INVALID_DATA, inst)
3105                    << ext_inst_name()
3106                    << ": Vector Count must be 32-bit integer OpConstant";
3107           }
3108 
3109           vector_count = const_val & 0xffffffff;
3110           if (!vector_count || vector_count > 4) {
3111             return _.diag(SPV_ERROR_INVALID_DATA, inst)
3112                    << ext_inst_name() << ": Vector Count must be positive "
3113                    << "integer less than or equal to 4";
3114           }
3115           break;
3116         }
3117         // TODO: Add validation rules for remaining cases as well.
3118         case NonSemanticShaderDebugInfo100DebugFunctionDefinition:
3119         case NonSemanticShaderDebugInfo100DebugSourceContinued:
3120         case NonSemanticShaderDebugInfo100DebugLine:
3121         case NonSemanticShaderDebugInfo100DebugNoLine:
3122         case NonSemanticShaderDebugInfo100DebugBuildIdentifier:
3123         case NonSemanticShaderDebugInfo100DebugStoragePath:
3124         case NonSemanticShaderDebugInfo100DebugEntryPoint:
3125           break;
3126         case NonSemanticShaderDebugInfo100InstructionsMax:
3127           assert(0);
3128           break;
3129       }
3130     }
3131 
3132     // Handle any non-common OpenCL insts, then common
3133     if (ext_inst_type != SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100 ||
3134         OpenCLDebugInfo100Instructions(ext_inst_index) !=
3135             OpenCLDebugInfo100DebugModuleINTEL) {
3136       const CommonDebugInfoInstructions ext_inst_key =
3137           CommonDebugInfoInstructions(ext_inst_index);
3138       switch (ext_inst_key) {
3139         case CommonDebugInfoDebugInfoNone:
3140         case CommonDebugInfoDebugNoScope:
3141           break;
3142           // The binary parser validates the opcode for DebugInfoNone,
3143           // DebugNoScope, DebugOperation. We just check the parameters to
3144           // DebugOperation are properly constants for vulkan debug info.
3145         case CommonDebugInfoDebugOperation: {
3146           CHECK_CONST_UINT_OPERAND("Operation", 5);
3147           for (uint32_t i = 6; i < num_words; ++i) {
3148             CHECK_CONST_UINT_OPERAND("Operand", i);
3149           }
3150           break;
3151         }
3152         case CommonDebugInfoDebugCompilationUnit: {
3153           CHECK_CONST_UINT_OPERAND("Version", 5);
3154           CHECK_CONST_UINT_OPERAND("DWARF Version", 6);
3155           CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource, 7);
3156           CHECK_CONST_UINT_OPERAND("Language", 8);
3157           break;
3158         }
3159         case CommonDebugInfoDebugSource: {
3160           CHECK_OPERAND("File", spv::Op::OpString, 5);
3161           if (num_words == 7) CHECK_OPERAND("Text", spv::Op::OpString, 6);
3162           break;
3163         }
3164         case CommonDebugInfoDebugTypeBasic: {
3165           CHECK_OPERAND("Name", spv::Op::OpString, 5);
3166           CHECK_OPERAND("Size", spv::Op::OpConstant, 6);
3167           CHECK_CONST_UINT_OPERAND("Encoding", 7);
3168           break;
3169         }
3170         case CommonDebugInfoDebugTypePointer: {
3171           auto validate_base_type = ValidateOperandDebugType(
3172               _, "Base Type", inst, 5, ext_inst_name, false);
3173           if (validate_base_type != SPV_SUCCESS) return validate_base_type;
3174           CHECK_CONST_UINT_OPERAND("Storage Class", 6);
3175           CHECK_CONST_UINT_OPERAND("Flags", 7);
3176           break;
3177         }
3178         case CommonDebugInfoDebugTypeQualifier: {
3179           auto validate_base_type = ValidateOperandDebugType(
3180               _, "Base Type", inst, 5, ext_inst_name, false);
3181           if (validate_base_type != SPV_SUCCESS) return validate_base_type;
3182           CHECK_CONST_UINT_OPERAND("Type Qualifier", 6);
3183           break;
3184         }
3185         case CommonDebugInfoDebugTypeVector: {
3186           auto validate_base_type =
3187               ValidateOperandBaseType(_, inst, 5, ext_inst_name);
3188           if (validate_base_type != SPV_SUCCESS) return validate_base_type;
3189 
3190           CHECK_CONST_UINT_OPERAND("Component Count", 6);
3191           uint32_t component_count = inst->word(6);
3192           if (vulkanDebugInfo) {
3193             uint64_t const_val;
3194             if (!_.GetConstantValUint64(component_count, &const_val)) {
3195               return _.diag(SPV_ERROR_INVALID_DATA, inst)
3196                      << ext_inst_name()
3197                      << ": Component Count must be 32-bit integer OpConstant";
3198             }
3199             component_count = const_val & 0xffffffff;
3200           }
3201 
3202           if (!component_count || component_count > 4) {
3203             return _.diag(SPV_ERROR_INVALID_DATA, inst)
3204                    << ext_inst_name() << ": Component Count must be positive "
3205                    << "integer less than or equal to 4";
3206           }
3207           break;
3208         }
3209         case CommonDebugInfoDebugTypeArray: {
3210           auto validate_base_type = ValidateOperandDebugType(
3211               _, "Base Type", inst, 5, ext_inst_name, false);
3212           if (validate_base_type != SPV_SUCCESS) return validate_base_type;
3213           for (uint32_t i = 6; i < num_words; ++i) {
3214             bool invalid = false;
3215             auto* component_count = _.FindDef(inst->word(i));
3216             if (IsConstIntScalarTypeWith32Or64Bits(_, component_count)) {
3217               // TODO: We need a spec discussion for the runtime array for
3218               // OpenCL.
3219               if (!vulkanDebugInfo && !component_count->word(3)) {
3220                 invalid = true;
3221               }
3222             } else if (component_count->words().size() > 6 &&
3223                        (CommonDebugInfoInstructions(component_count->word(4)) ==
3224                             CommonDebugInfoDebugLocalVariable ||
3225                         CommonDebugInfoInstructions(component_count->word(4)) ==
3226                             CommonDebugInfoDebugGlobalVariable)) {
3227               auto* component_count_type = _.FindDef(component_count->word(6));
3228               if (component_count_type->words().size() > 7) {
3229                 uint32_t encoding = component_count_type->word(7);
3230                 if (CommonDebugInfoInstructions(component_count_type->word(
3231                         4)) != CommonDebugInfoDebugTypeBasic ||
3232                     (vulkanDebugInfo && !IsUint32Constant(_, encoding)) ||
3233                     OpenCLDebugInfo100DebugBaseTypeAttributeEncoding(
3234                         vulkanDebugInfo
3235                             ? GetUint32Constant(_, encoding)
3236                             : encoding) != OpenCLDebugInfo100Unsigned) {
3237                   invalid = true;
3238                 } else {
3239                   // DebugTypeBasic for DebugLocalVariable/DebugGlobalVariable
3240                   // must have Unsigned encoding and 32 or 64 as its size in
3241                   // bits.
3242                   Instruction* size_in_bits =
3243                       _.FindDef(component_count_type->word(6));
3244                   if (!_.IsIntScalarType(size_in_bits->type_id()) ||
3245                       (size_in_bits->word(3) != 32 &&
3246                        size_in_bits->word(3) != 64)) {
3247                     invalid = true;
3248                   }
3249                 }
3250               } else {
3251                 invalid = true;
3252               }
3253             } else {
3254               invalid = true;
3255             }
3256             if (invalid) {
3257               return _.diag(SPV_ERROR_INVALID_DATA, inst)
3258                      << ext_inst_name() << ": Component Count must be "
3259                      << "OpConstant with a 32- or 64-bits integer scalar type "
3260                         "or "
3261                      << "DebugGlobalVariable or DebugLocalVariable with a 32- "
3262                         "or "
3263                      << "64-bits unsigned integer scalar type";
3264             }
3265           }
3266           break;
3267         }
3268         case CommonDebugInfoDebugTypedef: {
3269           CHECK_OPERAND("Name", spv::Op::OpString, 5);
3270           auto validate_base_type =
3271               ValidateOperandBaseType(_, inst, 6, ext_inst_name);
3272           if (validate_base_type != SPV_SUCCESS) return validate_base_type;
3273           CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource, 7);
3274           CHECK_CONST_UINT_OPERAND("Line", 8);
3275           CHECK_CONST_UINT_OPERAND("Column", 9);
3276           auto validate_parent =
3277               ValidateOperandLexicalScope(_, "Parent", inst, 10, ext_inst_name);
3278           if (validate_parent != SPV_SUCCESS) return validate_parent;
3279           break;
3280         }
3281         case CommonDebugInfoDebugTypeFunction: {
3282           CHECK_CONST_UINT_OPERAND("Flags", 5);
3283           auto* return_type = _.FindDef(inst->word(6));
3284           // TODO: We need a spec discussion that we have to allow return and
3285           // parameter types of a DebugTypeFunction to have template parameter.
3286           if (return_type->opcode() != spv::Op::OpTypeVoid) {
3287             auto validate_return = ValidateOperandDebugType(
3288                 _, "Return Type", inst, 6, ext_inst_name, true);
3289             if (validate_return != SPV_SUCCESS) return validate_return;
3290           }
3291           for (uint32_t word_index = 7; word_index < num_words; ++word_index) {
3292             auto validate_param = ValidateOperandDebugType(
3293                 _, "Parameter Types", inst, word_index, ext_inst_name, true);
3294             if (validate_param != SPV_SUCCESS) return validate_param;
3295           }
3296           break;
3297         }
3298         case CommonDebugInfoDebugTypeEnum: {
3299           CHECK_OPERAND("Name", spv::Op::OpString, 5);
3300           if (!DoesDebugInfoOperandMatchExpectation(
3301                   _,
3302                   [](CommonDebugInfoInstructions dbg_inst) {
3303                     return dbg_inst == CommonDebugInfoDebugInfoNone;
3304                   },
3305                   inst, 6)) {
3306             auto validate_underlying_type = ValidateOperandDebugType(
3307                 _, "Underlying Types", inst, 6, ext_inst_name, false);
3308             if (validate_underlying_type != SPV_SUCCESS)
3309               return validate_underlying_type;
3310           }
3311           CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource, 7);
3312           CHECK_CONST_UINT_OPERAND("Line", 8);
3313           CHECK_CONST_UINT_OPERAND("Column", 9);
3314           auto validate_parent =
3315               ValidateOperandLexicalScope(_, "Parent", inst, 10, ext_inst_name);
3316           if (validate_parent != SPV_SUCCESS) return validate_parent;
3317           CHECK_OPERAND("Size", spv::Op::OpConstant, 11);
3318           auto* size = _.FindDef(inst->word(11));
3319           if (!_.IsIntScalarType(size->type_id()) || !size->word(3)) {
3320             return _.diag(SPV_ERROR_INVALID_DATA, inst)
3321                    << ext_inst_name() << ": expected operand Size is a "
3322                    << "positive integer";
3323           }
3324           CHECK_CONST_UINT_OPERAND("Flags", 12);
3325           for (uint32_t word_index = 13; word_index + 1 < num_words;
3326                word_index += 2) {
3327             CHECK_OPERAND("Value", spv::Op::OpConstant, word_index);
3328             CHECK_OPERAND("Name", spv::Op::OpString, word_index + 1);
3329           }
3330           break;
3331         }
3332         case CommonDebugInfoDebugTypeComposite: {
3333           CHECK_OPERAND("Name", spv::Op::OpString, 5);
3334           CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource, 7);
3335           CHECK_CONST_UINT_OPERAND("Line", 8);
3336           CHECK_CONST_UINT_OPERAND("Column", 9);
3337           auto validate_parent =
3338               ValidateOperandLexicalScope(_, "Parent", inst, 10, ext_inst_name);
3339           if (validate_parent != SPV_SUCCESS) return validate_parent;
3340           CHECK_OPERAND("Linkage Name", spv::Op::OpString, 11);
3341           if (!DoesDebugInfoOperandMatchExpectation(
3342                   _,
3343                   [](CommonDebugInfoInstructions dbg_inst) {
3344                     return dbg_inst == CommonDebugInfoDebugInfoNone;
3345                   },
3346                   inst, 12)) {
3347             CHECK_OPERAND("Size", spv::Op::OpConstant, 12);
3348           }
3349           CHECK_CONST_UINT_OPERAND("Flags", 13);
3350           for (uint32_t word_index = 14; word_index < num_words; ++word_index) {
3351             if (!DoesDebugInfoOperandMatchExpectation(
3352                     _,
3353                     [](CommonDebugInfoInstructions dbg_inst) {
3354                       return dbg_inst == CommonDebugInfoDebugTypeMember ||
3355                              dbg_inst == CommonDebugInfoDebugFunction ||
3356                              dbg_inst == CommonDebugInfoDebugTypeInheritance;
3357                     },
3358                     inst, word_index)) {
3359               return _.diag(SPV_ERROR_INVALID_DATA, inst)
3360                      << ext_inst_name() << ": "
3361                      << "expected operand Members "
3362                      << "must be DebugTypeMember, DebugFunction, or "
3363                         "DebugTypeInheritance";
3364             }
3365           }
3366           break;
3367         }
3368         case CommonDebugInfoDebugTypeMember: {
3369           CHECK_OPERAND("Name", spv::Op::OpString, 5);
3370           // TODO: We need a spec discussion that we have to allow member types
3371           // to have template parameter.
3372           auto validate_type =
3373               ValidateOperandDebugType(_, "Type", inst, 6, ext_inst_name, true);
3374           if (validate_type != SPV_SUCCESS) return validate_type;
3375           CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource, 7);
3376           CHECK_CONST_UINT_OPERAND("Line", 8);
3377           CHECK_CONST_UINT_OPERAND("Column", 9);
3378           // NonSemantic.Shader.DebugInfo doesn't have the Parent operand
3379           if (vulkanDebugInfo) {
3380             CHECK_OPERAND("Offset", spv::Op::OpConstant, 10);
3381             CHECK_OPERAND("Size", spv::Op::OpConstant, 11);
3382             CHECK_CONST_UINT_OPERAND("Flags", 12);
3383             if (num_words == 14)
3384               CHECK_OPERAND("Value", spv::Op::OpConstant, 13);
3385           } else {
3386             CHECK_DEBUG_OPERAND("Parent", CommonDebugInfoDebugTypeComposite,
3387                                 10);
3388             CHECK_OPERAND("Offset", spv::Op::OpConstant, 11);
3389             CHECK_OPERAND("Size", spv::Op::OpConstant, 12);
3390             CHECK_CONST_UINT_OPERAND("Flags", 13);
3391             if (num_words == 15)
3392               CHECK_OPERAND("Value", spv::Op::OpConstant, 14);
3393           }
3394           break;
3395         }
3396         case CommonDebugInfoDebugTypeInheritance: {
3397           CHECK_DEBUG_OPERAND("Child", CommonDebugInfoDebugTypeComposite, 5);
3398           auto* debug_inst = _.FindDef(inst->word(5));
3399           auto composite_type =
3400               OpenCLDebugInfo100DebugCompositeType(debug_inst->word(6));
3401           if (composite_type != OpenCLDebugInfo100Class &&
3402               composite_type != OpenCLDebugInfo100Structure) {
3403             return _.diag(SPV_ERROR_INVALID_DATA, inst)
3404                    << ext_inst_name() << ": "
3405                    << "expected operand Child must be class or struct debug "
3406                       "type";
3407           }
3408           CHECK_DEBUG_OPERAND("Parent", CommonDebugInfoDebugTypeComposite, 6);
3409           debug_inst = _.FindDef(inst->word(6));
3410           composite_type =
3411               OpenCLDebugInfo100DebugCompositeType(debug_inst->word(6));
3412           if (composite_type != OpenCLDebugInfo100Class &&
3413               composite_type != OpenCLDebugInfo100Structure) {
3414             return _.diag(SPV_ERROR_INVALID_DATA, inst)
3415                    << ext_inst_name() << ": "
3416                    << "expected operand Parent must be class or struct debug "
3417                       "type";
3418           }
3419           CHECK_OPERAND("Offset", spv::Op::OpConstant, 7);
3420           CHECK_OPERAND("Size", spv::Op::OpConstant, 8);
3421           CHECK_CONST_UINT_OPERAND("Flags", 9);
3422           break;
3423         }
3424         case CommonDebugInfoDebugFunction: {
3425           CHECK_OPERAND("Name", spv::Op::OpString, 5);
3426           auto validate_type = ValidateOperandDebugType(_, "Type", inst, 6,
3427                                                         ext_inst_name, false);
3428           if (validate_type != SPV_SUCCESS) return validate_type;
3429           CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource, 7);
3430           CHECK_CONST_UINT_OPERAND("Line", 8);
3431           CHECK_CONST_UINT_OPERAND("Column", 9);
3432           auto validate_parent =
3433               ValidateOperandLexicalScope(_, "Parent", inst, 10, ext_inst_name);
3434           if (validate_parent != SPV_SUCCESS) return validate_parent;
3435           CHECK_OPERAND("Linkage Name", spv::Op::OpString, 11);
3436           CHECK_CONST_UINT_OPERAND("Flags", 12);
3437           CHECK_CONST_UINT_OPERAND("Scope Line", 13);
3438           // NonSemantic.Shader.DebugInfo.100 doesn't include a reference to the
3439           // OpFunction
3440           if (vulkanDebugInfo) {
3441             if (num_words == 15) {
3442               CHECK_DEBUG_OPERAND("Declaration",
3443                                   CommonDebugInfoDebugFunctionDeclaration, 14);
3444             }
3445           } else {
3446             if (!DoesDebugInfoOperandMatchExpectation(
3447                     _,
3448                     [](CommonDebugInfoInstructions dbg_inst) {
3449                       return dbg_inst == CommonDebugInfoDebugInfoNone;
3450                     },
3451                     inst, 14)) {
3452               CHECK_OPERAND("Function", spv::Op::OpFunction, 14);
3453             }
3454             if (num_words == 16) {
3455               CHECK_DEBUG_OPERAND("Declaration",
3456                                   CommonDebugInfoDebugFunctionDeclaration, 15);
3457             }
3458           }
3459           break;
3460         }
3461         case CommonDebugInfoDebugFunctionDeclaration: {
3462           CHECK_OPERAND("Name", spv::Op::OpString, 5);
3463           auto validate_type = ValidateOperandDebugType(_, "Type", inst, 6,
3464                                                         ext_inst_name, false);
3465           if (validate_type != SPV_SUCCESS) return validate_type;
3466           CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource, 7);
3467           CHECK_CONST_UINT_OPERAND("Line", 8);
3468           CHECK_CONST_UINT_OPERAND("Column", 9);
3469           auto validate_parent =
3470               ValidateOperandLexicalScope(_, "Parent", inst, 10, ext_inst_name);
3471           if (validate_parent != SPV_SUCCESS) return validate_parent;
3472           CHECK_OPERAND("Linkage Name", spv::Op::OpString, 11);
3473           CHECK_CONST_UINT_OPERAND("Flags", 12);
3474           break;
3475         }
3476         case CommonDebugInfoDebugLexicalBlock: {
3477           CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource, 5);
3478           CHECK_CONST_UINT_OPERAND("Line", 6);
3479           CHECK_CONST_UINT_OPERAND("Column", 7);
3480           auto validate_parent =
3481               ValidateOperandLexicalScope(_, "Parent", inst, 8, ext_inst_name);
3482           if (validate_parent != SPV_SUCCESS) return validate_parent;
3483           if (num_words == 10) CHECK_OPERAND("Name", spv::Op::OpString, 9);
3484           break;
3485         }
3486         case CommonDebugInfoDebugScope: {
3487           auto validate_scope =
3488               ValidateOperandLexicalScope(_, "Scope", inst, 5, ext_inst_name);
3489           if (validate_scope != SPV_SUCCESS) return validate_scope;
3490           if (num_words == 7) {
3491             CHECK_DEBUG_OPERAND("Inlined At", CommonDebugInfoDebugInlinedAt, 6);
3492           }
3493           break;
3494         }
3495         case CommonDebugInfoDebugLocalVariable: {
3496           CHECK_OPERAND("Name", spv::Op::OpString, 5);
3497           // TODO: We need a spec discussion that we have to allow local
3498           // variable types to have template parameter.
3499           auto validate_type =
3500               ValidateOperandDebugType(_, "Type", inst, 6, ext_inst_name, true);
3501           if (validate_type != SPV_SUCCESS) return validate_type;
3502           CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource, 7);
3503           CHECK_CONST_UINT_OPERAND("Line", 8);
3504           CHECK_CONST_UINT_OPERAND("Column", 9);
3505           auto validate_parent =
3506               ValidateOperandLexicalScope(_, "Parent", inst, 10, ext_inst_name);
3507           if (validate_parent != SPV_SUCCESS) return validate_parent;
3508           CHECK_CONST_UINT_OPERAND("Flags", 11);
3509           if (num_words == 13) {
3510             CHECK_CONST_UINT_OPERAND("ArgNumber", 12);
3511           }
3512           break;
3513         }
3514         case CommonDebugInfoDebugDeclare: {
3515           CHECK_DEBUG_OPERAND("Local Variable",
3516                               CommonDebugInfoDebugLocalVariable, 5);
3517           auto* operand = _.FindDef(inst->word(6));
3518           if (operand->opcode() != spv::Op::OpVariable &&
3519               operand->opcode() != spv::Op::OpFunctionParameter) {
3520             return _.diag(SPV_ERROR_INVALID_DATA, inst)
3521                    << ext_inst_name() << ": "
3522                    << "expected operand Variable must be a result id of "
3523                       "OpVariable or OpFunctionParameter";
3524           }
3525 
3526           CHECK_DEBUG_OPERAND("Expression", CommonDebugInfoDebugExpression, 7);
3527 
3528           if (vulkanDebugInfo) {
3529             for (uint32_t word_index = 8; word_index < num_words;
3530                  ++word_index) {
3531               auto index_inst = _.FindDef(inst->word(word_index));
3532               auto type_id = index_inst != nullptr ? index_inst->type_id() : 0;
3533               if (type_id == 0 || !IsIntScalar(_, type_id, false, false))
3534                 return _.diag(SPV_ERROR_INVALID_DATA, inst)
3535                        << ext_inst_name() << ": "
3536                        << "expected index must be scalar integer";
3537             }
3538           }
3539           break;
3540         }
3541         case CommonDebugInfoDebugExpression: {
3542           for (uint32_t word_index = 5; word_index < num_words; ++word_index) {
3543             CHECK_DEBUG_OPERAND("Operation", CommonDebugInfoDebugOperation,
3544                                 word_index);
3545           }
3546           break;
3547         }
3548         case CommonDebugInfoDebugTypeTemplate: {
3549           if (!DoesDebugInfoOperandMatchExpectation(
3550                   _,
3551                   [](CommonDebugInfoInstructions dbg_inst) {
3552                     return dbg_inst == CommonDebugInfoDebugTypeComposite ||
3553                            dbg_inst == CommonDebugInfoDebugFunction;
3554                   },
3555                   inst, 5)) {
3556             return _.diag(SPV_ERROR_INVALID_DATA, inst)
3557                    << ext_inst_name() << ": "
3558                    << "expected operand Target must be DebugTypeComposite "
3559                    << "or DebugFunction";
3560           }
3561           for (uint32_t word_index = 6; word_index < num_words; ++word_index) {
3562             if (!DoesDebugInfoOperandMatchExpectation(
3563                     _,
3564                     [](CommonDebugInfoInstructions dbg_inst) {
3565                       return dbg_inst ==
3566                                  CommonDebugInfoDebugTypeTemplateParameter ||
3567                              dbg_inst ==
3568                                  CommonDebugInfoDebugTypeTemplateTemplateParameter;
3569                     },
3570                     inst, word_index)) {
3571               return _.diag(SPV_ERROR_INVALID_DATA, inst)
3572                      << ext_inst_name() << ": "
3573                      << "expected operand Parameters must be "
3574                      << "DebugTypeTemplateParameter or "
3575                      << "DebugTypeTemplateTemplateParameter";
3576             }
3577           }
3578           break;
3579         }
3580         case CommonDebugInfoDebugTypeTemplateParameter: {
3581           CHECK_OPERAND("Name", spv::Op::OpString, 5);
3582           auto validate_actual_type = ValidateOperandDebugType(
3583               _, "Actual Type", inst, 6, ext_inst_name, false);
3584           if (validate_actual_type != SPV_SUCCESS) return validate_actual_type;
3585           if (!DoesDebugInfoOperandMatchExpectation(
3586                   _,
3587                   [](CommonDebugInfoInstructions dbg_inst) {
3588                     return dbg_inst == CommonDebugInfoDebugInfoNone;
3589                   },
3590                   inst, 7)) {
3591             CHECK_OPERAND("Value", spv::Op::OpConstant, 7);
3592           }
3593           CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource, 8);
3594           CHECK_CONST_UINT_OPERAND("Line", 9);
3595           CHECK_CONST_UINT_OPERAND("Column", 10);
3596           break;
3597         }
3598         case CommonDebugInfoDebugGlobalVariable: {
3599           CHECK_OPERAND("Name", spv::Op::OpString, 5);
3600           auto validate_type = ValidateOperandDebugType(_, "Type", inst, 6,
3601                                                         ext_inst_name, false);
3602           if (validate_type != SPV_SUCCESS) return validate_type;
3603           CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource, 7);
3604           CHECK_CONST_UINT_OPERAND("Line", 8);
3605           CHECK_CONST_UINT_OPERAND("Column", 9);
3606           auto validate_scope =
3607               ValidateOperandLexicalScope(_, "Scope", inst, 10, ext_inst_name);
3608           if (validate_scope != SPV_SUCCESS) return validate_scope;
3609           CHECK_OPERAND("Linkage Name", spv::Op::OpString, 11);
3610           if (!DoesDebugInfoOperandMatchExpectation(
3611                   _,
3612                   [](CommonDebugInfoInstructions dbg_inst) {
3613                     return dbg_inst == CommonDebugInfoDebugInfoNone;
3614                   },
3615                   inst, 12)) {
3616             auto* operand = _.FindDef(inst->word(12));
3617             if (operand->opcode() != spv::Op::OpVariable &&
3618                 operand->opcode() != spv::Op::OpConstant) {
3619               return _.diag(SPV_ERROR_INVALID_DATA, inst)
3620                      << ext_inst_name() << ": "
3621                      << "expected operand Variable must be a result id of "
3622                         "OpVariable or OpConstant or DebugInfoNone";
3623             }
3624           }
3625           if (num_words == 15) {
3626             CHECK_DEBUG_OPERAND("Static Member Declaration",
3627                                 CommonDebugInfoDebugTypeMember, 14);
3628           }
3629           break;
3630         }
3631         case CommonDebugInfoDebugInlinedAt: {
3632           CHECK_CONST_UINT_OPERAND("Line", 5);
3633           auto validate_scope =
3634               ValidateOperandLexicalScope(_, "Scope", inst, 6, ext_inst_name);
3635           if (validate_scope != SPV_SUCCESS) return validate_scope;
3636           if (num_words == 8) {
3637             CHECK_DEBUG_OPERAND("Inlined", CommonDebugInfoDebugInlinedAt, 7);
3638           }
3639           break;
3640         }
3641         case CommonDebugInfoDebugValue: {
3642           CHECK_DEBUG_OPERAND("Local Variable",
3643                               CommonDebugInfoDebugLocalVariable, 5);
3644           CHECK_DEBUG_OPERAND("Expression", CommonDebugInfoDebugExpression, 7);
3645 
3646           for (uint32_t word_index = 8; word_index < num_words; ++word_index) {
3647             // TODO: The following code simply checks if it is a const int
3648             // scalar or a DebugLocalVariable or DebugGlobalVariable, but we
3649             // have to check it using the same validation for Indexes of
3650             // OpAccessChain.
3651             if (!IsConstWithIntScalarType(_, inst, word_index) &&
3652                 !IsDebugVariableWithIntScalarType(_, inst, word_index)) {
3653               return _.diag(SPV_ERROR_INVALID_DATA, inst)
3654                      << ext_inst_name() << ": expected operand Indexes is "
3655                      << "OpConstant, DebugGlobalVariable, or "
3656                      << "type is OpConstant with an integer scalar type";
3657             }
3658           }
3659           break;
3660         }
3661 
3662         // TODO: Add validation rules for remaining cases as well.
3663         case CommonDebugInfoDebugTypePtrToMember:
3664         case CommonDebugInfoDebugTypeTemplateTemplateParameter:
3665         case CommonDebugInfoDebugTypeTemplateParameterPack:
3666         case CommonDebugInfoDebugLexicalBlockDiscriminator:
3667         case CommonDebugInfoDebugInlinedVariable:
3668         case CommonDebugInfoDebugMacroDef:
3669         case CommonDebugInfoDebugMacroUndef:
3670         case CommonDebugInfoDebugImportedEntity:
3671           break;
3672         case CommonDebugInfoInstructionsMax:
3673           assert(0);
3674           break;
3675       }
3676     }
3677   } else if (ext_inst_type == SPV_EXT_INST_TYPE_NONSEMANTIC_CLSPVREFLECTION) {
3678     auto import_inst = _.FindDef(inst->GetOperandAs<uint32_t>(2));
3679     const std::string name = import_inst->GetOperandAs<std::string>(1);
3680     const std::string reflection = "NonSemantic.ClspvReflection.";
3681     char* end_ptr;
3682     auto version_string = name.substr(reflection.size());
3683     if (version_string.empty()) {
3684       return _.diag(SPV_ERROR_INVALID_DATA, import_inst)
3685              << "Missing NonSemantic.ClspvReflection import version";
3686     }
3687     uint32_t version = static_cast<uint32_t>(
3688         std::strtoul(version_string.c_str(), &end_ptr, 10));
3689     if (end_ptr && *end_ptr != '\0') {
3690       return _.diag(SPV_ERROR_INVALID_DATA, import_inst)
3691              << "NonSemantic.ClspvReflection import does not encode the "
3692                 "version correctly";
3693     }
3694     if (version == 0 || version > NonSemanticClspvReflectionRevision) {
3695       return _.diag(SPV_ERROR_INVALID_DATA, import_inst)
3696              << "Unknown NonSemantic.ClspvReflection import version";
3697     }
3698 
3699     return ValidateClspvReflectionInstruction(_, inst, version);
3700   }
3701 
3702   return SPV_SUCCESS;
3703 }
3704 
ExtensionPass(ValidationState_t & _,const Instruction * inst)3705 spv_result_t ExtensionPass(ValidationState_t& _, const Instruction* inst) {
3706   const spv::Op opcode = inst->opcode();
3707   if (opcode == spv::Op::OpExtension) return ValidateExtension(_, inst);
3708   if (opcode == spv::Op::OpExtInstImport) return ValidateExtInstImport(_, inst);
3709   if (opcode == spv::Op::OpExtInst) return ValidateExtInst(_, inst);
3710 
3711   return SPV_SUCCESS;
3712 }
3713 
3714 }  // namespace val
3715 }  // namespace spvtools
3716