• 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 "spirv/unified1/NonSemanticClspvReflection.h"
22 
23 #include "NonSemanticShaderDebugInfo100.h"
24 #include "OpenCLDebugInfo100.h"
25 #include "source/common_debug_info.h"
26 #include "source/diagnostic.h"
27 #include "source/enum_string_mapping.h"
28 #include "source/extensions.h"
29 #include "source/latest_version_glsl_std_450_header.h"
30 #include "source/latest_version_opencl_std_header.h"
31 #include "source/opcode.h"
32 #include "source/spirv_constant.h"
33 #include "source/spirv_target_env.h"
34 #include "source/val/instruction.h"
35 #include "source/val/validate.h"
36 #include "source/val/validation_state.h"
37 
38 namespace spvtools {
39 namespace val {
40 namespace {
41 
GetSizeTBitWidth(const ValidationState_t & _)42 uint32_t GetSizeTBitWidth(const ValidationState_t& _) {
43   if (_.addressing_model() == SpvAddressingModelPhysical32) return 32;
44 
45   if (_.addressing_model() == SpvAddressingModelPhysical64) return 64;
46 
47   return 0;
48 }
49 
IsIntScalar(ValidationState_t & _,uint32_t id,bool must_len32,bool must_unsigned)50 bool IsIntScalar(ValidationState_t& _, uint32_t id, bool must_len32,
51                  bool must_unsigned) {
52   auto type = _.FindDef(id);
53   if (!type || type->opcode() != SpvOpTypeInt) {
54     return false;
55   }
56 
57   if (must_len32 && type->GetOperandAs<uint32_t>(1) != 32) {
58     return false;
59   }
60 
61   return !must_unsigned || type->GetOperandAs<uint32_t>(2) == 0;
62 }
63 
IsUint32Constant(ValidationState_t & _,uint32_t id)64 bool IsUint32Constant(ValidationState_t& _, uint32_t id) {
65   auto inst = _.FindDef(id);
66   if (!inst || inst->opcode() != SpvOpConstant) {
67     return false;
68   }
69 
70   return IsIntScalar(_, inst->type_id(), true, true);
71 }
72 
GetUint32Constant(ValidationState_t & _,uint32_t id)73 uint32_t GetUint32Constant(ValidationState_t& _, uint32_t id) {
74   auto inst = _.FindDef(id);
75   return inst->word(3);
76 }
77 
78 // Check that the operand of a debug info instruction |inst| at |word_index|
79 // is a result id of an instruction with |expected_opcode|.
ValidateOperandForDebugInfo(ValidationState_t & _,const std::string & operand_name,SpvOp expected_opcode,const Instruction * inst,uint32_t word_index,const std::function<std::string ()> & ext_inst_name)80 spv_result_t ValidateOperandForDebugInfo(
81     ValidationState_t& _, const std::string& operand_name,
82     SpvOp expected_opcode, const Instruction* inst, uint32_t word_index,
83     const std::function<std::string()>& ext_inst_name) {
84   auto* operand = _.FindDef(inst->word(word_index));
85   if (operand->opcode() != expected_opcode) {
86     spv_opcode_desc desc = nullptr;
87     if (_.grammar().lookupOpcode(expected_opcode, &desc) != SPV_SUCCESS ||
88         !desc) {
89       return _.diag(SPV_ERROR_INVALID_DATA, inst)
90              << ext_inst_name() << ": "
91              << "expected operand " << operand_name << " is invalid";
92     }
93     return _.diag(SPV_ERROR_INVALID_DATA, inst)
94            << ext_inst_name() << ": "
95            << "expected operand " << operand_name << " must be a result id of "
96            << "Op" << desc->name;
97   }
98   return SPV_SUCCESS;
99 }
100 
101 // For NonSemantic.Shader.DebugInfo.100 check that the operand of a debug info
102 // instruction |inst| at |word_index| is a result id of a 32-bit integer
103 // OpConstant instruction. For OpenCL.DebugInfo.100 the parameter is a literal
104 // 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)105 spv_result_t ValidateUint32ConstantOperandForDebugInfo(
106     ValidationState_t& _, const std::string& operand_name,
107     const Instruction* inst, uint32_t word_index,
108     const std::function<std::string()>& ext_inst_name) {
109   if (!IsUint32Constant(_, inst->word(word_index))) {
110     return _.diag(SPV_ERROR_INVALID_DATA, inst)
111            << ext_inst_name() << ": expected operand " << operand_name
112            << " must be a result id of 32-bit unsigned OpConstant";
113   }
114   return SPV_SUCCESS;
115 }
116 
117 #define CHECK_OPERAND(NAME, opcode, index)                                  \
118   do {                                                                      \
119     auto result = ValidateOperandForDebugInfo(_, NAME, opcode, inst, index, \
120                                               ext_inst_name);               \
121     if (result != SPV_SUCCESS) return result;                               \
122   } while (0)
123 
124 #define CHECK_CONST_UINT_OPERAND(NAME, index)                \
125   if (vulkanDebugInfo) {                                     \
126     auto result = ValidateUint32ConstantOperandForDebugInfo( \
127         _, NAME, inst, index, ext_inst_name);                \
128     if (result != SPV_SUCCESS) return result;                \
129   }
130 
131 // True if the operand of a debug info instruction |inst| at |word_index|
132 // satisfies |expectation| that is given as a function. Otherwise,
133 // returns false.
DoesDebugInfoOperandMatchExpectation(const ValidationState_t & _,const std::function<bool (CommonDebugInfoInstructions)> & expectation,const Instruction * inst,uint32_t word_index)134 bool DoesDebugInfoOperandMatchExpectation(
135     const ValidationState_t& _,
136     const std::function<bool(CommonDebugInfoInstructions)>& expectation,
137     const Instruction* inst, uint32_t word_index) {
138   if (inst->words().size() <= word_index) return false;
139   auto* debug_inst = _.FindDef(inst->word(word_index));
140   if (debug_inst->opcode() != SpvOpExtInst ||
141       (debug_inst->ext_inst_type() != SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100 &&
142        debug_inst->ext_inst_type() !=
143            SPV_EXT_INST_TYPE_NONSEMANTIC_SHADER_DEBUGINFO_100) ||
144       !expectation(CommonDebugInfoInstructions(debug_inst->word(4)))) {
145     return false;
146   }
147   return true;
148 }
149 
150 // Overload for NonSemanticShaderDebugInfo100Instructions.
DoesDebugInfoOperandMatchExpectation(const ValidationState_t & _,const std::function<bool (NonSemanticShaderDebugInfo100Instructions)> & expectation,const Instruction * inst,uint32_t word_index)151 bool DoesDebugInfoOperandMatchExpectation(
152     const ValidationState_t& _,
153     const std::function<bool(NonSemanticShaderDebugInfo100Instructions)>&
154         expectation,
155     const Instruction* inst, uint32_t word_index) {
156   if (inst->words().size() <= word_index) return false;
157   auto* debug_inst = _.FindDef(inst->word(word_index));
158   if (debug_inst->opcode() != SpvOpExtInst ||
159       (debug_inst->ext_inst_type() !=
160        SPV_EXT_INST_TYPE_NONSEMANTIC_SHADER_DEBUGINFO_100) ||
161       !expectation(
162           NonSemanticShaderDebugInfo100Instructions(debug_inst->word(4)))) {
163     return false;
164   }
165   return true;
166 }
167 
168 // Check that the operand of a debug info instruction |inst| at |word_index|
169 // is a result id of an debug info instruction whose debug instruction type
170 // 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)171 spv_result_t ValidateDebugInfoOperand(
172     ValidationState_t& _, const std::string& debug_inst_name,
173     CommonDebugInfoInstructions expected_debug_inst, const Instruction* inst,
174     uint32_t word_index, const std::function<std::string()>& ext_inst_name) {
175   std::function<bool(CommonDebugInfoInstructions)> expectation =
176       [expected_debug_inst](CommonDebugInfoInstructions dbg_inst) {
177         return dbg_inst == expected_debug_inst;
178       };
179   if (DoesDebugInfoOperandMatchExpectation(_, expectation, inst, word_index))
180     return SPV_SUCCESS;
181 
182   spv_ext_inst_desc desc = nullptr;
183   if (_.grammar().lookupExtInst(inst->ext_inst_type(), expected_debug_inst,
184                                 &desc) != SPV_SUCCESS ||
185       !desc) {
186     return _.diag(SPV_ERROR_INVALID_DATA, inst)
187            << ext_inst_name() << ": "
188            << "expected operand " << debug_inst_name << " is invalid";
189   }
190   return _.diag(SPV_ERROR_INVALID_DATA, inst)
191          << ext_inst_name() << ": "
192          << "expected operand " << debug_inst_name << " must be a result id of "
193          << desc->name;
194 }
195 
196 #define CHECK_DEBUG_OPERAND(NAME, debug_opcode, index)                         \
197   do {                                                                         \
198     auto result = ValidateDebugInfoOperand(_, NAME, debug_opcode, inst, index, \
199                                            ext_inst_name);                     \
200     if (result != SPV_SUCCESS) return result;                                  \
201   } while (0)
202 
203 // Check that the operand of a debug info instruction |inst| at |word_index|
204 // 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)205 spv_result_t ValidateOperandBaseType(
206     ValidationState_t& _, const Instruction* inst, uint32_t word_index,
207     const std::function<std::string()>& ext_inst_name) {
208   return ValidateDebugInfoOperand(_, "Base Type", CommonDebugInfoDebugTypeBasic,
209                                   inst, word_index, ext_inst_name);
210 }
211 
212 // Check that the operand of a debug info instruction |inst| at |word_index|
213 // is a result id of a debug lexical scope instruction which is one of
214 // DebugCompilationUnit, DebugFunction, DebugLexicalBlock, or
215 // 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)216 spv_result_t ValidateOperandLexicalScope(
217     ValidationState_t& _, const std::string& debug_inst_name,
218     const Instruction* inst, uint32_t word_index,
219     const std::function<std::string()>& ext_inst_name) {
220   std::function<bool(CommonDebugInfoInstructions)> expectation =
221       [](CommonDebugInfoInstructions dbg_inst) {
222         return dbg_inst == CommonDebugInfoDebugCompilationUnit ||
223                dbg_inst == CommonDebugInfoDebugFunction ||
224                dbg_inst == CommonDebugInfoDebugLexicalBlock ||
225                dbg_inst == CommonDebugInfoDebugTypeComposite;
226       };
227   if (DoesDebugInfoOperandMatchExpectation(_, expectation, inst, word_index))
228     return SPV_SUCCESS;
229 
230   return _.diag(SPV_ERROR_INVALID_DATA, inst)
231          << ext_inst_name() << ": "
232          << "expected operand " << debug_inst_name
233          << " must be a result id of a lexical scope";
234 }
235 
236 // Check that the operand of a debug info instruction |inst| at |word_index|
237 // is a result id of a debug type instruction (See DebugTypeXXX in
238 // "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)239 spv_result_t ValidateOperandDebugType(
240     ValidationState_t& _, const std::string& debug_inst_name,
241     const Instruction* inst, uint32_t word_index,
242     const std::function<std::string()>& ext_inst_name,
243     bool allow_template_param) {
244   // Check for NonSemanticShaderDebugInfo100 specific types.
245   if (inst->ext_inst_type() ==
246       SPV_EXT_INST_TYPE_NONSEMANTIC_SHADER_DEBUGINFO_100) {
247     std::function<bool(NonSemanticShaderDebugInfo100Instructions)> expectation =
248         [](NonSemanticShaderDebugInfo100Instructions dbg_inst) {
249           return dbg_inst == NonSemanticShaderDebugInfo100DebugTypeMatrix;
250         };
251     if (DoesDebugInfoOperandMatchExpectation(_, expectation, inst, word_index))
252       return SPV_SUCCESS;
253   }
254 
255   // Check for common types.
256   std::function<bool(CommonDebugInfoInstructions)> expectation =
257       [&allow_template_param](CommonDebugInfoInstructions dbg_inst) {
258         if (allow_template_param &&
259             (dbg_inst == CommonDebugInfoDebugTypeTemplateParameter ||
260              dbg_inst == CommonDebugInfoDebugTypeTemplateTemplateParameter)) {
261           return true;
262         }
263         return CommonDebugInfoDebugTypeBasic <= dbg_inst &&
264                dbg_inst <= CommonDebugInfoDebugTypeTemplate;
265       };
266   if (DoesDebugInfoOperandMatchExpectation(_, expectation, inst, word_index))
267     return SPV_SUCCESS;
268 
269   return _.diag(SPV_ERROR_INVALID_DATA, inst)
270          << ext_inst_name() << ": "
271          << "expected operand " << debug_inst_name
272          << " is not a valid debug type";
273 }
274 
ValidateClspvReflectionKernel(ValidationState_t & _,const Instruction * inst)275 spv_result_t ValidateClspvReflectionKernel(ValidationState_t& _,
276                                            const Instruction* inst) {
277   const auto kernel_id = inst->GetOperandAs<uint32_t>(4);
278   const auto kernel = _.FindDef(kernel_id);
279   if (kernel->opcode() != SpvOpFunction) {
280     return _.diag(SPV_ERROR_INVALID_ID, inst)
281            << "Kernel does not reference a function";
282   }
283 
284   bool found_kernel = false;
285   for (auto entry_point : _.entry_points()) {
286     if (entry_point == kernel_id) {
287       found_kernel = true;
288       break;
289     }
290   }
291   if (!found_kernel) {
292     return _.diag(SPV_ERROR_INVALID_ID, inst)
293            << "Kernel does not reference an entry-point";
294   }
295 
296   const auto* exec_models = _.GetExecutionModels(kernel_id);
297   if (!exec_models || exec_models->empty()) {
298     return _.diag(SPV_ERROR_INVALID_ID, inst)
299            << "Kernel does not reference an entry-point";
300   }
301   for (auto exec_model : *exec_models) {
302     if (exec_model != SpvExecutionModelGLCompute) {
303       return _.diag(SPV_ERROR_INVALID_ID, inst)
304              << "Kernel must refer only to GLCompute entry-points";
305     }
306   }
307 
308   auto name = _.FindDef(inst->GetOperandAs<uint32_t>(5));
309   if (!name || name->opcode() != SpvOpString) {
310     return _.diag(SPV_ERROR_INVALID_ID, inst) << "Name must be an OpString";
311   }
312 
313   const std::string name_str = name->GetOperandAs<std::string>(1);
314   bool found = false;
315   for (auto& desc : _.entry_point_descriptions(kernel_id)) {
316     if (name_str == desc.name) {
317       found = true;
318       break;
319     }
320   }
321   if (!found) {
322     return _.diag(SPV_ERROR_INVALID_ID, inst)
323            << "Name must match an entry-point for Kernel";
324   }
325 
326   return SPV_SUCCESS;
327 }
328 
ValidateClspvReflectionArgumentInfo(ValidationState_t & _,const Instruction * inst)329 spv_result_t ValidateClspvReflectionArgumentInfo(ValidationState_t& _,
330                                                  const Instruction* inst) {
331   const auto num_operands = inst->operands().size();
332   if (_.GetIdOpcode(inst->GetOperandAs<uint32_t>(4)) != SpvOpString) {
333     return _.diag(SPV_ERROR_INVALID_ID, inst) << "Name must be an OpString";
334   }
335   if (num_operands > 5) {
336     if (_.GetIdOpcode(inst->GetOperandAs<uint32_t>(5)) != SpvOpString) {
337       return _.diag(SPV_ERROR_INVALID_ID, inst)
338              << "TypeName must be an OpString";
339     }
340   }
341   if (num_operands > 6) {
342     if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(6))) {
343       return _.diag(SPV_ERROR_INVALID_ID, inst)
344              << "AddressQualifier must be a 32-bit unsigned integer "
345                 "OpConstant";
346     }
347   }
348   if (num_operands > 7) {
349     if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(7))) {
350       return _.diag(SPV_ERROR_INVALID_ID, inst)
351              << "AccessQualifier must be a 32-bit unsigned integer "
352                 "OpConstant";
353     }
354   }
355   if (num_operands > 8) {
356     if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(8))) {
357       return _.diag(SPV_ERROR_INVALID_ID, inst)
358              << "TypeQualifier must be a 32-bit unsigned integer "
359                 "OpConstant";
360     }
361   }
362 
363   return SPV_SUCCESS;
364 }
365 
ValidateKernelDecl(ValidationState_t & _,const Instruction * inst)366 spv_result_t ValidateKernelDecl(ValidationState_t& _, const Instruction* inst) {
367   const auto decl_id = inst->GetOperandAs<uint32_t>(4);
368   const auto decl = _.FindDef(decl_id);
369   if (!decl || decl->opcode() != SpvOpExtInst) {
370     return _.diag(SPV_ERROR_INVALID_ID, inst)
371            << "Kernel must be a Kernel extended instruction";
372   }
373 
374   if (decl->GetOperandAs<uint32_t>(2) != inst->GetOperandAs<uint32_t>(2)) {
375     return _.diag(SPV_ERROR_INVALID_ID, inst)
376            << "Kernel must be from the same extended instruction import";
377   }
378 
379   const auto ext_inst =
380       decl->GetOperandAs<NonSemanticClspvReflectionInstructions>(3);
381   if (ext_inst != NonSemanticClspvReflectionKernel) {
382     return _.diag(SPV_ERROR_INVALID_ID, inst)
383            << "Kernel must be a Kernel extended instruction";
384   }
385 
386   return SPV_SUCCESS;
387 }
388 
ValidateArgInfo(ValidationState_t & _,const Instruction * inst,uint32_t info_index)389 spv_result_t ValidateArgInfo(ValidationState_t& _, const Instruction* inst,
390                              uint32_t info_index) {
391   auto info = _.FindDef(inst->GetOperandAs<uint32_t>(info_index));
392   if (!info || info->opcode() != SpvOpExtInst) {
393     return _.diag(SPV_ERROR_INVALID_ID, inst)
394            << "ArgInfo must be an ArgumentInfo extended instruction";
395   }
396 
397   if (info->GetOperandAs<uint32_t>(2) != inst->GetOperandAs<uint32_t>(2)) {
398     return _.diag(SPV_ERROR_INVALID_ID, inst)
399            << "ArgInfo must be from the same extended instruction import";
400   }
401 
402   auto ext_inst = info->GetOperandAs<NonSemanticClspvReflectionInstructions>(3);
403   if (ext_inst != NonSemanticClspvReflectionArgumentInfo) {
404     return _.diag(SPV_ERROR_INVALID_ID, inst)
405            << "ArgInfo must be an ArgumentInfo extended instruction";
406   }
407 
408   return SPV_SUCCESS;
409 }
410 
ValidateClspvReflectionArgumentBuffer(ValidationState_t & _,const Instruction * inst)411 spv_result_t ValidateClspvReflectionArgumentBuffer(ValidationState_t& _,
412                                                    const Instruction* inst) {
413   const auto num_operands = inst->operands().size();
414   if (auto error = ValidateKernelDecl(_, inst)) {
415     return error;
416   }
417 
418   if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(5))) {
419     return _.diag(SPV_ERROR_INVALID_ID, inst)
420            << "Ordinal must be a 32-bit unsigned integer OpConstant";
421   }
422 
423   if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(6))) {
424     return _.diag(SPV_ERROR_INVALID_ID, inst)
425            << "DescriptorSet must be a 32-bit unsigned integer OpConstant";
426   }
427 
428   if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(7))) {
429     return _.diag(SPV_ERROR_INVALID_ID, inst)
430            << "Binding must be a 32-bit unsigned integer OpConstant";
431   }
432 
433   if (num_operands == 9) {
434     if (auto error = ValidateArgInfo(_, inst, 8)) {
435       return error;
436     }
437   }
438 
439   return SPV_SUCCESS;
440 }
441 
ValidateClspvReflectionArgumentPodBuffer(ValidationState_t & _,const Instruction * inst)442 spv_result_t ValidateClspvReflectionArgumentPodBuffer(ValidationState_t& _,
443                                                       const Instruction* inst) {
444   const auto num_operands = inst->operands().size();
445   if (auto error = ValidateKernelDecl(_, inst)) {
446     return error;
447   }
448 
449   if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(5))) {
450     return _.diag(SPV_ERROR_INVALID_ID, inst)
451            << "Ordinal must be a 32-bit unsigned integer OpConstant";
452   }
453 
454   if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(6))) {
455     return _.diag(SPV_ERROR_INVALID_ID, inst)
456            << "DescriptorSet must be a 32-bit unsigned integer OpConstant";
457   }
458 
459   if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(7))) {
460     return _.diag(SPV_ERROR_INVALID_ID, inst)
461            << "Binding must be a 32-bit unsigned integer OpConstant";
462   }
463 
464   if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(8))) {
465     return _.diag(SPV_ERROR_INVALID_ID, inst)
466            << "Offset must be a 32-bit unsigned integer OpConstant";
467   }
468 
469   if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(9))) {
470     return _.diag(SPV_ERROR_INVALID_ID, inst)
471            << "Size must be a 32-bit unsigned integer OpConstant";
472   }
473 
474   if (num_operands == 11) {
475     if (auto error = ValidateArgInfo(_, inst, 10)) {
476       return error;
477     }
478   }
479 
480   return SPV_SUCCESS;
481 }
482 
ValidateClspvReflectionArgumentPodPushConstant(ValidationState_t & _,const Instruction * inst)483 spv_result_t ValidateClspvReflectionArgumentPodPushConstant(
484     ValidationState_t& _, const Instruction* inst) {
485   const auto num_operands = inst->operands().size();
486   if (auto error = ValidateKernelDecl(_, inst)) {
487     return error;
488   }
489 
490   if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(5))) {
491     return _.diag(SPV_ERROR_INVALID_ID, inst)
492            << "Ordinal must be a 32-bit unsigned integer OpConstant";
493   }
494 
495   if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(6))) {
496     return _.diag(SPV_ERROR_INVALID_ID, inst)
497            << "Offset must be a 32-bit unsigned integer OpConstant";
498   }
499 
500   if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(7))) {
501     return _.diag(SPV_ERROR_INVALID_ID, inst)
502            << "Size must be a 32-bit unsigned integer OpConstant";
503   }
504 
505   if (num_operands == 9) {
506     if (auto error = ValidateArgInfo(_, inst, 8)) {
507       return error;
508     }
509   }
510 
511   return SPV_SUCCESS;
512 }
513 
ValidateClspvReflectionArgumentWorkgroup(ValidationState_t & _,const Instruction * inst)514 spv_result_t ValidateClspvReflectionArgumentWorkgroup(ValidationState_t& _,
515                                                       const Instruction* inst) {
516   const auto num_operands = inst->operands().size();
517   if (auto error = ValidateKernelDecl(_, inst)) {
518     return error;
519   }
520 
521   if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(5))) {
522     return _.diag(SPV_ERROR_INVALID_ID, inst)
523            << "Ordinal must be a 32-bit unsigned integer OpConstant";
524   }
525 
526   if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(6))) {
527     return _.diag(SPV_ERROR_INVALID_ID, inst)
528            << "SpecId must be a 32-bit unsigned integer OpConstant";
529   }
530 
531   if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(7))) {
532     return _.diag(SPV_ERROR_INVALID_ID, inst)
533            << "ElemSize must be a 32-bit unsigned integer OpConstant";
534   }
535 
536   if (num_operands == 9) {
537     if (auto error = ValidateArgInfo(_, inst, 8)) {
538       return error;
539     }
540   }
541 
542   return SPV_SUCCESS;
543 }
544 
ValidateClspvReflectionSpecConstantTriple(ValidationState_t & _,const Instruction * inst)545 spv_result_t ValidateClspvReflectionSpecConstantTriple(
546     ValidationState_t& _, const Instruction* inst) {
547   if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(4))) {
548     return _.diag(SPV_ERROR_INVALID_ID, inst)
549            << "X must be a 32-bit unsigned integer OpConstant";
550   }
551 
552   if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(5))) {
553     return _.diag(SPV_ERROR_INVALID_ID, inst)
554            << "Y must be a 32-bit unsigned integer OpConstant";
555   }
556 
557   if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(6))) {
558     return _.diag(SPV_ERROR_INVALID_ID, inst)
559            << "Z must be a 32-bit unsigned integer OpConstant";
560   }
561 
562   return SPV_SUCCESS;
563 }
564 
ValidateClspvReflectionSpecConstantWorkDim(ValidationState_t & _,const Instruction * inst)565 spv_result_t ValidateClspvReflectionSpecConstantWorkDim(
566     ValidationState_t& _, const Instruction* inst) {
567   if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(4))) {
568     return _.diag(SPV_ERROR_INVALID_ID, inst)
569            << "Dim must be a 32-bit unsigned integer OpConstant";
570   }
571 
572   return SPV_SUCCESS;
573 }
574 
ValidateClspvReflectionPushConstant(ValidationState_t & _,const Instruction * inst)575 spv_result_t ValidateClspvReflectionPushConstant(ValidationState_t& _,
576                                                  const Instruction* inst) {
577   if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(4))) {
578     return _.diag(SPV_ERROR_INVALID_ID, inst)
579            << "Offset must be a 32-bit unsigned integer OpConstant";
580   }
581 
582   if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(5))) {
583     return _.diag(SPV_ERROR_INVALID_ID, inst)
584            << "Size must be a 32-bit unsigned integer OpConstant";
585   }
586 
587   return SPV_SUCCESS;
588 }
589 
ValidateClspvReflectionConstantData(ValidationState_t & _,const Instruction * inst)590 spv_result_t ValidateClspvReflectionConstantData(ValidationState_t& _,
591                                                  const Instruction* inst) {
592   if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(4))) {
593     return _.diag(SPV_ERROR_INVALID_ID, inst)
594            << "DescriptorSet must be a 32-bit unsigned integer OpConstant";
595   }
596 
597   if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(5))) {
598     return _.diag(SPV_ERROR_INVALID_ID, inst)
599            << "Binding must be a 32-bit unsigned integer OpConstant";
600   }
601 
602   if (_.GetIdOpcode(inst->GetOperandAs<uint32_t>(6)) != SpvOpString) {
603     return _.diag(SPV_ERROR_INVALID_ID, inst) << "Data must be an OpString";
604   }
605 
606   return SPV_SUCCESS;
607 }
608 
ValidateClspvReflectionSampler(ValidationState_t & _,const Instruction * inst)609 spv_result_t ValidateClspvReflectionSampler(ValidationState_t& _,
610                                             const Instruction* inst) {
611   if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(4))) {
612     return _.diag(SPV_ERROR_INVALID_ID, inst)
613            << "DescriptorSet must be a 32-bit unsigned integer OpConstant";
614   }
615 
616   if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(5))) {
617     return _.diag(SPV_ERROR_INVALID_ID, inst)
618            << "Binding must be a 32-bit unsigned integer OpConstant";
619   }
620 
621   if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(6))) {
622     return _.diag(SPV_ERROR_INVALID_ID, inst)
623            << "Mask must be a 32-bit unsigned integer OpConstant";
624   }
625 
626   return SPV_SUCCESS;
627 }
628 
ValidateClspvReflectionPropertyRequiredWorkgroupSize(ValidationState_t & _,const Instruction * inst)629 spv_result_t ValidateClspvReflectionPropertyRequiredWorkgroupSize(
630     ValidationState_t& _, const Instruction* inst) {
631   if (auto error = ValidateKernelDecl(_, inst)) {
632     return error;
633   }
634 
635   if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(5))) {
636     return _.diag(SPV_ERROR_INVALID_ID, inst)
637            << "X must be a 32-bit unsigned integer OpConstant";
638   }
639 
640   if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(6))) {
641     return _.diag(SPV_ERROR_INVALID_ID, inst)
642            << "Y must be a 32-bit unsigned integer OpConstant";
643   }
644 
645   if (!IsUint32Constant(_, inst->GetOperandAs<uint32_t>(7))) {
646     return _.diag(SPV_ERROR_INVALID_ID, inst)
647            << "Z must be a 32-bit unsigned integer OpConstant";
648   }
649 
650   return SPV_SUCCESS;
651 }
652 
ValidateClspvReflectionInstruction(ValidationState_t & _,const Instruction * inst,uint32_t)653 spv_result_t ValidateClspvReflectionInstruction(ValidationState_t& _,
654                                                 const Instruction* inst,
655                                                 uint32_t /*version*/) {
656   if (!_.IsVoidType(inst->type_id())) {
657     return _.diag(SPV_ERROR_INVALID_ID, inst)
658            << "Return Type must be OpTypeVoid";
659   }
660 
661   auto ext_inst = inst->GetOperandAs<NonSemanticClspvReflectionInstructions>(3);
662   switch (ext_inst) {
663     case NonSemanticClspvReflectionKernel:
664       return ValidateClspvReflectionKernel(_, inst);
665     case NonSemanticClspvReflectionArgumentInfo:
666       return ValidateClspvReflectionArgumentInfo(_, inst);
667     case NonSemanticClspvReflectionArgumentStorageBuffer:
668     case NonSemanticClspvReflectionArgumentUniform:
669     case NonSemanticClspvReflectionArgumentSampledImage:
670     case NonSemanticClspvReflectionArgumentStorageImage:
671     case NonSemanticClspvReflectionArgumentSampler:
672       return ValidateClspvReflectionArgumentBuffer(_, inst);
673     case NonSemanticClspvReflectionArgumentPodStorageBuffer:
674     case NonSemanticClspvReflectionArgumentPodUniform:
675       return ValidateClspvReflectionArgumentPodBuffer(_, inst);
676     case NonSemanticClspvReflectionArgumentPodPushConstant:
677       return ValidateClspvReflectionArgumentPodPushConstant(_, inst);
678     case NonSemanticClspvReflectionArgumentWorkgroup:
679       return ValidateClspvReflectionArgumentWorkgroup(_, inst);
680     case NonSemanticClspvReflectionSpecConstantWorkgroupSize:
681     case NonSemanticClspvReflectionSpecConstantGlobalOffset:
682       return ValidateClspvReflectionSpecConstantTriple(_, inst);
683     case NonSemanticClspvReflectionSpecConstantWorkDim:
684       return ValidateClspvReflectionSpecConstantWorkDim(_, inst);
685     case NonSemanticClspvReflectionPushConstantGlobalOffset:
686     case NonSemanticClspvReflectionPushConstantEnqueuedLocalSize:
687     case NonSemanticClspvReflectionPushConstantGlobalSize:
688     case NonSemanticClspvReflectionPushConstantRegionOffset:
689     case NonSemanticClspvReflectionPushConstantNumWorkgroups:
690     case NonSemanticClspvReflectionPushConstantRegionGroupOffset:
691       return ValidateClspvReflectionPushConstant(_, inst);
692     case NonSemanticClspvReflectionConstantDataStorageBuffer:
693     case NonSemanticClspvReflectionConstantDataUniform:
694       return ValidateClspvReflectionConstantData(_, inst);
695     case NonSemanticClspvReflectionLiteralSampler:
696       return ValidateClspvReflectionSampler(_, inst);
697     case NonSemanticClspvReflectionPropertyRequiredWorkgroupSize:
698       return ValidateClspvReflectionPropertyRequiredWorkgroupSize(_, inst);
699     default:
700       break;
701   }
702 
703   return SPV_SUCCESS;
704 }
705 
IsConstIntScalarTypeWith32Or64Bits(ValidationState_t & _,Instruction * instr)706 bool IsConstIntScalarTypeWith32Or64Bits(ValidationState_t& _,
707                                         Instruction* instr) {
708   if (instr->opcode() != SpvOpConstant) return false;
709   if (!_.IsIntScalarType(instr->type_id())) return false;
710   uint32_t size_in_bits = _.GetBitWidth(instr->type_id());
711   return size_in_bits == 32 || size_in_bits == 64;
712 }
713 
IsConstWithIntScalarType(ValidationState_t & _,const Instruction * inst,uint32_t word_index)714 bool IsConstWithIntScalarType(ValidationState_t& _, const Instruction* inst,
715                               uint32_t word_index) {
716   auto* int_scalar_const = _.FindDef(inst->word(word_index));
717   if (int_scalar_const->opcode() == SpvOpConstant &&
718       _.IsIntScalarType(int_scalar_const->type_id())) {
719     return true;
720   }
721   return false;
722 }
723 
IsDebugVariableWithIntScalarType(ValidationState_t & _,const Instruction * inst,uint32_t word_index)724 bool IsDebugVariableWithIntScalarType(ValidationState_t& _,
725                                       const Instruction* inst,
726                                       uint32_t word_index) {
727   auto* dbg_int_scalar_var = _.FindDef(inst->word(word_index));
728   if (CommonDebugInfoInstructions(dbg_int_scalar_var->word(4)) ==
729           CommonDebugInfoDebugLocalVariable ||
730       CommonDebugInfoInstructions(dbg_int_scalar_var->word(4)) ==
731           CommonDebugInfoDebugGlobalVariable) {
732     auto* dbg_type = _.FindDef(dbg_int_scalar_var->word(6));
733     if (CommonDebugInfoInstructions(dbg_type->word(4)) ==
734         CommonDebugInfoDebugTypeBasic) {
735       const spv_ext_inst_type_t ext_inst_type =
736           spv_ext_inst_type_t(inst->ext_inst_type());
737       const bool vulkanDebugInfo =
738           ext_inst_type == SPV_EXT_INST_TYPE_NONSEMANTIC_SHADER_DEBUGINFO_100;
739       uint32_t encoding = dbg_type->word(7);
740       if (!vulkanDebugInfo || IsUint32Constant(_, encoding)) {
741         auto ocl_encoding = OpenCLDebugInfo100DebugBaseTypeAttributeEncoding(
742             vulkanDebugInfo ? GetUint32Constant(_, encoding) : encoding);
743         if (ocl_encoding == OpenCLDebugInfo100Signed ||
744             ocl_encoding == OpenCLDebugInfo100Unsigned) {
745           return true;
746         }
747       }
748     }
749   }
750   return false;
751 }
752 
753 }  // anonymous namespace
754 
ValidateExtension(ValidationState_t & _,const Instruction * inst)755 spv_result_t ValidateExtension(ValidationState_t& _, const Instruction* inst) {
756   if (_.version() < SPV_SPIRV_VERSION_WORD(1, 4)) {
757     std::string extension = GetExtensionString(&(inst->c_inst()));
758     if (extension ==
759             ExtensionToString(kSPV_KHR_workgroup_memory_explicit_layout) ||
760         extension == ExtensionToString(kSPV_EXT_mesh_shader)) {
761       return _.diag(SPV_ERROR_WRONG_VERSION, inst)
762              << extension << " extension requires SPIR-V version 1.4 or later.";
763     }
764   }
765 
766   return SPV_SUCCESS;
767 }
768 
ValidateExtInstImport(ValidationState_t & _,const Instruction * inst)769 spv_result_t ValidateExtInstImport(ValidationState_t& _,
770                                    const Instruction* inst) {
771   const auto name_id = 1;
772   if (_.version() <= SPV_SPIRV_VERSION_WORD(1, 5) &&
773       !_.HasExtension(kSPV_KHR_non_semantic_info)) {
774     const std::string name = inst->GetOperandAs<std::string>(name_id);
775     if (name.find("NonSemantic.") == 0) {
776       return _.diag(SPV_ERROR_INVALID_DATA, inst)
777              << "NonSemantic extended instruction sets cannot be declared "
778                 "without SPV_KHR_non_semantic_info.";
779     }
780   }
781 
782   return SPV_SUCCESS;
783 }
784 
ValidateExtInst(ValidationState_t & _,const Instruction * inst)785 spv_result_t ValidateExtInst(ValidationState_t& _, const Instruction* inst) {
786   const uint32_t result_type = inst->type_id();
787   const uint32_t num_operands = static_cast<uint32_t>(inst->operands().size());
788 
789   const uint32_t ext_inst_set = inst->word(3);
790   const uint32_t ext_inst_index = inst->word(4);
791   const spv_ext_inst_type_t ext_inst_type =
792       spv_ext_inst_type_t(inst->ext_inst_type());
793 
794   auto ext_inst_name = [&_, ext_inst_set, ext_inst_type, ext_inst_index]() {
795     spv_ext_inst_desc desc = nullptr;
796     if (_.grammar().lookupExtInst(ext_inst_type, ext_inst_index, &desc) !=
797             SPV_SUCCESS ||
798         !desc) {
799       return std::string("Unknown ExtInst");
800     }
801 
802     auto* import_inst = _.FindDef(ext_inst_set);
803     assert(import_inst);
804 
805     std::ostringstream ss;
806     ss << import_inst->GetOperandAs<std::string>(1);
807     ss << " ";
808     ss << desc->name;
809 
810     return ss.str();
811   };
812 
813   if (ext_inst_type == SPV_EXT_INST_TYPE_GLSL_STD_450) {
814     const GLSLstd450 ext_inst_key = GLSLstd450(ext_inst_index);
815     switch (ext_inst_key) {
816       case GLSLstd450Round:
817       case GLSLstd450RoundEven:
818       case GLSLstd450FAbs:
819       case GLSLstd450Trunc:
820       case GLSLstd450FSign:
821       case GLSLstd450Floor:
822       case GLSLstd450Ceil:
823       case GLSLstd450Fract:
824       case GLSLstd450Sqrt:
825       case GLSLstd450InverseSqrt:
826       case GLSLstd450FMin:
827       case GLSLstd450FMax:
828       case GLSLstd450FClamp:
829       case GLSLstd450FMix:
830       case GLSLstd450Step:
831       case GLSLstd450SmoothStep:
832       case GLSLstd450Fma:
833       case GLSLstd450Normalize:
834       case GLSLstd450FaceForward:
835       case GLSLstd450Reflect:
836       case GLSLstd450NMin:
837       case GLSLstd450NMax:
838       case GLSLstd450NClamp: {
839         if (!_.IsFloatScalarOrVectorType(result_type)) {
840           return _.diag(SPV_ERROR_INVALID_DATA, inst)
841                  << ext_inst_name() << ": "
842                  << "expected Result Type to be a float scalar or vector type";
843         }
844 
845         for (uint32_t operand_index = 4; operand_index < num_operands;
846              ++operand_index) {
847           const uint32_t operand_type = _.GetOperandTypeId(inst, operand_index);
848           if (result_type != operand_type) {
849             return _.diag(SPV_ERROR_INVALID_DATA, inst)
850                    << ext_inst_name() << ": "
851                    << "expected types of all operands to be equal to Result "
852                       "Type";
853           }
854         }
855         break;
856       }
857 
858       case GLSLstd450SAbs:
859       case GLSLstd450SSign:
860       case GLSLstd450UMin:
861       case GLSLstd450SMin:
862       case GLSLstd450UMax:
863       case GLSLstd450SMax:
864       case GLSLstd450UClamp:
865       case GLSLstd450SClamp:
866       case GLSLstd450FindILsb:
867       case GLSLstd450FindUMsb:
868       case GLSLstd450FindSMsb: {
869         if (!_.IsIntScalarOrVectorType(result_type)) {
870           return _.diag(SPV_ERROR_INVALID_DATA, inst)
871                  << ext_inst_name() << ": "
872                  << "expected Result Type to be an int scalar or vector type";
873         }
874 
875         const uint32_t result_type_bit_width = _.GetBitWidth(result_type);
876         const uint32_t result_type_dimension = _.GetDimension(result_type);
877 
878         for (uint32_t operand_index = 4; operand_index < num_operands;
879              ++operand_index) {
880           const uint32_t operand_type = _.GetOperandTypeId(inst, operand_index);
881           if (!operand_type || !_.IsIntScalarOrVectorType(operand_type)) {
882             return _.diag(SPV_ERROR_INVALID_DATA, inst)
883                    << ext_inst_name() << ": "
884                    << "expected all operands to be int scalars or vectors";
885           }
886 
887           if (result_type_dimension != _.GetDimension(operand_type)) {
888             return _.diag(SPV_ERROR_INVALID_DATA, inst)
889                    << ext_inst_name() << ": "
890                    << "expected all operands to have the same dimension as "
891                    << "Result Type";
892           }
893 
894           if (result_type_bit_width != _.GetBitWidth(operand_type)) {
895             return _.diag(SPV_ERROR_INVALID_DATA, inst)
896                    << ext_inst_name() << ": "
897                    << "expected all operands to have the same bit width as "
898                    << "Result Type";
899           }
900 
901           if (ext_inst_key == GLSLstd450FindUMsb ||
902               ext_inst_key == GLSLstd450FindSMsb) {
903             if (result_type_bit_width != 32) {
904               return _.diag(SPV_ERROR_INVALID_DATA, inst)
905                      << ext_inst_name() << ": "
906                      << "this instruction is currently limited to 32-bit width "
907                      << "components";
908             }
909           }
910         }
911         break;
912       }
913 
914       case GLSLstd450Radians:
915       case GLSLstd450Degrees:
916       case GLSLstd450Sin:
917       case GLSLstd450Cos:
918       case GLSLstd450Tan:
919       case GLSLstd450Asin:
920       case GLSLstd450Acos:
921       case GLSLstd450Atan:
922       case GLSLstd450Sinh:
923       case GLSLstd450Cosh:
924       case GLSLstd450Tanh:
925       case GLSLstd450Asinh:
926       case GLSLstd450Acosh:
927       case GLSLstd450Atanh:
928       case GLSLstd450Exp:
929       case GLSLstd450Exp2:
930       case GLSLstd450Log:
931       case GLSLstd450Log2:
932       case GLSLstd450Atan2:
933       case GLSLstd450Pow: {
934         if (!_.IsFloatScalarOrVectorType(result_type)) {
935           return _.diag(SPV_ERROR_INVALID_DATA, inst)
936                  << ext_inst_name() << ": "
937                  << "expected Result Type to be a 16 or 32-bit scalar or "
938                     "vector float type";
939         }
940 
941         const uint32_t result_type_bit_width = _.GetBitWidth(result_type);
942         if (result_type_bit_width != 16 && result_type_bit_width != 32) {
943           return _.diag(SPV_ERROR_INVALID_DATA, inst)
944                  << ext_inst_name() << ": "
945                  << "expected Result Type to be a 16 or 32-bit scalar or "
946                     "vector float type";
947         }
948 
949         for (uint32_t operand_index = 4; operand_index < num_operands;
950              ++operand_index) {
951           const uint32_t operand_type = _.GetOperandTypeId(inst, operand_index);
952           if (result_type != operand_type) {
953             return _.diag(SPV_ERROR_INVALID_DATA, inst)
954                    << ext_inst_name() << ": "
955                    << "expected types of all operands to be equal to Result "
956                       "Type";
957           }
958         }
959         break;
960       }
961 
962       case GLSLstd450Determinant: {
963         const uint32_t x_type = _.GetOperandTypeId(inst, 4);
964         uint32_t num_rows = 0;
965         uint32_t num_cols = 0;
966         uint32_t col_type = 0;
967         uint32_t component_type = 0;
968         if (!_.GetMatrixTypeInfo(x_type, &num_rows, &num_cols, &col_type,
969                                  &component_type) ||
970             num_rows != num_cols) {
971           return _.diag(SPV_ERROR_INVALID_DATA, inst)
972                  << ext_inst_name() << ": "
973                  << "expected operand X to be a square matrix";
974         }
975 
976         if (result_type != component_type) {
977           return _.diag(SPV_ERROR_INVALID_DATA, inst)
978                  << ext_inst_name() << ": "
979                  << "expected operand X component type to be equal to "
980                  << "Result Type";
981         }
982         break;
983       }
984 
985       case GLSLstd450MatrixInverse: {
986         uint32_t num_rows = 0;
987         uint32_t num_cols = 0;
988         uint32_t col_type = 0;
989         uint32_t component_type = 0;
990         if (!_.GetMatrixTypeInfo(result_type, &num_rows, &num_cols, &col_type,
991                                  &component_type) ||
992             num_rows != num_cols) {
993           return _.diag(SPV_ERROR_INVALID_DATA, inst)
994                  << ext_inst_name() << ": "
995                  << "expected Result Type to be a square matrix";
996         }
997 
998         const uint32_t x_type = _.GetOperandTypeId(inst, 4);
999         if (result_type != x_type) {
1000           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1001                  << ext_inst_name() << ": "
1002                  << "expected operand X type to be equal to Result Type";
1003         }
1004         break;
1005       }
1006 
1007       case GLSLstd450Modf: {
1008         if (!_.IsFloatScalarOrVectorType(result_type)) {
1009           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1010                  << ext_inst_name() << ": "
1011                  << "expected Result Type to be a scalar or vector float type";
1012         }
1013 
1014         const uint32_t x_type = _.GetOperandTypeId(inst, 4);
1015         const uint32_t i_type = _.GetOperandTypeId(inst, 5);
1016 
1017         if (x_type != result_type) {
1018           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1019                  << ext_inst_name() << ": "
1020                  << "expected operand X type to be equal to Result Type";
1021         }
1022 
1023         uint32_t i_storage_class = 0;
1024         uint32_t i_data_type = 0;
1025         if (!_.GetPointerTypeInfo(i_type, &i_data_type, &i_storage_class)) {
1026           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1027                  << ext_inst_name() << ": "
1028                  << "expected operand I to be a pointer";
1029         }
1030 
1031         if (i_data_type != result_type) {
1032           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1033                  << ext_inst_name() << ": "
1034                  << "expected operand I data type to be equal to Result Type";
1035         }
1036 
1037         break;
1038       }
1039 
1040       case GLSLstd450ModfStruct: {
1041         std::vector<uint32_t> result_types;
1042         if (!_.GetStructMemberTypes(result_type, &result_types) ||
1043             result_types.size() != 2 ||
1044             !_.IsFloatScalarOrVectorType(result_types[0]) ||
1045             result_types[1] != result_types[0]) {
1046           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1047                  << ext_inst_name() << ": "
1048                  << "expected Result Type to be a struct with two identical "
1049                  << "scalar or vector float type members";
1050         }
1051 
1052         const uint32_t x_type = _.GetOperandTypeId(inst, 4);
1053         if (x_type != result_types[0]) {
1054           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1055                  << ext_inst_name() << ": "
1056                  << "expected operand X type to be equal to members of "
1057                  << "Result Type struct";
1058         }
1059         break;
1060       }
1061 
1062       case GLSLstd450Frexp: {
1063         if (!_.IsFloatScalarOrVectorType(result_type)) {
1064           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1065                  << ext_inst_name() << ": "
1066                  << "expected Result Type to be a scalar or vector float type";
1067         }
1068 
1069         const uint32_t x_type = _.GetOperandTypeId(inst, 4);
1070         const uint32_t exp_type = _.GetOperandTypeId(inst, 5);
1071 
1072         if (x_type != result_type) {
1073           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1074                  << ext_inst_name() << ": "
1075                  << "expected operand X type to be equal to Result Type";
1076         }
1077 
1078         uint32_t exp_storage_class = 0;
1079         uint32_t exp_data_type = 0;
1080         if (!_.GetPointerTypeInfo(exp_type, &exp_data_type,
1081                                   &exp_storage_class)) {
1082           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1083                  << ext_inst_name() << ": "
1084                  << "expected operand Exp to be a pointer";
1085         }
1086 
1087         if (!_.IsIntScalarOrVectorType(exp_data_type) ||
1088             (!_.HasExtension(kSPV_AMD_gpu_shader_int16) &&
1089              _.GetBitWidth(exp_data_type) != 32) ||
1090             (_.HasExtension(kSPV_AMD_gpu_shader_int16) &&
1091              _.GetBitWidth(exp_data_type) != 16 &&
1092              _.GetBitWidth(exp_data_type) != 32)) {
1093           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1094                  << ext_inst_name() << ": "
1095                  << "expected operand Exp data type to be a "
1096                  << (_.HasExtension(kSPV_AMD_gpu_shader_int16)
1097                          ? "16-bit or 32-bit "
1098                          : "32-bit ")
1099                  << "int scalar or vector type";
1100         }
1101 
1102         if (_.GetDimension(result_type) != _.GetDimension(exp_data_type)) {
1103           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1104                  << ext_inst_name() << ": "
1105                  << "expected operand Exp data type to have the same component "
1106                  << "number as Result Type";
1107         }
1108 
1109         break;
1110       }
1111 
1112       case GLSLstd450Ldexp: {
1113         if (!_.IsFloatScalarOrVectorType(result_type)) {
1114           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1115                  << ext_inst_name() << ": "
1116                  << "expected Result Type to be a scalar or vector float type";
1117         }
1118 
1119         const uint32_t x_type = _.GetOperandTypeId(inst, 4);
1120         const uint32_t exp_type = _.GetOperandTypeId(inst, 5);
1121 
1122         if (x_type != result_type) {
1123           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1124                  << ext_inst_name() << ": "
1125                  << "expected operand X type to be equal to Result Type";
1126         }
1127 
1128         if (!_.IsIntScalarOrVectorType(exp_type)) {
1129           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1130                  << ext_inst_name() << ": "
1131                  << "expected operand Exp to be a 32-bit int scalar "
1132                  << "or vector type";
1133         }
1134 
1135         if (_.GetDimension(result_type) != _.GetDimension(exp_type)) {
1136           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1137                  << ext_inst_name() << ": "
1138                  << "expected operand Exp to have the same component "
1139                  << "number as Result Type";
1140         }
1141 
1142         break;
1143       }
1144 
1145       case GLSLstd450FrexpStruct: {
1146         std::vector<uint32_t> result_types;
1147         if (!_.GetStructMemberTypes(result_type, &result_types) ||
1148             result_types.size() != 2 ||
1149             !_.IsFloatScalarOrVectorType(result_types[0]) ||
1150             !_.IsIntScalarOrVectorType(result_types[1]) ||
1151             (!_.HasExtension(kSPV_AMD_gpu_shader_int16) &&
1152              _.GetBitWidth(result_types[1]) != 32) ||
1153             (_.HasExtension(kSPV_AMD_gpu_shader_int16) &&
1154              _.GetBitWidth(result_types[1]) != 16 &&
1155              _.GetBitWidth(result_types[1]) != 32) ||
1156             _.GetDimension(result_types[0]) !=
1157                 _.GetDimension(result_types[1])) {
1158           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1159                  << ext_inst_name() << ": "
1160                  << "expected Result Type to be a struct with two members, "
1161                  << "first member a float scalar or vector, second member a "
1162                  << (_.HasExtension(kSPV_AMD_gpu_shader_int16)
1163                          ? "16-bit or 32-bit "
1164                          : "32-bit ")
1165                  << "int scalar or vector with the same number of "
1166                  << "components as the first member";
1167         }
1168 
1169         const uint32_t x_type = _.GetOperandTypeId(inst, 4);
1170         if (x_type != result_types[0]) {
1171           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1172                  << ext_inst_name() << ": "
1173                  << "expected operand X type to be equal to the first member "
1174                  << "of Result Type struct";
1175         }
1176         break;
1177       }
1178 
1179       case GLSLstd450PackSnorm4x8:
1180       case GLSLstd450PackUnorm4x8: {
1181         if (!_.IsIntScalarType(result_type) ||
1182             _.GetBitWidth(result_type) != 32) {
1183           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1184                  << ext_inst_name() << ": "
1185                  << "expected Result Type to be 32-bit int scalar type";
1186         }
1187 
1188         const uint32_t v_type = _.GetOperandTypeId(inst, 4);
1189         if (!_.IsFloatVectorType(v_type) || _.GetDimension(v_type) != 4 ||
1190             _.GetBitWidth(v_type) != 32) {
1191           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1192                  << ext_inst_name() << ": "
1193                  << "expected operand V to be a 32-bit float vector of size 4";
1194         }
1195         break;
1196       }
1197 
1198       case GLSLstd450PackSnorm2x16:
1199       case GLSLstd450PackUnorm2x16:
1200       case GLSLstd450PackHalf2x16: {
1201         if (!_.IsIntScalarType(result_type) ||
1202             _.GetBitWidth(result_type) != 32) {
1203           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1204                  << ext_inst_name() << ": "
1205                  << "expected Result Type to be 32-bit int scalar type";
1206         }
1207 
1208         const uint32_t v_type = _.GetOperandTypeId(inst, 4);
1209         if (!_.IsFloatVectorType(v_type) || _.GetDimension(v_type) != 2 ||
1210             _.GetBitWidth(v_type) != 32) {
1211           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1212                  << ext_inst_name() << ": "
1213                  << "expected operand V to be a 32-bit float vector of size 2";
1214         }
1215         break;
1216       }
1217 
1218       case GLSLstd450PackDouble2x32: {
1219         if (!_.IsFloatScalarType(result_type) ||
1220             _.GetBitWidth(result_type) != 64) {
1221           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1222                  << ext_inst_name() << ": "
1223                  << "expected Result Type to be 64-bit float scalar type";
1224         }
1225 
1226         const uint32_t v_type = _.GetOperandTypeId(inst, 4);
1227         if (!_.IsIntVectorType(v_type) || _.GetDimension(v_type) != 2 ||
1228             _.GetBitWidth(v_type) != 32) {
1229           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1230                  << ext_inst_name() << ": "
1231                  << "expected operand V to be a 32-bit int vector of size 2";
1232         }
1233         break;
1234       }
1235 
1236       case GLSLstd450UnpackSnorm4x8:
1237       case GLSLstd450UnpackUnorm4x8: {
1238         if (!_.IsFloatVectorType(result_type) ||
1239             _.GetDimension(result_type) != 4 ||
1240             _.GetBitWidth(result_type) != 32) {
1241           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1242                  << ext_inst_name() << ": "
1243                  << "expected Result Type to be a 32-bit float vector of size "
1244                     "4";
1245         }
1246 
1247         const uint32_t v_type = _.GetOperandTypeId(inst, 4);
1248         if (!_.IsIntScalarType(v_type) || _.GetBitWidth(v_type) != 32) {
1249           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1250                  << ext_inst_name() << ": "
1251                  << "expected operand P to be a 32-bit int scalar";
1252         }
1253         break;
1254       }
1255 
1256       case GLSLstd450UnpackSnorm2x16:
1257       case GLSLstd450UnpackUnorm2x16:
1258       case GLSLstd450UnpackHalf2x16: {
1259         if (!_.IsFloatVectorType(result_type) ||
1260             _.GetDimension(result_type) != 2 ||
1261             _.GetBitWidth(result_type) != 32) {
1262           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1263                  << ext_inst_name() << ": "
1264                  << "expected Result Type to be a 32-bit float vector of size "
1265                     "2";
1266         }
1267 
1268         const uint32_t v_type = _.GetOperandTypeId(inst, 4);
1269         if (!_.IsIntScalarType(v_type) || _.GetBitWidth(v_type) != 32) {
1270           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1271                  << ext_inst_name() << ": "
1272                  << "expected operand P to be a 32-bit int scalar";
1273         }
1274         break;
1275       }
1276 
1277       case GLSLstd450UnpackDouble2x32: {
1278         if (!_.IsIntVectorType(result_type) ||
1279             _.GetDimension(result_type) != 2 ||
1280             _.GetBitWidth(result_type) != 32) {
1281           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1282                  << ext_inst_name() << ": "
1283                  << "expected Result Type to be a 32-bit int vector of size "
1284                     "2";
1285         }
1286 
1287         const uint32_t v_type = _.GetOperandTypeId(inst, 4);
1288         if (!_.IsFloatScalarType(v_type) || _.GetBitWidth(v_type) != 64) {
1289           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1290                  << ext_inst_name() << ": "
1291                  << "expected operand V to be a 64-bit float scalar";
1292         }
1293         break;
1294       }
1295 
1296       case GLSLstd450Length: {
1297         if (!_.IsFloatScalarType(result_type)) {
1298           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1299                  << ext_inst_name() << ": "
1300                  << "expected Result Type to be a float scalar type";
1301         }
1302 
1303         const uint32_t x_type = _.GetOperandTypeId(inst, 4);
1304         if (!_.IsFloatScalarOrVectorType(x_type)) {
1305           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1306                  << ext_inst_name() << ": "
1307                  << "expected operand X to be of float scalar or vector type";
1308         }
1309 
1310         if (result_type != _.GetComponentType(x_type)) {
1311           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1312                  << ext_inst_name() << ": "
1313                  << "expected operand X component type to be equal to Result "
1314                     "Type";
1315         }
1316         break;
1317       }
1318 
1319       case GLSLstd450Distance: {
1320         if (!_.IsFloatScalarType(result_type)) {
1321           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1322                  << ext_inst_name() << ": "
1323                  << "expected Result Type to be a float scalar type";
1324         }
1325 
1326         const uint32_t p0_type = _.GetOperandTypeId(inst, 4);
1327         if (!_.IsFloatScalarOrVectorType(p0_type)) {
1328           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1329                  << ext_inst_name() << ": "
1330                  << "expected operand P0 to be of float scalar or vector type";
1331         }
1332 
1333         if (result_type != _.GetComponentType(p0_type)) {
1334           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1335                  << ext_inst_name() << ": "
1336                  << "expected operand P0 component type to be equal to "
1337                  << "Result Type";
1338         }
1339 
1340         const uint32_t p1_type = _.GetOperandTypeId(inst, 5);
1341         if (!_.IsFloatScalarOrVectorType(p1_type)) {
1342           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1343                  << ext_inst_name() << ": "
1344                  << "expected operand P1 to be of float scalar or vector type";
1345         }
1346 
1347         if (result_type != _.GetComponentType(p1_type)) {
1348           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1349                  << ext_inst_name() << ": "
1350                  << "expected operand P1 component type to be equal to "
1351                  << "Result Type";
1352         }
1353 
1354         if (_.GetDimension(p0_type) != _.GetDimension(p1_type)) {
1355           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1356                  << ext_inst_name() << ": "
1357                  << "expected operands P0 and P1 to have the same number of "
1358                  << "components";
1359         }
1360         break;
1361       }
1362 
1363       case GLSLstd450Cross: {
1364         if (!_.IsFloatVectorType(result_type)) {
1365           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1366                  << ext_inst_name() << ": "
1367                  << "expected Result Type to be a float vector type";
1368         }
1369 
1370         if (_.GetDimension(result_type) != 3) {
1371           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1372                  << ext_inst_name() << ": "
1373                  << "expected Result Type to have 3 components";
1374         }
1375 
1376         const uint32_t x_type = _.GetOperandTypeId(inst, 4);
1377         const uint32_t y_type = _.GetOperandTypeId(inst, 5);
1378 
1379         if (x_type != result_type) {
1380           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1381                  << ext_inst_name() << ": "
1382                  << "expected operand X type to be equal to Result Type";
1383         }
1384 
1385         if (y_type != result_type) {
1386           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1387                  << ext_inst_name() << ": "
1388                  << "expected operand Y type to be equal to Result Type";
1389         }
1390         break;
1391       }
1392 
1393       case GLSLstd450Refract: {
1394         if (!_.IsFloatScalarOrVectorType(result_type)) {
1395           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1396                  << ext_inst_name() << ": "
1397                  << "expected Result Type to be a float scalar or vector type";
1398         }
1399 
1400         const uint32_t i_type = _.GetOperandTypeId(inst, 4);
1401         const uint32_t n_type = _.GetOperandTypeId(inst, 5);
1402         const uint32_t eta_type = _.GetOperandTypeId(inst, 6);
1403 
1404         if (result_type != i_type) {
1405           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1406                  << ext_inst_name() << ": "
1407                  << "expected operand I to be of type equal to Result Type";
1408         }
1409 
1410         if (result_type != n_type) {
1411           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1412                  << ext_inst_name() << ": "
1413                  << "expected operand N to be of type equal to Result Type";
1414         }
1415 
1416         if (!_.IsFloatScalarType(eta_type)) {
1417           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1418                  << ext_inst_name() << ": "
1419                  << "expected operand Eta to be a float scalar";
1420         }
1421         break;
1422       }
1423 
1424       case GLSLstd450InterpolateAtCentroid:
1425       case GLSLstd450InterpolateAtSample:
1426       case GLSLstd450InterpolateAtOffset: {
1427         if (!_.HasCapability(SpvCapabilityInterpolationFunction)) {
1428           return _.diag(SPV_ERROR_INVALID_CAPABILITY, inst)
1429                  << ext_inst_name()
1430                  << " requires capability InterpolationFunction";
1431         }
1432 
1433         if (!_.IsFloatScalarOrVectorType(result_type) ||
1434             _.GetBitWidth(result_type) != 32) {
1435           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1436                  << ext_inst_name() << ": "
1437                  << "expected Result Type to be a 32-bit float scalar "
1438                  << "or vector type";
1439         }
1440 
1441         // If HLSL legalization and first operand is an OpLoad, use load
1442         // pointer as the interpolant lvalue. Else use interpolate first
1443         // operand.
1444         uint32_t interp_id = inst->GetOperandAs<uint32_t>(4);
1445         auto* interp_inst = _.FindDef(interp_id);
1446         uint32_t interpolant_type = (_.options()->before_hlsl_legalization &&
1447                                      interp_inst->opcode() == SpvOpLoad)
1448                                         ? _.GetOperandTypeId(interp_inst, 2)
1449                                         : _.GetOperandTypeId(inst, 4);
1450 
1451         uint32_t interpolant_storage_class = 0;
1452         uint32_t interpolant_data_type = 0;
1453         if (!_.GetPointerTypeInfo(interpolant_type, &interpolant_data_type,
1454                                   &interpolant_storage_class)) {
1455           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1456                  << ext_inst_name() << ": "
1457                  << "expected Interpolant to be a pointer";
1458         }
1459 
1460         if (result_type != interpolant_data_type) {
1461           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1462                  << ext_inst_name() << ": "
1463                  << "expected Interpolant data type to be equal to Result Type";
1464         }
1465 
1466         if (interpolant_storage_class != SpvStorageClassInput) {
1467           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1468                  << ext_inst_name() << ": "
1469                  << "expected Interpolant storage class to be Input";
1470         }
1471 
1472         if (ext_inst_key == GLSLstd450InterpolateAtSample) {
1473           const uint32_t sample_type = _.GetOperandTypeId(inst, 5);
1474           if (!_.IsIntScalarType(sample_type) ||
1475               _.GetBitWidth(sample_type) != 32) {
1476             return _.diag(SPV_ERROR_INVALID_DATA, inst)
1477                    << ext_inst_name() << ": "
1478                    << "expected Sample to be 32-bit integer";
1479           }
1480         }
1481 
1482         if (ext_inst_key == GLSLstd450InterpolateAtOffset) {
1483           const uint32_t offset_type = _.GetOperandTypeId(inst, 5);
1484           if (!_.IsFloatVectorType(offset_type) ||
1485               _.GetDimension(offset_type) != 2 ||
1486               _.GetBitWidth(offset_type) != 32) {
1487             return _.diag(SPV_ERROR_INVALID_DATA, inst)
1488                    << ext_inst_name() << ": "
1489                    << "expected Offset to be a vector of 2 32-bit floats";
1490           }
1491         }
1492 
1493         _.function(inst->function()->id())
1494             ->RegisterExecutionModelLimitation(
1495                 SpvExecutionModelFragment,
1496                 ext_inst_name() +
1497                     std::string(" requires Fragment execution model"));
1498         break;
1499       }
1500 
1501       case GLSLstd450IMix: {
1502         return _.diag(SPV_ERROR_INVALID_DATA, inst)
1503                << "Extended instruction GLSLstd450IMix is not supported";
1504       }
1505 
1506       case GLSLstd450Bad: {
1507         return _.diag(SPV_ERROR_INVALID_DATA, inst)
1508                << "Encountered extended instruction GLSLstd450Bad";
1509       }
1510 
1511       case GLSLstd450Count: {
1512         assert(0);
1513         break;
1514       }
1515     }
1516   } else if (ext_inst_type == SPV_EXT_INST_TYPE_OPENCL_STD) {
1517     const OpenCLLIB::Entrypoints ext_inst_key =
1518         OpenCLLIB::Entrypoints(ext_inst_index);
1519     switch (ext_inst_key) {
1520       case OpenCLLIB::Acos:
1521       case OpenCLLIB::Acosh:
1522       case OpenCLLIB::Acospi:
1523       case OpenCLLIB::Asin:
1524       case OpenCLLIB::Asinh:
1525       case OpenCLLIB::Asinpi:
1526       case OpenCLLIB::Atan:
1527       case OpenCLLIB::Atan2:
1528       case OpenCLLIB::Atanh:
1529       case OpenCLLIB::Atanpi:
1530       case OpenCLLIB::Atan2pi:
1531       case OpenCLLIB::Cbrt:
1532       case OpenCLLIB::Ceil:
1533       case OpenCLLIB::Copysign:
1534       case OpenCLLIB::Cos:
1535       case OpenCLLIB::Cosh:
1536       case OpenCLLIB::Cospi:
1537       case OpenCLLIB::Erfc:
1538       case OpenCLLIB::Erf:
1539       case OpenCLLIB::Exp:
1540       case OpenCLLIB::Exp2:
1541       case OpenCLLIB::Exp10:
1542       case OpenCLLIB::Expm1:
1543       case OpenCLLIB::Fabs:
1544       case OpenCLLIB::Fdim:
1545       case OpenCLLIB::Floor:
1546       case OpenCLLIB::Fma:
1547       case OpenCLLIB::Fmax:
1548       case OpenCLLIB::Fmin:
1549       case OpenCLLIB::Fmod:
1550       case OpenCLLIB::Hypot:
1551       case OpenCLLIB::Lgamma:
1552       case OpenCLLIB::Log:
1553       case OpenCLLIB::Log2:
1554       case OpenCLLIB::Log10:
1555       case OpenCLLIB::Log1p:
1556       case OpenCLLIB::Logb:
1557       case OpenCLLIB::Mad:
1558       case OpenCLLIB::Maxmag:
1559       case OpenCLLIB::Minmag:
1560       case OpenCLLIB::Nextafter:
1561       case OpenCLLIB::Pow:
1562       case OpenCLLIB::Powr:
1563       case OpenCLLIB::Remainder:
1564       case OpenCLLIB::Rint:
1565       case OpenCLLIB::Round:
1566       case OpenCLLIB::Rsqrt:
1567       case OpenCLLIB::Sin:
1568       case OpenCLLIB::Sinh:
1569       case OpenCLLIB::Sinpi:
1570       case OpenCLLIB::Sqrt:
1571       case OpenCLLIB::Tan:
1572       case OpenCLLIB::Tanh:
1573       case OpenCLLIB::Tanpi:
1574       case OpenCLLIB::Tgamma:
1575       case OpenCLLIB::Trunc:
1576       case OpenCLLIB::Half_cos:
1577       case OpenCLLIB::Half_divide:
1578       case OpenCLLIB::Half_exp:
1579       case OpenCLLIB::Half_exp2:
1580       case OpenCLLIB::Half_exp10:
1581       case OpenCLLIB::Half_log:
1582       case OpenCLLIB::Half_log2:
1583       case OpenCLLIB::Half_log10:
1584       case OpenCLLIB::Half_powr:
1585       case OpenCLLIB::Half_recip:
1586       case OpenCLLIB::Half_rsqrt:
1587       case OpenCLLIB::Half_sin:
1588       case OpenCLLIB::Half_sqrt:
1589       case OpenCLLIB::Half_tan:
1590       case OpenCLLIB::Native_cos:
1591       case OpenCLLIB::Native_divide:
1592       case OpenCLLIB::Native_exp:
1593       case OpenCLLIB::Native_exp2:
1594       case OpenCLLIB::Native_exp10:
1595       case OpenCLLIB::Native_log:
1596       case OpenCLLIB::Native_log2:
1597       case OpenCLLIB::Native_log10:
1598       case OpenCLLIB::Native_powr:
1599       case OpenCLLIB::Native_recip:
1600       case OpenCLLIB::Native_rsqrt:
1601       case OpenCLLIB::Native_sin:
1602       case OpenCLLIB::Native_sqrt:
1603       case OpenCLLIB::Native_tan:
1604       case OpenCLLIB::FClamp:
1605       case OpenCLLIB::Degrees:
1606       case OpenCLLIB::FMax_common:
1607       case OpenCLLIB::FMin_common:
1608       case OpenCLLIB::Mix:
1609       case OpenCLLIB::Radians:
1610       case OpenCLLIB::Step:
1611       case OpenCLLIB::Smoothstep:
1612       case OpenCLLIB::Sign: {
1613         if (!_.IsFloatScalarOrVectorType(result_type)) {
1614           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1615                  << ext_inst_name() << ": "
1616                  << "expected Result Type to be a float scalar or vector type";
1617         }
1618 
1619         const uint32_t num_components = _.GetDimension(result_type);
1620         if (num_components > 4 && num_components != 8 && num_components != 16) {
1621           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1622                  << ext_inst_name() << ": "
1623                  << "expected Result Type to be a scalar or a vector with 2, "
1624                     "3, 4, 8 or 16 components";
1625         }
1626 
1627         for (uint32_t operand_index = 4; operand_index < num_operands;
1628              ++operand_index) {
1629           const uint32_t operand_type = _.GetOperandTypeId(inst, operand_index);
1630           if (result_type != operand_type) {
1631             return _.diag(SPV_ERROR_INVALID_DATA, inst)
1632                    << ext_inst_name() << ": "
1633                    << "expected types of all operands to be equal to Result "
1634                       "Type";
1635           }
1636         }
1637         break;
1638       }
1639 
1640       case OpenCLLIB::Fract:
1641       case OpenCLLIB::Modf:
1642       case OpenCLLIB::Sincos: {
1643         if (!_.IsFloatScalarOrVectorType(result_type)) {
1644           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1645                  << ext_inst_name() << ": "
1646                  << "expected Result Type to be a float scalar or vector type";
1647         }
1648 
1649         const uint32_t num_components = _.GetDimension(result_type);
1650         if (num_components > 4 && num_components != 8 && num_components != 16) {
1651           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1652                  << ext_inst_name() << ": "
1653                  << "expected Result Type to be a scalar or a vector with 2, "
1654                     "3, 4, 8 or 16 components";
1655         }
1656 
1657         const uint32_t x_type = _.GetOperandTypeId(inst, 4);
1658         if (result_type != x_type) {
1659           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1660                  << ext_inst_name() << ": "
1661                  << "expected type of operand X to be equal to Result Type";
1662         }
1663 
1664         const uint32_t p_type = _.GetOperandTypeId(inst, 5);
1665         uint32_t p_storage_class = 0;
1666         uint32_t p_data_type = 0;
1667         if (!_.GetPointerTypeInfo(p_type, &p_data_type, &p_storage_class)) {
1668           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1669                  << ext_inst_name() << ": "
1670                  << "expected the last operand to be a pointer";
1671         }
1672 
1673         if (p_storage_class != SpvStorageClassGeneric &&
1674             p_storage_class != SpvStorageClassCrossWorkgroup &&
1675             p_storage_class != SpvStorageClassWorkgroup &&
1676             p_storage_class != SpvStorageClassFunction) {
1677           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1678                  << ext_inst_name() << ": "
1679                  << "expected storage class of the pointer to be Generic, "
1680                     "CrossWorkgroup, Workgroup or Function";
1681         }
1682 
1683         if (result_type != p_data_type) {
1684           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1685                  << ext_inst_name() << ": "
1686                  << "expected data type of the pointer to be equal to Result "
1687                     "Type";
1688         }
1689         break;
1690       }
1691 
1692       case OpenCLLIB::Frexp:
1693       case OpenCLLIB::Lgamma_r:
1694       case OpenCLLIB::Remquo: {
1695         if (!_.IsFloatScalarOrVectorType(result_type)) {
1696           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1697                  << ext_inst_name() << ": "
1698                  << "expected Result Type to be a float scalar or vector type";
1699         }
1700 
1701         const uint32_t num_components = _.GetDimension(result_type);
1702         if (num_components > 4 && num_components != 8 && num_components != 16) {
1703           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1704                  << ext_inst_name() << ": "
1705                  << "expected Result Type to be a scalar or a vector with 2, "
1706                     "3, 4, 8 or 16 components";
1707         }
1708 
1709         uint32_t operand_index = 4;
1710         const uint32_t x_type = _.GetOperandTypeId(inst, operand_index++);
1711         if (result_type != x_type) {
1712           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1713                  << ext_inst_name() << ": "
1714                  << "expected type of operand X to be equal to Result Type";
1715         }
1716 
1717         if (ext_inst_key == OpenCLLIB::Remquo) {
1718           const uint32_t y_type = _.GetOperandTypeId(inst, operand_index++);
1719           if (result_type != y_type) {
1720             return _.diag(SPV_ERROR_INVALID_DATA, inst)
1721                    << ext_inst_name() << ": "
1722                    << "expected type of operand Y to be equal to Result Type";
1723           }
1724         }
1725 
1726         const uint32_t p_type = _.GetOperandTypeId(inst, operand_index++);
1727         uint32_t p_storage_class = 0;
1728         uint32_t p_data_type = 0;
1729         if (!_.GetPointerTypeInfo(p_type, &p_data_type, &p_storage_class)) {
1730           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1731                  << ext_inst_name() << ": "
1732                  << "expected the last operand to be a pointer";
1733         }
1734 
1735         if (p_storage_class != SpvStorageClassGeneric &&
1736             p_storage_class != SpvStorageClassCrossWorkgroup &&
1737             p_storage_class != SpvStorageClassWorkgroup &&
1738             p_storage_class != SpvStorageClassFunction) {
1739           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1740                  << ext_inst_name() << ": "
1741                  << "expected storage class of the pointer to be Generic, "
1742                     "CrossWorkgroup, Workgroup or Function";
1743         }
1744 
1745         if (!_.IsIntScalarOrVectorType(p_data_type) ||
1746             _.GetBitWidth(p_data_type) != 32) {
1747           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1748                  << ext_inst_name() << ": "
1749                  << "expected data type of the pointer to be a 32-bit int "
1750                     "scalar or vector type";
1751         }
1752 
1753         if (_.GetDimension(p_data_type) != num_components) {
1754           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1755                  << ext_inst_name() << ": "
1756                  << "expected data type of the pointer to have the same number "
1757                     "of components as Result Type";
1758         }
1759         break;
1760       }
1761 
1762       case OpenCLLIB::Ilogb: {
1763         if (!_.IsIntScalarOrVectorType(result_type) ||
1764             _.GetBitWidth(result_type) != 32) {
1765           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1766                  << ext_inst_name() << ": "
1767                  << "expected Result Type to be a 32-bit int scalar or vector "
1768                     "type";
1769         }
1770 
1771         const uint32_t num_components = _.GetDimension(result_type);
1772         if (num_components > 4 && num_components != 8 && num_components != 16) {
1773           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1774                  << ext_inst_name() << ": "
1775                  << "expected Result Type to be a scalar or a vector with 2, "
1776                     "3, 4, 8 or 16 components";
1777         }
1778 
1779         const uint32_t x_type = _.GetOperandTypeId(inst, 4);
1780         if (!_.IsFloatScalarOrVectorType(x_type)) {
1781           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1782                  << ext_inst_name() << ": "
1783                  << "expected operand X to be a float scalar or vector";
1784         }
1785 
1786         if (_.GetDimension(x_type) != num_components) {
1787           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1788                  << ext_inst_name() << ": "
1789                  << "expected operand X to have the same number of components "
1790                     "as Result Type";
1791         }
1792         break;
1793       }
1794 
1795       case OpenCLLIB::Ldexp:
1796       case OpenCLLIB::Pown:
1797       case OpenCLLIB::Rootn: {
1798         if (!_.IsFloatScalarOrVectorType(result_type)) {
1799           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1800                  << ext_inst_name() << ": "
1801                  << "expected Result Type to be a float scalar or vector type";
1802         }
1803 
1804         const uint32_t num_components = _.GetDimension(result_type);
1805         if (num_components > 4 && num_components != 8 && num_components != 16) {
1806           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1807                  << ext_inst_name() << ": "
1808                  << "expected Result Type to be a scalar or a vector with 2, "
1809                     "3, 4, 8 or 16 components";
1810         }
1811 
1812         const uint32_t x_type = _.GetOperandTypeId(inst, 4);
1813         if (result_type != x_type) {
1814           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1815                  << ext_inst_name() << ": "
1816                  << "expected type of operand X to be equal to Result Type";
1817         }
1818 
1819         const uint32_t exp_type = _.GetOperandTypeId(inst, 5);
1820         if (!_.IsIntScalarOrVectorType(exp_type) ||
1821             _.GetBitWidth(exp_type) != 32) {
1822           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1823                  << ext_inst_name() << ": "
1824                  << "expected the exponent to be a 32-bit int scalar or vector";
1825         }
1826 
1827         if (_.GetDimension(exp_type) != num_components) {
1828           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1829                  << ext_inst_name() << ": "
1830                  << "expected the exponent to have the same number of "
1831                     "components as Result Type";
1832         }
1833         break;
1834       }
1835 
1836       case OpenCLLIB::Nan: {
1837         if (!_.IsFloatScalarOrVectorType(result_type)) {
1838           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1839                  << ext_inst_name() << ": "
1840                  << "expected Result Type to be a float scalar or vector type";
1841         }
1842 
1843         const uint32_t num_components = _.GetDimension(result_type);
1844         if (num_components > 4 && num_components != 8 && num_components != 16) {
1845           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1846                  << ext_inst_name() << ": "
1847                  << "expected Result Type to be a scalar or a vector with 2, "
1848                     "3, 4, 8 or 16 components";
1849         }
1850 
1851         const uint32_t nancode_type = _.GetOperandTypeId(inst, 4);
1852         if (!_.IsIntScalarOrVectorType(nancode_type)) {
1853           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1854                  << ext_inst_name() << ": "
1855                  << "expected Nancode to be an int scalar or vector type";
1856         }
1857 
1858         if (_.GetDimension(nancode_type) != num_components) {
1859           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1860                  << ext_inst_name() << ": "
1861                  << "expected Nancode to have the same number of components as "
1862                     "Result Type";
1863         }
1864 
1865         if (_.GetBitWidth(result_type) != _.GetBitWidth(nancode_type)) {
1866           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1867                  << ext_inst_name() << ": "
1868                  << "expected Nancode to have the same bit width as Result "
1869                     "Type";
1870         }
1871         break;
1872       }
1873 
1874       case OpenCLLIB::SAbs:
1875       case OpenCLLIB::SAbs_diff:
1876       case OpenCLLIB::SAdd_sat:
1877       case OpenCLLIB::UAdd_sat:
1878       case OpenCLLIB::SHadd:
1879       case OpenCLLIB::UHadd:
1880       case OpenCLLIB::SRhadd:
1881       case OpenCLLIB::URhadd:
1882       case OpenCLLIB::SClamp:
1883       case OpenCLLIB::UClamp:
1884       case OpenCLLIB::Clz:
1885       case OpenCLLIB::Ctz:
1886       case OpenCLLIB::SMad_hi:
1887       case OpenCLLIB::UMad_sat:
1888       case OpenCLLIB::SMad_sat:
1889       case OpenCLLIB::SMax:
1890       case OpenCLLIB::UMax:
1891       case OpenCLLIB::SMin:
1892       case OpenCLLIB::UMin:
1893       case OpenCLLIB::SMul_hi:
1894       case OpenCLLIB::Rotate:
1895       case OpenCLLIB::SSub_sat:
1896       case OpenCLLIB::USub_sat:
1897       case OpenCLLIB::Popcount:
1898       case OpenCLLIB::UAbs:
1899       case OpenCLLIB::UAbs_diff:
1900       case OpenCLLIB::UMul_hi:
1901       case OpenCLLIB::UMad_hi: {
1902         if (!_.IsIntScalarOrVectorType(result_type)) {
1903           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1904                  << ext_inst_name() << ": "
1905                  << "expected Result Type to be an int scalar or vector type";
1906         }
1907 
1908         const uint32_t num_components = _.GetDimension(result_type);
1909         if (num_components > 4 && num_components != 8 && num_components != 16) {
1910           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1911                  << ext_inst_name() << ": "
1912                  << "expected Result Type to be a scalar or a vector with 2, "
1913                     "3, 4, 8 or 16 components";
1914         }
1915 
1916         for (uint32_t operand_index = 4; operand_index < num_operands;
1917              ++operand_index) {
1918           const uint32_t operand_type = _.GetOperandTypeId(inst, operand_index);
1919           if (result_type != operand_type) {
1920             return _.diag(SPV_ERROR_INVALID_DATA, inst)
1921                    << ext_inst_name() << ": "
1922                    << "expected types of all operands to be equal to Result "
1923                       "Type";
1924           }
1925         }
1926         break;
1927       }
1928 
1929       case OpenCLLIB::U_Upsample:
1930       case OpenCLLIB::S_Upsample: {
1931         if (!_.IsIntScalarOrVectorType(result_type)) {
1932           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1933                  << ext_inst_name() << ": "
1934                  << "expected Result Type to be an int scalar or vector "
1935                     "type";
1936         }
1937 
1938         const uint32_t result_num_components = _.GetDimension(result_type);
1939         if (result_num_components > 4 && result_num_components != 8 &&
1940             result_num_components != 16) {
1941           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1942                  << ext_inst_name() << ": "
1943                  << "expected Result Type to be a scalar or a vector with 2, "
1944                     "3, 4, 8 or 16 components";
1945         }
1946 
1947         const uint32_t result_bit_width = _.GetBitWidth(result_type);
1948         if (result_bit_width != 16 && result_bit_width != 32 &&
1949             result_bit_width != 64) {
1950           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1951                  << ext_inst_name() << ": "
1952                  << "expected bit width of Result Type components to be 16, 32 "
1953                     "or 64";
1954         }
1955 
1956         const uint32_t hi_type = _.GetOperandTypeId(inst, 4);
1957         const uint32_t lo_type = _.GetOperandTypeId(inst, 5);
1958 
1959         if (hi_type != lo_type) {
1960           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1961                  << ext_inst_name() << ": "
1962                  << "expected Hi and Lo operands to have the same type";
1963         }
1964 
1965         if (result_num_components != _.GetDimension(hi_type)) {
1966           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1967                  << ext_inst_name() << ": "
1968                  << "expected Hi and Lo operands to have the same number of "
1969                     "components as Result Type";
1970         }
1971 
1972         if (result_bit_width != 2 * _.GetBitWidth(hi_type)) {
1973           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1974                  << ext_inst_name() << ": "
1975                  << "expected bit width of components of Hi and Lo operands to "
1976                     "be half of the bit width of components of Result Type";
1977         }
1978         break;
1979       }
1980 
1981       case OpenCLLIB::SMad24:
1982       case OpenCLLIB::UMad24:
1983       case OpenCLLIB::SMul24:
1984       case OpenCLLIB::UMul24: {
1985         if (!_.IsIntScalarOrVectorType(result_type) ||
1986             _.GetBitWidth(result_type) != 32) {
1987           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1988                  << ext_inst_name() << ": "
1989                  << "expected Result Type to be a 32-bit int scalar or vector "
1990                     "type";
1991         }
1992 
1993         const uint32_t num_components = _.GetDimension(result_type);
1994         if (num_components > 4 && num_components != 8 && num_components != 16) {
1995           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1996                  << ext_inst_name() << ": "
1997                  << "expected Result Type to be a scalar or a vector with 2, "
1998                     "3, 4, 8 or 16 components";
1999         }
2000 
2001         for (uint32_t operand_index = 4; operand_index < num_operands;
2002              ++operand_index) {
2003           const uint32_t operand_type = _.GetOperandTypeId(inst, operand_index);
2004           if (result_type != operand_type) {
2005             return _.diag(SPV_ERROR_INVALID_DATA, inst)
2006                    << ext_inst_name() << ": "
2007                    << "expected types of all operands to be equal to Result "
2008                       "Type";
2009           }
2010         }
2011         break;
2012       }
2013 
2014       case OpenCLLIB::Cross: {
2015         if (!_.IsFloatVectorType(result_type)) {
2016           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2017                  << ext_inst_name() << ": "
2018                  << "expected Result Type to be a float vector type";
2019         }
2020 
2021         const uint32_t num_components = _.GetDimension(result_type);
2022         if (num_components != 3 && num_components != 4) {
2023           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2024                  << ext_inst_name() << ": "
2025                  << "expected Result Type to have 3 or 4 components";
2026         }
2027 
2028         const uint32_t x_type = _.GetOperandTypeId(inst, 4);
2029         const uint32_t y_type = _.GetOperandTypeId(inst, 5);
2030 
2031         if (x_type != result_type) {
2032           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2033                  << ext_inst_name() << ": "
2034                  << "expected operand X type to be equal to Result Type";
2035         }
2036 
2037         if (y_type != result_type) {
2038           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2039                  << ext_inst_name() << ": "
2040                  << "expected operand Y type to be equal to Result Type";
2041         }
2042         break;
2043       }
2044 
2045       case OpenCLLIB::Distance:
2046       case OpenCLLIB::Fast_distance: {
2047         if (!_.IsFloatScalarType(result_type)) {
2048           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2049                  << ext_inst_name() << ": "
2050                  << "expected Result Type to be a float scalar type";
2051         }
2052 
2053         const uint32_t p0_type = _.GetOperandTypeId(inst, 4);
2054         if (!_.IsFloatScalarOrVectorType(p0_type)) {
2055           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2056                  << ext_inst_name() << ": "
2057                  << "expected operand P0 to be of float scalar or vector type";
2058         }
2059 
2060         const uint32_t num_components = _.GetDimension(p0_type);
2061         if (num_components > 4) {
2062           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2063                  << ext_inst_name() << ": "
2064                  << "expected operand P0 to have no more than 4 components";
2065         }
2066 
2067         if (result_type != _.GetComponentType(p0_type)) {
2068           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2069                  << ext_inst_name() << ": "
2070                  << "expected operand P0 component type to be equal to "
2071                  << "Result Type";
2072         }
2073 
2074         const uint32_t p1_type = _.GetOperandTypeId(inst, 5);
2075         if (p0_type != p1_type) {
2076           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2077                  << ext_inst_name() << ": "
2078                  << "expected operands P0 and P1 to be of the same type";
2079         }
2080         break;
2081       }
2082 
2083       case OpenCLLIB::Length:
2084       case OpenCLLIB::Fast_length: {
2085         if (!_.IsFloatScalarType(result_type)) {
2086           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2087                  << ext_inst_name() << ": "
2088                  << "expected Result Type to be a float scalar type";
2089         }
2090 
2091         const uint32_t p_type = _.GetOperandTypeId(inst, 4);
2092         if (!_.IsFloatScalarOrVectorType(p_type)) {
2093           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2094                  << ext_inst_name() << ": "
2095                  << "expected operand P to be a float scalar or vector";
2096         }
2097 
2098         const uint32_t num_components = _.GetDimension(p_type);
2099         if (num_components > 4) {
2100           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2101                  << ext_inst_name() << ": "
2102                  << "expected operand P to have no more than 4 components";
2103         }
2104 
2105         if (result_type != _.GetComponentType(p_type)) {
2106           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2107                  << ext_inst_name() << ": "
2108                  << "expected operand P component type to be equal to Result "
2109                     "Type";
2110         }
2111         break;
2112       }
2113 
2114       case OpenCLLIB::Normalize:
2115       case OpenCLLIB::Fast_normalize: {
2116         if (!_.IsFloatScalarOrVectorType(result_type)) {
2117           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2118                  << ext_inst_name() << ": "
2119                  << "expected Result Type to be a float scalar or vector type";
2120         }
2121 
2122         const uint32_t num_components = _.GetDimension(result_type);
2123         if (num_components > 4) {
2124           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2125                  << ext_inst_name() << ": "
2126                  << "expected Result Type to have no more than 4 components";
2127         }
2128 
2129         const uint32_t p_type = _.GetOperandTypeId(inst, 4);
2130         if (p_type != result_type) {
2131           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2132                  << ext_inst_name() << ": "
2133                  << "expected operand P type to be equal to Result Type";
2134         }
2135         break;
2136       }
2137 
2138       case OpenCLLIB::Bitselect: {
2139         if (!_.IsFloatScalarOrVectorType(result_type) &&
2140             !_.IsIntScalarOrVectorType(result_type)) {
2141           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2142                  << ext_inst_name() << ": "
2143                  << "expected Result Type to be an int or float scalar or "
2144                     "vector type";
2145         }
2146 
2147         const uint32_t num_components = _.GetDimension(result_type);
2148         if (num_components > 4 && num_components != 8 && num_components != 16) {
2149           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2150                  << ext_inst_name() << ": "
2151                  << "expected Result Type to be a scalar or a vector with 2, "
2152                     "3, 4, 8 or 16 components";
2153         }
2154 
2155         for (uint32_t operand_index = 4; operand_index < num_operands;
2156              ++operand_index) {
2157           const uint32_t operand_type = _.GetOperandTypeId(inst, operand_index);
2158           if (result_type != operand_type) {
2159             return _.diag(SPV_ERROR_INVALID_DATA, inst)
2160                    << ext_inst_name() << ": "
2161                    << "expected types of all operands to be equal to Result "
2162                       "Type";
2163           }
2164         }
2165         break;
2166       }
2167 
2168       case OpenCLLIB::Select: {
2169         if (!_.IsFloatScalarOrVectorType(result_type) &&
2170             !_.IsIntScalarOrVectorType(result_type)) {
2171           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2172                  << ext_inst_name() << ": "
2173                  << "expected Result Type to be an int or float scalar or "
2174                     "vector type";
2175         }
2176 
2177         const uint32_t num_components = _.GetDimension(result_type);
2178         if (num_components > 4 && num_components != 8 && num_components != 16) {
2179           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2180                  << ext_inst_name() << ": "
2181                  << "expected Result Type to be a scalar or a vector with 2, "
2182                     "3, 4, 8 or 16 components";
2183         }
2184 
2185         const uint32_t a_type = _.GetOperandTypeId(inst, 4);
2186         const uint32_t b_type = _.GetOperandTypeId(inst, 5);
2187         const uint32_t c_type = _.GetOperandTypeId(inst, 6);
2188 
2189         if (result_type != a_type) {
2190           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2191                  << ext_inst_name() << ": "
2192                  << "expected operand A type to be equal to Result Type";
2193         }
2194 
2195         if (result_type != b_type) {
2196           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2197                  << ext_inst_name() << ": "
2198                  << "expected operand B type to be equal to Result Type";
2199         }
2200 
2201         if (!_.IsIntScalarOrVectorType(c_type)) {
2202           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2203                  << ext_inst_name() << ": "
2204                  << "expected operand C to be an int scalar or vector";
2205         }
2206 
2207         if (num_components != _.GetDimension(c_type)) {
2208           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2209                  << ext_inst_name() << ": "
2210                  << "expected operand C to have the same number of components "
2211                     "as Result Type";
2212         }
2213 
2214         if (_.GetBitWidth(result_type) != _.GetBitWidth(c_type)) {
2215           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2216                  << ext_inst_name() << ": "
2217                  << "expected operand C to have the same bit width as Result "
2218                     "Type";
2219         }
2220         break;
2221       }
2222 
2223       case OpenCLLIB::Vloadn: {
2224         if (!_.IsFloatVectorType(result_type) &&
2225             !_.IsIntVectorType(result_type)) {
2226           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2227                  << ext_inst_name() << ": "
2228                  << "expected Result Type to be an int or float vector type";
2229         }
2230 
2231         const uint32_t num_components = _.GetDimension(result_type);
2232         if (num_components > 4 && num_components != 8 && num_components != 16) {
2233           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2234                  << ext_inst_name() << ": "
2235                  << "expected Result Type to have 2, 3, 4, 8 or 16 components";
2236         }
2237 
2238         const uint32_t offset_type = _.GetOperandTypeId(inst, 4);
2239         const uint32_t p_type = _.GetOperandTypeId(inst, 5);
2240 
2241         const uint32_t size_t_bit_width = GetSizeTBitWidth(_);
2242         if (!size_t_bit_width) {
2243           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2244                  << ext_inst_name()
2245                  << " can only be used with physical addressing models";
2246         }
2247 
2248         if (!_.IsIntScalarType(offset_type) ||
2249             _.GetBitWidth(offset_type) != size_t_bit_width) {
2250           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2251                  << ext_inst_name() << ": "
2252                  << "expected operand Offset to be of type size_t ("
2253                  << size_t_bit_width
2254                  << "-bit integer for the addressing model used in the module)";
2255         }
2256 
2257         uint32_t p_storage_class = 0;
2258         uint32_t p_data_type = 0;
2259         if (!_.GetPointerTypeInfo(p_type, &p_data_type, &p_storage_class)) {
2260           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2261                  << ext_inst_name() << ": "
2262                  << "expected operand P to be a pointer";
2263         }
2264 
2265         if (p_storage_class != SpvStorageClassUniformConstant &&
2266             p_storage_class != SpvStorageClassGeneric &&
2267             p_storage_class != SpvStorageClassCrossWorkgroup &&
2268             p_storage_class != SpvStorageClassWorkgroup &&
2269             p_storage_class != SpvStorageClassFunction) {
2270           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2271                  << ext_inst_name() << ": "
2272                  << "expected operand P storage class to be UniformConstant, "
2273                     "Generic, CrossWorkgroup, Workgroup or Function";
2274         }
2275 
2276         if (_.GetComponentType(result_type) != p_data_type) {
2277           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2278                  << ext_inst_name() << ": "
2279                  << "expected operand P data type to be equal to component "
2280                     "type of Result Type";
2281         }
2282 
2283         const uint32_t n_value = inst->word(7);
2284         if (num_components != n_value) {
2285           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2286                  << ext_inst_name() << ": "
2287                  << "expected literal N to be equal to the number of "
2288                     "components of Result Type";
2289         }
2290         break;
2291       }
2292 
2293       case OpenCLLIB::Vstoren: {
2294         if (_.GetIdOpcode(result_type) != SpvOpTypeVoid) {
2295           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2296                  << ext_inst_name() << ": expected Result Type to be void";
2297         }
2298 
2299         const uint32_t data_type = _.GetOperandTypeId(inst, 4);
2300         const uint32_t offset_type = _.GetOperandTypeId(inst, 5);
2301         const uint32_t p_type = _.GetOperandTypeId(inst, 6);
2302 
2303         if (!_.IsFloatVectorType(data_type) && !_.IsIntVectorType(data_type)) {
2304           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2305                  << ext_inst_name() << ": "
2306                  << "expected Data to be an int or float vector";
2307         }
2308 
2309         const uint32_t num_components = _.GetDimension(data_type);
2310         if (num_components > 4 && num_components != 8 && num_components != 16) {
2311           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2312                  << ext_inst_name() << ": "
2313                  << "expected Data to have 2, 3, 4, 8 or 16 components";
2314         }
2315 
2316         const uint32_t size_t_bit_width = GetSizeTBitWidth(_);
2317         if (!size_t_bit_width) {
2318           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2319                  << ext_inst_name()
2320                  << " can only be used with physical addressing models";
2321         }
2322 
2323         if (!_.IsIntScalarType(offset_type) ||
2324             _.GetBitWidth(offset_type) != size_t_bit_width) {
2325           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2326                  << ext_inst_name() << ": "
2327                  << "expected operand Offset to be of type size_t ("
2328                  << size_t_bit_width
2329                  << "-bit integer for the addressing model used in the module)";
2330         }
2331 
2332         uint32_t p_storage_class = 0;
2333         uint32_t p_data_type = 0;
2334         if (!_.GetPointerTypeInfo(p_type, &p_data_type, &p_storage_class)) {
2335           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2336                  << ext_inst_name() << ": "
2337                  << "expected operand P to be a pointer";
2338         }
2339 
2340         if (p_storage_class != SpvStorageClassGeneric &&
2341             p_storage_class != SpvStorageClassCrossWorkgroup &&
2342             p_storage_class != SpvStorageClassWorkgroup &&
2343             p_storage_class != SpvStorageClassFunction) {
2344           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2345                  << ext_inst_name() << ": "
2346                  << "expected operand P storage class to be Generic, "
2347                     "CrossWorkgroup, Workgroup or Function";
2348         }
2349 
2350         if (_.GetComponentType(data_type) != p_data_type) {
2351           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2352                  << ext_inst_name() << ": "
2353                  << "expected operand P data type to be equal to the type of "
2354                     "operand Data components";
2355         }
2356         break;
2357       }
2358 
2359       case OpenCLLIB::Vload_half: {
2360         if (!_.IsFloatScalarType(result_type)) {
2361           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2362                  << ext_inst_name() << ": "
2363                  << "expected Result Type to be a float scalar type";
2364         }
2365 
2366         const uint32_t offset_type = _.GetOperandTypeId(inst, 4);
2367         const uint32_t p_type = _.GetOperandTypeId(inst, 5);
2368 
2369         const uint32_t size_t_bit_width = GetSizeTBitWidth(_);
2370         if (!size_t_bit_width) {
2371           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2372                  << ext_inst_name()
2373                  << " can only be used with physical addressing models";
2374         }
2375 
2376         if (!_.IsIntScalarType(offset_type) ||
2377             _.GetBitWidth(offset_type) != size_t_bit_width) {
2378           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2379                  << ext_inst_name() << ": "
2380                  << "expected operand Offset to be of type size_t ("
2381                  << size_t_bit_width
2382                  << "-bit integer for the addressing model used in the module)";
2383         }
2384 
2385         uint32_t p_storage_class = 0;
2386         uint32_t p_data_type = 0;
2387         if (!_.GetPointerTypeInfo(p_type, &p_data_type, &p_storage_class)) {
2388           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2389                  << ext_inst_name() << ": "
2390                  << "expected operand P to be a pointer";
2391         }
2392 
2393         if (p_storage_class != SpvStorageClassUniformConstant &&
2394             p_storage_class != SpvStorageClassGeneric &&
2395             p_storage_class != SpvStorageClassCrossWorkgroup &&
2396             p_storage_class != SpvStorageClassWorkgroup &&
2397             p_storage_class != SpvStorageClassFunction) {
2398           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2399                  << ext_inst_name() << ": "
2400                  << "expected operand P storage class to be UniformConstant, "
2401                     "Generic, CrossWorkgroup, Workgroup or Function";
2402         }
2403 
2404         if (!_.IsFloatScalarType(p_data_type) ||
2405             _.GetBitWidth(p_data_type) != 16) {
2406           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2407                  << ext_inst_name() << ": "
2408                  << "expected operand P data type to be 16-bit float scalar";
2409         }
2410         break;
2411       }
2412 
2413       case OpenCLLIB::Vload_halfn:
2414       case OpenCLLIB::Vloada_halfn: {
2415         if (!_.IsFloatVectorType(result_type)) {
2416           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2417                  << ext_inst_name() << ": "
2418                  << "expected Result Type to be a float vector type";
2419         }
2420 
2421         const uint32_t num_components = _.GetDimension(result_type);
2422         if (num_components > 4 && num_components != 8 && num_components != 16) {
2423           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2424                  << ext_inst_name() << ": "
2425                  << "expected Result Type to have 2, 3, 4, 8 or 16 components";
2426         }
2427 
2428         const uint32_t offset_type = _.GetOperandTypeId(inst, 4);
2429         const uint32_t p_type = _.GetOperandTypeId(inst, 5);
2430 
2431         const uint32_t size_t_bit_width = GetSizeTBitWidth(_);
2432         if (!size_t_bit_width) {
2433           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2434                  << ext_inst_name()
2435                  << " can only be used with physical addressing models";
2436         }
2437 
2438         if (!_.IsIntScalarType(offset_type) ||
2439             _.GetBitWidth(offset_type) != size_t_bit_width) {
2440           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2441                  << ext_inst_name() << ": "
2442                  << "expected operand Offset to be of type size_t ("
2443                  << size_t_bit_width
2444                  << "-bit integer for the addressing model used in the module)";
2445         }
2446 
2447         uint32_t p_storage_class = 0;
2448         uint32_t p_data_type = 0;
2449         if (!_.GetPointerTypeInfo(p_type, &p_data_type, &p_storage_class)) {
2450           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2451                  << ext_inst_name() << ": "
2452                  << "expected operand P to be a pointer";
2453         }
2454 
2455         if (p_storage_class != SpvStorageClassUniformConstant &&
2456             p_storage_class != SpvStorageClassGeneric &&
2457             p_storage_class != SpvStorageClassCrossWorkgroup &&
2458             p_storage_class != SpvStorageClassWorkgroup &&
2459             p_storage_class != SpvStorageClassFunction) {
2460           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2461                  << ext_inst_name() << ": "
2462                  << "expected operand P storage class to be UniformConstant, "
2463                     "Generic, CrossWorkgroup, Workgroup or Function";
2464         }
2465 
2466         if (!_.IsFloatScalarType(p_data_type) ||
2467             _.GetBitWidth(p_data_type) != 16) {
2468           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2469                  << ext_inst_name() << ": "
2470                  << "expected operand P data type to be 16-bit float scalar";
2471         }
2472 
2473         const uint32_t n_value = inst->word(7);
2474         if (num_components != n_value) {
2475           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2476                  << ext_inst_name() << ": "
2477                  << "expected literal N to be equal to the number of "
2478                     "components of Result Type";
2479         }
2480         break;
2481       }
2482 
2483       case OpenCLLIB::Vstore_half:
2484       case OpenCLLIB::Vstore_half_r:
2485       case OpenCLLIB::Vstore_halfn:
2486       case OpenCLLIB::Vstore_halfn_r:
2487       case OpenCLLIB::Vstorea_halfn:
2488       case OpenCLLIB::Vstorea_halfn_r: {
2489         if (_.GetIdOpcode(result_type) != SpvOpTypeVoid) {
2490           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2491                  << ext_inst_name() << ": expected Result Type to be void";
2492         }
2493 
2494         const uint32_t data_type = _.GetOperandTypeId(inst, 4);
2495         const uint32_t offset_type = _.GetOperandTypeId(inst, 5);
2496         const uint32_t p_type = _.GetOperandTypeId(inst, 6);
2497         const uint32_t data_type_bit_width = _.GetBitWidth(data_type);
2498 
2499         if (ext_inst_key == OpenCLLIB::Vstore_half ||
2500             ext_inst_key == OpenCLLIB::Vstore_half_r) {
2501           if (!_.IsFloatScalarType(data_type) ||
2502               (data_type_bit_width != 32 && data_type_bit_width != 64)) {
2503             return _.diag(SPV_ERROR_INVALID_DATA, inst)
2504                    << ext_inst_name() << ": "
2505                    << "expected Data to be a 32 or 64-bit float scalar";
2506           }
2507         } else {
2508           if (!_.IsFloatVectorType(data_type) ||
2509               (data_type_bit_width != 32 && data_type_bit_width != 64)) {
2510             return _.diag(SPV_ERROR_INVALID_DATA, inst)
2511                    << ext_inst_name() << ": "
2512                    << "expected Data to be a 32 or 64-bit float vector";
2513           }
2514 
2515           const uint32_t num_components = _.GetDimension(data_type);
2516           if (num_components > 4 && num_components != 8 &&
2517               num_components != 16) {
2518             return _.diag(SPV_ERROR_INVALID_DATA, inst)
2519                    << ext_inst_name() << ": "
2520                    << "expected Data to have 2, 3, 4, 8 or 16 components";
2521           }
2522         }
2523 
2524         const uint32_t size_t_bit_width = GetSizeTBitWidth(_);
2525         if (!size_t_bit_width) {
2526           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2527                  << ext_inst_name()
2528                  << " can only be used with physical addressing models";
2529         }
2530 
2531         if (!_.IsIntScalarType(offset_type) ||
2532             _.GetBitWidth(offset_type) != size_t_bit_width) {
2533           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2534                  << ext_inst_name() << ": "
2535                  << "expected operand Offset to be of type size_t ("
2536                  << size_t_bit_width
2537                  << "-bit integer for the addressing model used in the module)";
2538         }
2539 
2540         uint32_t p_storage_class = 0;
2541         uint32_t p_data_type = 0;
2542         if (!_.GetPointerTypeInfo(p_type, &p_data_type, &p_storage_class)) {
2543           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2544                  << ext_inst_name() << ": "
2545                  << "expected operand P to be a pointer";
2546         }
2547 
2548         if (p_storage_class != SpvStorageClassGeneric &&
2549             p_storage_class != SpvStorageClassCrossWorkgroup &&
2550             p_storage_class != SpvStorageClassWorkgroup &&
2551             p_storage_class != SpvStorageClassFunction) {
2552           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2553                  << ext_inst_name() << ": "
2554                  << "expected operand P storage class to be Generic, "
2555                     "CrossWorkgroup, Workgroup or Function";
2556         }
2557 
2558         if (!_.IsFloatScalarType(p_data_type) ||
2559             _.GetBitWidth(p_data_type) != 16) {
2560           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2561                  << ext_inst_name() << ": "
2562                  << "expected operand P data type to be 16-bit float scalar";
2563         }
2564 
2565         // Rounding mode enum is checked by assembler.
2566         break;
2567       }
2568 
2569       case OpenCLLIB::Shuffle:
2570       case OpenCLLIB::Shuffle2: {
2571         if (!_.IsFloatVectorType(result_type) &&
2572             !_.IsIntVectorType(result_type)) {
2573           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2574                  << ext_inst_name() << ": "
2575                  << "expected Result Type to be an int or float vector type";
2576         }
2577 
2578         const uint32_t result_num_components = _.GetDimension(result_type);
2579         if (result_num_components != 2 && result_num_components != 4 &&
2580             result_num_components != 8 && result_num_components != 16) {
2581           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2582                  << ext_inst_name() << ": "
2583                  << "expected Result Type to have 2, 4, 8 or 16 components";
2584         }
2585 
2586         uint32_t operand_index = 4;
2587         const uint32_t x_type = _.GetOperandTypeId(inst, operand_index++);
2588 
2589         if (ext_inst_key == OpenCLLIB::Shuffle2) {
2590           const uint32_t y_type = _.GetOperandTypeId(inst, operand_index++);
2591           if (x_type != y_type) {
2592             return _.diag(SPV_ERROR_INVALID_DATA, inst)
2593                    << ext_inst_name() << ": "
2594                    << "expected operands X and Y to be of the same type";
2595           }
2596         }
2597 
2598         const uint32_t shuffle_mask_type =
2599             _.GetOperandTypeId(inst, operand_index++);
2600 
2601         if (!_.IsFloatVectorType(x_type) && !_.IsIntVectorType(x_type)) {
2602           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2603                  << ext_inst_name() << ": "
2604                  << "expected operand X to be an int or float vector";
2605         }
2606 
2607         const uint32_t x_num_components = _.GetDimension(x_type);
2608         if (x_num_components != 2 && x_num_components != 4 &&
2609             x_num_components != 8 && x_num_components != 16) {
2610           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2611                  << ext_inst_name() << ": "
2612                  << "expected operand X to have 2, 4, 8 or 16 components";
2613         }
2614 
2615         const uint32_t result_component_type = _.GetComponentType(result_type);
2616 
2617         if (result_component_type != _.GetComponentType(x_type)) {
2618           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2619                  << ext_inst_name() << ": "
2620                  << "expected operand X and Result Type to have equal "
2621                     "component types";
2622         }
2623 
2624         if (!_.IsIntVectorType(shuffle_mask_type)) {
2625           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2626                  << ext_inst_name() << ": "
2627                  << "expected operand Shuffle Mask to be an int vector";
2628         }
2629 
2630         if (result_num_components != _.GetDimension(shuffle_mask_type)) {
2631           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2632                  << ext_inst_name() << ": "
2633                  << "expected operand Shuffle Mask to have the same number of "
2634                     "components as Result Type";
2635         }
2636 
2637         if (_.GetBitWidth(result_component_type) !=
2638             _.GetBitWidth(shuffle_mask_type)) {
2639           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2640                  << ext_inst_name() << ": "
2641                  << "expected operand Shuffle Mask components to have the same "
2642                     "bit width as Result Type components";
2643         }
2644         break;
2645       }
2646 
2647       case OpenCLLIB::Printf: {
2648         if (!_.IsIntScalarType(result_type) ||
2649             _.GetBitWidth(result_type) != 32) {
2650           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2651                  << ext_inst_name() << ": "
2652                  << "expected Result Type to be a 32-bit int type";
2653         }
2654 
2655         const uint32_t format_type = _.GetOperandTypeId(inst, 4);
2656         uint32_t format_storage_class = 0;
2657         uint32_t format_data_type = 0;
2658         if (!_.GetPointerTypeInfo(format_type, &format_data_type,
2659                                   &format_storage_class)) {
2660           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2661                  << ext_inst_name() << ": "
2662                  << "expected operand Format to be a pointer";
2663         }
2664 
2665         if (format_storage_class != SpvStorageClassUniformConstant) {
2666           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2667                  << ext_inst_name() << ": "
2668                  << "expected Format storage class to be UniformConstant";
2669         }
2670 
2671         if (!_.IsIntScalarType(format_data_type) ||
2672             _.GetBitWidth(format_data_type) != 8) {
2673           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2674                  << ext_inst_name() << ": "
2675                  << "expected Format data type to be 8-bit int";
2676         }
2677         break;
2678       }
2679 
2680       case OpenCLLIB::Prefetch: {
2681         if (_.GetIdOpcode(result_type) != SpvOpTypeVoid) {
2682           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2683                  << ext_inst_name() << ": expected Result Type to be void";
2684         }
2685 
2686         const uint32_t p_type = _.GetOperandTypeId(inst, 4);
2687         const uint32_t num_elements_type = _.GetOperandTypeId(inst, 5);
2688 
2689         uint32_t p_storage_class = 0;
2690         uint32_t p_data_type = 0;
2691         if (!_.GetPointerTypeInfo(p_type, &p_data_type, &p_storage_class)) {
2692           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2693                  << ext_inst_name() << ": "
2694                  << "expected operand Ptr to be a pointer";
2695         }
2696 
2697         if (p_storage_class != SpvStorageClassCrossWorkgroup) {
2698           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2699                  << ext_inst_name() << ": "
2700                  << "expected operand Ptr storage class to be CrossWorkgroup";
2701         }
2702 
2703         if (!_.IsFloatScalarOrVectorType(p_data_type) &&
2704             !_.IsIntScalarOrVectorType(p_data_type)) {
2705           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2706                  << ext_inst_name() << ": "
2707                  << "expected Ptr data type to be int or float scalar or "
2708                     "vector";
2709         }
2710 
2711         const uint32_t num_components = _.GetDimension(p_data_type);
2712         if (num_components > 4 && num_components != 8 && num_components != 16) {
2713           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2714                  << ext_inst_name() << ": "
2715                  << "expected Result Type to be a scalar or a vector with 2, "
2716                     "3, 4, 8 or 16 components";
2717         }
2718 
2719         const uint32_t size_t_bit_width = GetSizeTBitWidth(_);
2720         if (!size_t_bit_width) {
2721           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2722                  << ext_inst_name()
2723                  << " can only be used with physical addressing models";
2724         }
2725 
2726         if (!_.IsIntScalarType(num_elements_type) ||
2727             _.GetBitWidth(num_elements_type) != size_t_bit_width) {
2728           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2729                  << ext_inst_name() << ": "
2730                  << "expected operand Num Elements to be of type size_t ("
2731                  << size_t_bit_width
2732                  << "-bit integer for the addressing model used in the module)";
2733         }
2734         break;
2735       }
2736     }
2737   } else if (ext_inst_type == SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100 ||
2738              ext_inst_type ==
2739                  SPV_EXT_INST_TYPE_NONSEMANTIC_SHADER_DEBUGINFO_100) {
2740     if (!_.IsVoidType(result_type)) {
2741       return _.diag(SPV_ERROR_INVALID_DATA, inst)
2742              << ext_inst_name() << ": "
2743              << "expected result type must be a result id of "
2744              << "OpTypeVoid";
2745     }
2746 
2747     const bool vulkanDebugInfo =
2748         ext_inst_type == SPV_EXT_INST_TYPE_NONSEMANTIC_SHADER_DEBUGINFO_100;
2749 
2750     auto num_words = inst->words().size();
2751 
2752     // Handle any non-common NonSemanticShaderDebugInfo instructions.
2753     if (vulkanDebugInfo) {
2754       const NonSemanticShaderDebugInfo100Instructions ext_inst_key =
2755           NonSemanticShaderDebugInfo100Instructions(ext_inst_index);
2756       switch (ext_inst_key) {
2757         // The following block of instructions will be handled by the common
2758         // validation.
2759         case NonSemanticShaderDebugInfo100DebugInfoNone:
2760         case NonSemanticShaderDebugInfo100DebugCompilationUnit:
2761         case NonSemanticShaderDebugInfo100DebugTypeBasic:
2762         case NonSemanticShaderDebugInfo100DebugTypePointer:
2763         case NonSemanticShaderDebugInfo100DebugTypeQualifier:
2764         case NonSemanticShaderDebugInfo100DebugTypeArray:
2765         case NonSemanticShaderDebugInfo100DebugTypeVector:
2766         case NonSemanticShaderDebugInfo100DebugTypedef:
2767         case NonSemanticShaderDebugInfo100DebugTypeFunction:
2768         case NonSemanticShaderDebugInfo100DebugTypeEnum:
2769         case NonSemanticShaderDebugInfo100DebugTypeComposite:
2770         case NonSemanticShaderDebugInfo100DebugTypeMember:
2771         case NonSemanticShaderDebugInfo100DebugTypeInheritance:
2772         case NonSemanticShaderDebugInfo100DebugTypePtrToMember:
2773         case NonSemanticShaderDebugInfo100DebugTypeTemplate:
2774         case NonSemanticShaderDebugInfo100DebugTypeTemplateParameter:
2775         case NonSemanticShaderDebugInfo100DebugTypeTemplateTemplateParameter:
2776         case NonSemanticShaderDebugInfo100DebugTypeTemplateParameterPack:
2777         case NonSemanticShaderDebugInfo100DebugGlobalVariable:
2778         case NonSemanticShaderDebugInfo100DebugFunctionDeclaration:
2779         case NonSemanticShaderDebugInfo100DebugFunction:
2780         case NonSemanticShaderDebugInfo100DebugLexicalBlock:
2781         case NonSemanticShaderDebugInfo100DebugLexicalBlockDiscriminator:
2782         case NonSemanticShaderDebugInfo100DebugScope:
2783         case NonSemanticShaderDebugInfo100DebugNoScope:
2784         case NonSemanticShaderDebugInfo100DebugInlinedAt:
2785         case NonSemanticShaderDebugInfo100DebugLocalVariable:
2786         case NonSemanticShaderDebugInfo100DebugInlinedVariable:
2787         case NonSemanticShaderDebugInfo100DebugDeclare:
2788         case NonSemanticShaderDebugInfo100DebugValue:
2789         case NonSemanticShaderDebugInfo100DebugOperation:
2790         case NonSemanticShaderDebugInfo100DebugExpression:
2791         case NonSemanticShaderDebugInfo100DebugMacroDef:
2792         case NonSemanticShaderDebugInfo100DebugMacroUndef:
2793         case NonSemanticShaderDebugInfo100DebugImportedEntity:
2794         case NonSemanticShaderDebugInfo100DebugSource:
2795           break;
2796         case NonSemanticShaderDebugInfo100DebugTypeMatrix: {
2797           CHECK_DEBUG_OPERAND("Vector Type", CommonDebugInfoDebugTypeVector, 5);
2798 
2799           CHECK_CONST_UINT_OPERAND("Vector Count", 6);
2800 
2801           uint32_t vector_count = inst->word(6);
2802           uint64_t const_val;
2803           if (!_.GetConstantValUint64(vector_count, &const_val)) {
2804             return _.diag(SPV_ERROR_INVALID_DATA, inst)
2805                    << ext_inst_name()
2806                    << ": Vector Count must be 32-bit integer OpConstant";
2807           }
2808 
2809           vector_count = const_val & 0xffffffff;
2810           if (!vector_count || vector_count > 4) {
2811             return _.diag(SPV_ERROR_INVALID_DATA, inst)
2812                    << ext_inst_name() << ": Vector Count must be positive "
2813                    << "integer less than or equal to 4";
2814           }
2815           break;
2816         }
2817         // TODO: Add validation rules for remaining cases as well.
2818         case NonSemanticShaderDebugInfo100DebugFunctionDefinition:
2819         case NonSemanticShaderDebugInfo100DebugSourceContinued:
2820         case NonSemanticShaderDebugInfo100DebugLine:
2821         case NonSemanticShaderDebugInfo100DebugNoLine:
2822         case NonSemanticShaderDebugInfo100DebugBuildIdentifier:
2823         case NonSemanticShaderDebugInfo100DebugStoragePath:
2824         case NonSemanticShaderDebugInfo100DebugEntryPoint:
2825           break;
2826         case NonSemanticShaderDebugInfo100InstructionsMax:
2827           assert(0);
2828           break;
2829       }
2830     }
2831 
2832     // Handle any non-common OpenCL insts, then common
2833     if (ext_inst_type != SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100 ||
2834         OpenCLDebugInfo100Instructions(ext_inst_index) !=
2835             OpenCLDebugInfo100DebugModuleINTEL) {
2836       const CommonDebugInfoInstructions ext_inst_key =
2837           CommonDebugInfoInstructions(ext_inst_index);
2838       switch (ext_inst_key) {
2839         case CommonDebugInfoDebugInfoNone:
2840         case CommonDebugInfoDebugNoScope:
2841           break;
2842           // The binary parser validates the opcode for DebugInfoNone,
2843           // DebugNoScope, DebugOperation. We just check the parameters to
2844           // DebugOperation are properly constants for vulkan debug info.
2845         case CommonDebugInfoDebugOperation: {
2846           CHECK_CONST_UINT_OPERAND("Operation", 5);
2847           for (uint32_t i = 6; i < num_words; ++i) {
2848             CHECK_CONST_UINT_OPERAND("Operand", i);
2849           }
2850           break;
2851         }
2852         case CommonDebugInfoDebugCompilationUnit: {
2853           CHECK_CONST_UINT_OPERAND("Version", 5);
2854           CHECK_CONST_UINT_OPERAND("DWARF Version", 6);
2855           CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource, 7);
2856           CHECK_CONST_UINT_OPERAND("Language", 8);
2857           break;
2858         }
2859         case CommonDebugInfoDebugSource: {
2860           CHECK_OPERAND("File", SpvOpString, 5);
2861           if (num_words == 7) CHECK_OPERAND("Text", SpvOpString, 6);
2862           break;
2863         }
2864         case CommonDebugInfoDebugTypeBasic: {
2865           CHECK_OPERAND("Name", SpvOpString, 5);
2866           CHECK_OPERAND("Size", SpvOpConstant, 6);
2867           CHECK_CONST_UINT_OPERAND("Encoding", 7);
2868           break;
2869         }
2870         case CommonDebugInfoDebugTypePointer: {
2871           auto validate_base_type =
2872               ValidateOperandBaseType(_, inst, 5, ext_inst_name);
2873           if (validate_base_type != SPV_SUCCESS) return validate_base_type;
2874           CHECK_CONST_UINT_OPERAND("Storage Class", 6);
2875           CHECK_CONST_UINT_OPERAND("Flags", 7);
2876           break;
2877         }
2878         case CommonDebugInfoDebugTypeQualifier: {
2879           auto validate_base_type =
2880               ValidateOperandBaseType(_, inst, 5, ext_inst_name);
2881           if (validate_base_type != SPV_SUCCESS) return validate_base_type;
2882           CHECK_CONST_UINT_OPERAND("Type Qualifier", 6);
2883           break;
2884         }
2885         case CommonDebugInfoDebugTypeVector: {
2886           auto validate_base_type =
2887               ValidateOperandBaseType(_, inst, 5, ext_inst_name);
2888           if (validate_base_type != SPV_SUCCESS) return validate_base_type;
2889 
2890           CHECK_CONST_UINT_OPERAND("Component Count", 6);
2891           uint32_t component_count = inst->word(6);
2892           if (vulkanDebugInfo) {
2893             uint64_t const_val;
2894             if (!_.GetConstantValUint64(component_count, &const_val)) {
2895               return _.diag(SPV_ERROR_INVALID_DATA, inst)
2896                      << ext_inst_name()
2897                      << ": Component Count must be 32-bit integer OpConstant";
2898             }
2899             component_count = const_val & 0xffffffff;
2900           }
2901 
2902           if (!component_count || component_count > 4) {
2903             return _.diag(SPV_ERROR_INVALID_DATA, inst)
2904                    << ext_inst_name() << ": Component Count must be positive "
2905                    << "integer less than or equal to 4";
2906           }
2907           break;
2908         }
2909         case CommonDebugInfoDebugTypeArray: {
2910           auto validate_base_type = ValidateOperandDebugType(
2911               _, "Base Type", inst, 5, ext_inst_name, false);
2912           if (validate_base_type != SPV_SUCCESS) return validate_base_type;
2913           for (uint32_t i = 6; i < num_words; ++i) {
2914             bool invalid = false;
2915             auto* component_count = _.FindDef(inst->word(i));
2916             if (IsConstIntScalarTypeWith32Or64Bits(_, component_count)) {
2917               // TODO: We need a spec discussion for the runtime array for
2918               // OpenCL.
2919               if (!vulkanDebugInfo && !component_count->word(3)) {
2920                 invalid = true;
2921               }
2922             } else if (component_count->words().size() > 6 &&
2923                        (CommonDebugInfoInstructions(component_count->word(4)) ==
2924                             CommonDebugInfoDebugLocalVariable ||
2925                         CommonDebugInfoInstructions(component_count->word(4)) ==
2926                             CommonDebugInfoDebugGlobalVariable)) {
2927               auto* component_count_type = _.FindDef(component_count->word(6));
2928               if (component_count_type->words().size() > 7) {
2929                 uint32_t encoding = component_count_type->word(7);
2930                 if (CommonDebugInfoInstructions(component_count_type->word(
2931                         4)) != CommonDebugInfoDebugTypeBasic ||
2932                     (vulkanDebugInfo && !IsUint32Constant(_, encoding)) ||
2933                     OpenCLDebugInfo100DebugBaseTypeAttributeEncoding(
2934                         vulkanDebugInfo
2935                             ? GetUint32Constant(_, encoding)
2936                             : encoding) != OpenCLDebugInfo100Unsigned) {
2937                   invalid = true;
2938                 } else {
2939                   // DebugTypeBasic for DebugLocalVariable/DebugGlobalVariable
2940                   // must have Unsigned encoding and 32 or 64 as its size in
2941                   // bits.
2942                   Instruction* size_in_bits =
2943                       _.FindDef(component_count_type->word(6));
2944                   if (!_.IsIntScalarType(size_in_bits->type_id()) ||
2945                       (size_in_bits->word(3) != 32 &&
2946                        size_in_bits->word(3) != 64)) {
2947                     invalid = true;
2948                   }
2949                 }
2950               } else {
2951                 invalid = true;
2952               }
2953             } else {
2954               invalid = true;
2955             }
2956             if (invalid) {
2957               return _.diag(SPV_ERROR_INVALID_DATA, inst)
2958                      << ext_inst_name() << ": Component Count must be "
2959                      << "OpConstant with a 32- or 64-bits integer scalar type "
2960                         "or "
2961                      << "DebugGlobalVariable or DebugLocalVariable with a 32- "
2962                         "or "
2963                      << "64-bits unsigned integer scalar type";
2964             }
2965           }
2966           break;
2967         }
2968         case CommonDebugInfoDebugTypedef: {
2969           CHECK_OPERAND("Name", SpvOpString, 5);
2970           auto validate_base_type =
2971               ValidateOperandBaseType(_, inst, 6, ext_inst_name);
2972           if (validate_base_type != SPV_SUCCESS) return validate_base_type;
2973           CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource, 7);
2974           CHECK_CONST_UINT_OPERAND("Line", 8);
2975           CHECK_CONST_UINT_OPERAND("Column", 9);
2976           auto validate_parent =
2977               ValidateOperandLexicalScope(_, "Parent", inst, 10, ext_inst_name);
2978           if (validate_parent != SPV_SUCCESS) return validate_parent;
2979           break;
2980         }
2981         case CommonDebugInfoDebugTypeFunction: {
2982           CHECK_CONST_UINT_OPERAND("Flags", 5);
2983           auto* return_type = _.FindDef(inst->word(6));
2984           // TODO: We need a spec discussion that we have to allow return and
2985           // parameter types of a DebugTypeFunction to have template parameter.
2986           if (return_type->opcode() != SpvOpTypeVoid) {
2987             auto validate_return = ValidateOperandDebugType(
2988                 _, "Return Type", inst, 6, ext_inst_name, true);
2989             if (validate_return != SPV_SUCCESS) return validate_return;
2990           }
2991           for (uint32_t word_index = 7; word_index < num_words; ++word_index) {
2992             auto validate_param = ValidateOperandDebugType(
2993                 _, "Parameter Types", inst, word_index, ext_inst_name, true);
2994             if (validate_param != SPV_SUCCESS) return validate_param;
2995           }
2996           break;
2997         }
2998         case CommonDebugInfoDebugTypeEnum: {
2999           CHECK_OPERAND("Name", SpvOpString, 5);
3000           if (!DoesDebugInfoOperandMatchExpectation(
3001                   _,
3002                   [](CommonDebugInfoInstructions dbg_inst) {
3003                     return dbg_inst == CommonDebugInfoDebugInfoNone;
3004                   },
3005                   inst, 6)) {
3006             auto validate_underlying_type = ValidateOperandDebugType(
3007                 _, "Underlying Types", inst, 6, ext_inst_name, false);
3008             if (validate_underlying_type != SPV_SUCCESS)
3009               return validate_underlying_type;
3010           }
3011           CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource, 7);
3012           CHECK_CONST_UINT_OPERAND("Line", 8);
3013           CHECK_CONST_UINT_OPERAND("Column", 9);
3014           auto validate_parent =
3015               ValidateOperandLexicalScope(_, "Parent", inst, 10, ext_inst_name);
3016           if (validate_parent != SPV_SUCCESS) return validate_parent;
3017           CHECK_OPERAND("Size", SpvOpConstant, 11);
3018           auto* size = _.FindDef(inst->word(11));
3019           if (!_.IsIntScalarType(size->type_id()) || !size->word(3)) {
3020             return _.diag(SPV_ERROR_INVALID_DATA, inst)
3021                    << ext_inst_name() << ": expected operand Size is a "
3022                    << "positive integer";
3023           }
3024           CHECK_CONST_UINT_OPERAND("Flags", 12);
3025           for (uint32_t word_index = 13; word_index + 1 < num_words;
3026                word_index += 2) {
3027             CHECK_OPERAND("Value", SpvOpConstant, word_index);
3028             CHECK_OPERAND("Name", SpvOpString, word_index + 1);
3029           }
3030           break;
3031         }
3032         case CommonDebugInfoDebugTypeComposite: {
3033           CHECK_OPERAND("Name", SpvOpString, 5);
3034           CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource, 7);
3035           CHECK_CONST_UINT_OPERAND("Line", 8);
3036           CHECK_CONST_UINT_OPERAND("Column", 9);
3037           auto validate_parent =
3038               ValidateOperandLexicalScope(_, "Parent", inst, 10, ext_inst_name);
3039           if (validate_parent != SPV_SUCCESS) return validate_parent;
3040           CHECK_OPERAND("Linkage Name", SpvOpString, 11);
3041           if (!DoesDebugInfoOperandMatchExpectation(
3042                   _,
3043                   [](CommonDebugInfoInstructions dbg_inst) {
3044                     return dbg_inst == CommonDebugInfoDebugInfoNone;
3045                   },
3046                   inst, 12)) {
3047             CHECK_OPERAND("Size", SpvOpConstant, 12);
3048           }
3049           CHECK_CONST_UINT_OPERAND("Flags", 13);
3050           for (uint32_t word_index = 14; word_index < num_words; ++word_index) {
3051             if (!DoesDebugInfoOperandMatchExpectation(
3052                     _,
3053                     [](CommonDebugInfoInstructions dbg_inst) {
3054                       return dbg_inst == CommonDebugInfoDebugTypeMember ||
3055                              dbg_inst == CommonDebugInfoDebugFunction ||
3056                              dbg_inst == CommonDebugInfoDebugTypeInheritance;
3057                     },
3058                     inst, word_index)) {
3059               return _.diag(SPV_ERROR_INVALID_DATA, inst)
3060                      << ext_inst_name() << ": "
3061                      << "expected operand Members "
3062                      << "must be DebugTypeMember, DebugFunction, or "
3063                         "DebugTypeInheritance";
3064             }
3065           }
3066           break;
3067         }
3068         case CommonDebugInfoDebugTypeMember: {
3069           CHECK_OPERAND("Name", SpvOpString, 5);
3070           // TODO: We need a spec discussion that we have to allow member types
3071           // to have template parameter.
3072           auto validate_type =
3073               ValidateOperandDebugType(_, "Type", inst, 6, ext_inst_name, true);
3074           if (validate_type != SPV_SUCCESS) return validate_type;
3075           CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource, 7);
3076           CHECK_CONST_UINT_OPERAND("Line", 8);
3077           CHECK_CONST_UINT_OPERAND("Column", 9);
3078           // NonSemantic.Shader.DebugInfo doesn't have the Parent operand
3079           if (vulkanDebugInfo) {
3080             CHECK_OPERAND("Offset", SpvOpConstant, 10);
3081             CHECK_OPERAND("Size", SpvOpConstant, 11);
3082             CHECK_CONST_UINT_OPERAND("Flags", 12);
3083             if (num_words == 14) CHECK_OPERAND("Value", SpvOpConstant, 13);
3084           } else {
3085             CHECK_DEBUG_OPERAND("Parent", CommonDebugInfoDebugTypeComposite,
3086                                 10);
3087             CHECK_OPERAND("Offset", SpvOpConstant, 11);
3088             CHECK_OPERAND("Size", SpvOpConstant, 12);
3089             CHECK_CONST_UINT_OPERAND("Flags", 13);
3090             if (num_words == 15) CHECK_OPERAND("Value", SpvOpConstant, 14);
3091           }
3092           break;
3093         }
3094         case CommonDebugInfoDebugTypeInheritance: {
3095           CHECK_DEBUG_OPERAND("Child", CommonDebugInfoDebugTypeComposite, 5);
3096           auto* debug_inst = _.FindDef(inst->word(5));
3097           auto composite_type =
3098               OpenCLDebugInfo100DebugCompositeType(debug_inst->word(6));
3099           if (composite_type != OpenCLDebugInfo100Class &&
3100               composite_type != OpenCLDebugInfo100Structure) {
3101             return _.diag(SPV_ERROR_INVALID_DATA, inst)
3102                    << ext_inst_name() << ": "
3103                    << "expected operand Child must be class or struct debug "
3104                       "type";
3105           }
3106           CHECK_DEBUG_OPERAND("Parent", CommonDebugInfoDebugTypeComposite, 6);
3107           debug_inst = _.FindDef(inst->word(6));
3108           composite_type =
3109               OpenCLDebugInfo100DebugCompositeType(debug_inst->word(6));
3110           if (composite_type != OpenCLDebugInfo100Class &&
3111               composite_type != OpenCLDebugInfo100Structure) {
3112             return _.diag(SPV_ERROR_INVALID_DATA, inst)
3113                    << ext_inst_name() << ": "
3114                    << "expected operand Parent must be class or struct debug "
3115                       "type";
3116           }
3117           CHECK_OPERAND("Offset", SpvOpConstant, 7);
3118           CHECK_OPERAND("Size", SpvOpConstant, 8);
3119           CHECK_CONST_UINT_OPERAND("Flags", 9);
3120           break;
3121         }
3122         case CommonDebugInfoDebugFunction: {
3123           CHECK_OPERAND("Name", SpvOpString, 5);
3124           auto validate_type = ValidateOperandDebugType(_, "Type", inst, 6,
3125                                                         ext_inst_name, false);
3126           if (validate_type != SPV_SUCCESS) return validate_type;
3127           CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource, 7);
3128           CHECK_CONST_UINT_OPERAND("Line", 8);
3129           CHECK_CONST_UINT_OPERAND("Column", 9);
3130           auto validate_parent =
3131               ValidateOperandLexicalScope(_, "Parent", inst, 10, ext_inst_name);
3132           if (validate_parent != SPV_SUCCESS) return validate_parent;
3133           CHECK_OPERAND("Linkage Name", SpvOpString, 11);
3134           CHECK_CONST_UINT_OPERAND("Flags", 12);
3135           CHECK_CONST_UINT_OPERAND("Scope Line", 13);
3136           // NonSemantic.Shader.DebugInfo.100 doesn't include a reference to the
3137           // OpFunction
3138           if (vulkanDebugInfo) {
3139             if (num_words == 15) {
3140               CHECK_DEBUG_OPERAND("Declaration",
3141                                   CommonDebugInfoDebugFunctionDeclaration, 14);
3142             }
3143           } else {
3144             if (!DoesDebugInfoOperandMatchExpectation(
3145                     _,
3146                     [](CommonDebugInfoInstructions dbg_inst) {
3147                       return dbg_inst == CommonDebugInfoDebugInfoNone;
3148                     },
3149                     inst, 14)) {
3150               CHECK_OPERAND("Function", SpvOpFunction, 14);
3151             }
3152             if (num_words == 16) {
3153               CHECK_DEBUG_OPERAND("Declaration",
3154                                   CommonDebugInfoDebugFunctionDeclaration, 15);
3155             }
3156           }
3157           break;
3158         }
3159         case CommonDebugInfoDebugFunctionDeclaration: {
3160           CHECK_OPERAND("Name", SpvOpString, 5);
3161           auto validate_type = ValidateOperandDebugType(_, "Type", inst, 6,
3162                                                         ext_inst_name, false);
3163           if (validate_type != SPV_SUCCESS) return validate_type;
3164           CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource, 7);
3165           CHECK_CONST_UINT_OPERAND("Line", 8);
3166           CHECK_CONST_UINT_OPERAND("Column", 9);
3167           auto validate_parent =
3168               ValidateOperandLexicalScope(_, "Parent", inst, 10, ext_inst_name);
3169           if (validate_parent != SPV_SUCCESS) return validate_parent;
3170           CHECK_OPERAND("Linkage Name", SpvOpString, 11);
3171           CHECK_CONST_UINT_OPERAND("Flags", 12);
3172           break;
3173         }
3174         case CommonDebugInfoDebugLexicalBlock: {
3175           CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource, 5);
3176           CHECK_CONST_UINT_OPERAND("Line", 6);
3177           CHECK_CONST_UINT_OPERAND("Column", 7);
3178           auto validate_parent =
3179               ValidateOperandLexicalScope(_, "Parent", inst, 8, ext_inst_name);
3180           if (validate_parent != SPV_SUCCESS) return validate_parent;
3181           if (num_words == 10) CHECK_OPERAND("Name", SpvOpString, 9);
3182           break;
3183         }
3184         case CommonDebugInfoDebugScope: {
3185           auto validate_scope =
3186               ValidateOperandLexicalScope(_, "Scope", inst, 5, ext_inst_name);
3187           if (validate_scope != SPV_SUCCESS) return validate_scope;
3188           if (num_words == 7) {
3189             CHECK_DEBUG_OPERAND("Inlined At", CommonDebugInfoDebugInlinedAt, 6);
3190           }
3191           break;
3192         }
3193         case CommonDebugInfoDebugLocalVariable: {
3194           CHECK_OPERAND("Name", SpvOpString, 5);
3195           // TODO: We need a spec discussion that we have to allow local
3196           // variable types to have template parameter.
3197           auto validate_type =
3198               ValidateOperandDebugType(_, "Type", inst, 6, ext_inst_name, true);
3199           if (validate_type != SPV_SUCCESS) return validate_type;
3200           CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource, 7);
3201           CHECK_CONST_UINT_OPERAND("Line", 8);
3202           CHECK_CONST_UINT_OPERAND("Column", 9);
3203           auto validate_parent =
3204               ValidateOperandLexicalScope(_, "Parent", inst, 10, ext_inst_name);
3205           if (validate_parent != SPV_SUCCESS) return validate_parent;
3206           CHECK_CONST_UINT_OPERAND("Flags", 11);
3207           if (num_words == 13) {
3208             CHECK_CONST_UINT_OPERAND("ArgNumber", 12);
3209           }
3210           break;
3211         }
3212         case CommonDebugInfoDebugDeclare: {
3213           CHECK_DEBUG_OPERAND("Local Variable",
3214                               CommonDebugInfoDebugLocalVariable, 5);
3215           auto* operand = _.FindDef(inst->word(6));
3216           if (operand->opcode() != SpvOpVariable &&
3217               operand->opcode() != SpvOpFunctionParameter) {
3218             return _.diag(SPV_ERROR_INVALID_DATA, inst)
3219                    << ext_inst_name() << ": "
3220                    << "expected operand Variable must be a result id of "
3221                       "OpVariable or OpFunctionParameter";
3222           }
3223 
3224           CHECK_DEBUG_OPERAND("Expression", CommonDebugInfoDebugExpression, 7);
3225 
3226           if (vulkanDebugInfo) {
3227             for (uint32_t word_index = 8; word_index < num_words;
3228                  ++word_index) {
3229               auto index_inst = _.FindDef(inst->word(word_index));
3230               auto type_id = index_inst != nullptr ? index_inst->type_id() : 0;
3231               if (type_id == 0 || !IsIntScalar(_, type_id, false, false))
3232                 return _.diag(SPV_ERROR_INVALID_DATA, inst)
3233                        << ext_inst_name() << ": "
3234                        << "expected index must be scalar integer";
3235             }
3236           }
3237           break;
3238         }
3239         case CommonDebugInfoDebugExpression: {
3240           for (uint32_t word_index = 5; word_index < num_words; ++word_index) {
3241             CHECK_DEBUG_OPERAND("Operation", CommonDebugInfoDebugOperation,
3242                                 word_index);
3243           }
3244           break;
3245         }
3246         case CommonDebugInfoDebugTypeTemplate: {
3247           if (!DoesDebugInfoOperandMatchExpectation(
3248                   _,
3249                   [](CommonDebugInfoInstructions dbg_inst) {
3250                     return dbg_inst == CommonDebugInfoDebugTypeComposite ||
3251                            dbg_inst == CommonDebugInfoDebugFunction;
3252                   },
3253                   inst, 5)) {
3254             return _.diag(SPV_ERROR_INVALID_DATA, inst)
3255                    << ext_inst_name() << ": "
3256                    << "expected operand Target must be DebugTypeComposite "
3257                    << "or DebugFunction";
3258           }
3259           for (uint32_t word_index = 6; word_index < num_words; ++word_index) {
3260             if (!DoesDebugInfoOperandMatchExpectation(
3261                     _,
3262                     [](CommonDebugInfoInstructions dbg_inst) {
3263                       return dbg_inst ==
3264                                  CommonDebugInfoDebugTypeTemplateParameter ||
3265                              dbg_inst ==
3266                                  CommonDebugInfoDebugTypeTemplateTemplateParameter;
3267                     },
3268                     inst, word_index)) {
3269               return _.diag(SPV_ERROR_INVALID_DATA, inst)
3270                      << ext_inst_name() << ": "
3271                      << "expected operand Parameters must be "
3272                      << "DebugTypeTemplateParameter or "
3273                      << "DebugTypeTemplateTemplateParameter";
3274             }
3275           }
3276           break;
3277         }
3278         case CommonDebugInfoDebugTypeTemplateParameter: {
3279           CHECK_OPERAND("Name", SpvOpString, 5);
3280           auto validate_actual_type = ValidateOperandDebugType(
3281               _, "Actual Type", inst, 6, ext_inst_name, false);
3282           if (validate_actual_type != SPV_SUCCESS) return validate_actual_type;
3283           if (!DoesDebugInfoOperandMatchExpectation(
3284                   _,
3285                   [](CommonDebugInfoInstructions dbg_inst) {
3286                     return dbg_inst == CommonDebugInfoDebugInfoNone;
3287                   },
3288                   inst, 7)) {
3289             CHECK_OPERAND("Value", SpvOpConstant, 7);
3290           }
3291           CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource, 8);
3292           CHECK_CONST_UINT_OPERAND("Line", 9);
3293           CHECK_CONST_UINT_OPERAND("Column", 10);
3294           break;
3295         }
3296         case CommonDebugInfoDebugGlobalVariable: {
3297           CHECK_OPERAND("Name", SpvOpString, 5);
3298           auto validate_type = ValidateOperandDebugType(_, "Type", inst, 6,
3299                                                         ext_inst_name, false);
3300           if (validate_type != SPV_SUCCESS) return validate_type;
3301           CHECK_DEBUG_OPERAND("Source", CommonDebugInfoDebugSource, 7);
3302           CHECK_CONST_UINT_OPERAND("Line", 8);
3303           CHECK_CONST_UINT_OPERAND("Column", 9);
3304           auto validate_scope =
3305               ValidateOperandLexicalScope(_, "Scope", inst, 10, ext_inst_name);
3306           if (validate_scope != SPV_SUCCESS) return validate_scope;
3307           CHECK_OPERAND("Linkage Name", SpvOpString, 11);
3308           if (!DoesDebugInfoOperandMatchExpectation(
3309                   _,
3310                   [](CommonDebugInfoInstructions dbg_inst) {
3311                     return dbg_inst == CommonDebugInfoDebugInfoNone;
3312                   },
3313                   inst, 12)) {
3314             auto* operand = _.FindDef(inst->word(12));
3315             if (operand->opcode() != SpvOpVariable &&
3316                 operand->opcode() != SpvOpConstant) {
3317               return _.diag(SPV_ERROR_INVALID_DATA, inst)
3318                      << ext_inst_name() << ": "
3319                      << "expected operand Variable must be a result id of "
3320                         "OpVariable or OpConstant or DebugInfoNone";
3321             }
3322           }
3323           if (num_words == 15) {
3324             CHECK_DEBUG_OPERAND("Static Member Declaration",
3325                                 CommonDebugInfoDebugTypeMember, 14);
3326           }
3327           break;
3328         }
3329         case CommonDebugInfoDebugInlinedAt: {
3330           CHECK_CONST_UINT_OPERAND("Line", 5);
3331           auto validate_scope =
3332               ValidateOperandLexicalScope(_, "Scope", inst, 6, ext_inst_name);
3333           if (validate_scope != SPV_SUCCESS) return validate_scope;
3334           if (num_words == 8) {
3335             CHECK_DEBUG_OPERAND("Inlined", CommonDebugInfoDebugInlinedAt, 7);
3336           }
3337           break;
3338         }
3339         case CommonDebugInfoDebugValue: {
3340           CHECK_DEBUG_OPERAND("Local Variable",
3341                               CommonDebugInfoDebugLocalVariable, 5);
3342           CHECK_DEBUG_OPERAND("Expression", CommonDebugInfoDebugExpression, 7);
3343 
3344           for (uint32_t word_index = 8; word_index < num_words; ++word_index) {
3345             // TODO: The following code simply checks if it is a const int
3346             // scalar or a DebugLocalVariable or DebugGlobalVariable, but we
3347             // have to check it using the same validation for Indexes of
3348             // OpAccessChain.
3349             if (!IsConstWithIntScalarType(_, inst, word_index) &&
3350                 !IsDebugVariableWithIntScalarType(_, inst, word_index)) {
3351               return _.diag(SPV_ERROR_INVALID_DATA, inst)
3352                      << ext_inst_name() << ": expected operand Indexes is "
3353                      << "OpConstant, DebugGlobalVariable, or "
3354                      << "type is OpConstant with an integer scalar type";
3355             }
3356           }
3357           break;
3358         }
3359 
3360         // TODO: Add validation rules for remaining cases as well.
3361         case CommonDebugInfoDebugTypePtrToMember:
3362         case CommonDebugInfoDebugTypeTemplateTemplateParameter:
3363         case CommonDebugInfoDebugTypeTemplateParameterPack:
3364         case CommonDebugInfoDebugLexicalBlockDiscriminator:
3365         case CommonDebugInfoDebugInlinedVariable:
3366         case CommonDebugInfoDebugMacroDef:
3367         case CommonDebugInfoDebugMacroUndef:
3368         case CommonDebugInfoDebugImportedEntity:
3369           break;
3370         case CommonDebugInfoInstructionsMax:
3371           assert(0);
3372           break;
3373       }
3374     }
3375   } else if (ext_inst_type == SPV_EXT_INST_TYPE_NONSEMANTIC_CLSPVREFLECTION) {
3376     auto import_inst = _.FindDef(inst->GetOperandAs<uint32_t>(2));
3377     const std::string name = import_inst->GetOperandAs<std::string>(1);
3378     const std::string reflection = "NonSemantic.ClspvReflection.";
3379     char* end_ptr;
3380     auto version_string = name.substr(reflection.size());
3381     if (version_string.empty()) {
3382       return _.diag(SPV_ERROR_INVALID_DATA, import_inst)
3383              << "Missing NonSemantic.ClspvReflection import version";
3384     }
3385     uint32_t version = static_cast<uint32_t>(
3386         std::strtoul(version_string.c_str(), &end_ptr, 10));
3387     if (end_ptr && *end_ptr != '\0') {
3388       return _.diag(SPV_ERROR_INVALID_DATA, import_inst)
3389              << "NonSemantic.ClspvReflection import does not encode the "
3390                 "version correctly";
3391     }
3392     if (version == 0 || version > NonSemanticClspvReflectionRevision) {
3393       return _.diag(SPV_ERROR_INVALID_DATA, import_inst)
3394              << "Unknown NonSemantic.ClspvReflection import version";
3395     }
3396 
3397     return ValidateClspvReflectionInstruction(_, inst, version);
3398   }
3399 
3400   return SPV_SUCCESS;
3401 }
3402 
ExtensionPass(ValidationState_t & _,const Instruction * inst)3403 spv_result_t ExtensionPass(ValidationState_t& _, const Instruction* inst) {
3404   const SpvOp opcode = inst->opcode();
3405   if (opcode == SpvOpExtension) return ValidateExtension(_, inst);
3406   if (opcode == SpvOpExtInstImport) return ValidateExtInstImport(_, inst);
3407   if (opcode == SpvOpExtInst) return ValidateExtInst(_, inst);
3408 
3409   return SPV_SUCCESS;
3410 }
3411 
3412 }  // namespace val
3413 }  // namespace spvtools
3414