• 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 
17 #include "source/val/validate.h"
18 
19 #include <sstream>
20 #include <string>
21 #include <vector>
22 
23 #include "source/diagnostic.h"
24 #include "source/enum_string_mapping.h"
25 #include "source/extensions.h"
26 #include "source/latest_version_glsl_std_450_header.h"
27 #include "source/latest_version_opencl_std_header.h"
28 #include "source/opcode.h"
29 #include "source/spirv_target_env.h"
30 #include "source/val/instruction.h"
31 #include "source/val/validation_state.h"
32 
33 namespace spvtools {
34 namespace val {
35 namespace {
36 
GetSizeTBitWidth(const ValidationState_t & _)37 uint32_t GetSizeTBitWidth(const ValidationState_t& _) {
38   if (_.addressing_model() == SpvAddressingModelPhysical32) return 32;
39 
40   if (_.addressing_model() == SpvAddressingModelPhysical64) return 64;
41 
42   return 0;
43 }
44 
45 }  // anonymous namespace
46 
ValidateExtension(ValidationState_t & _,const Instruction * inst)47 spv_result_t ValidateExtension(ValidationState_t& _, const Instruction* inst) {
48   if (spvIsWebGPUEnv(_.context()->target_env)) {
49     std::string extension = GetExtensionString(&(inst->c_inst()));
50 
51     if (extension != ExtensionToString(kSPV_KHR_vulkan_memory_model)) {
52       return _.diag(SPV_ERROR_INVALID_DATA, inst)
53              << "For WebGPU, the only valid parameter to OpExtension is "
54              << "\"" << ExtensionToString(kSPV_KHR_vulkan_memory_model)
55              << "\".";
56     }
57   }
58 
59   return SPV_SUCCESS;
60 }
61 
ValidateExtInstImport(ValidationState_t & _,const Instruction * inst)62 spv_result_t ValidateExtInstImport(ValidationState_t& _,
63                                    const Instruction* inst) {
64   if (spvIsWebGPUEnv(_.context()->target_env)) {
65     const auto name_id = 1;
66     const std::string name(reinterpret_cast<const char*>(
67         inst->words().data() + inst->operands()[name_id].offset));
68     if (name != "GLSL.std.450") {
69       return _.diag(SPV_ERROR_INVALID_DATA, inst)
70              << "For WebGPU, the only valid parameter to OpExtInstImport is "
71                 "\"GLSL.std.450\".";
72     }
73   }
74 
75   return SPV_SUCCESS;
76 }
77 
ValidateExtInst(ValidationState_t & _,const Instruction * inst)78 spv_result_t ValidateExtInst(ValidationState_t& _, const Instruction* inst) {
79   const uint32_t result_type = inst->type_id();
80   const uint32_t num_operands = static_cast<uint32_t>(inst->operands().size());
81 
82   const uint32_t ext_inst_set = inst->word(3);
83   const uint32_t ext_inst_index = inst->word(4);
84   const spv_ext_inst_type_t ext_inst_type =
85       spv_ext_inst_type_t(inst->ext_inst_type());
86 
87   auto ext_inst_name = [&_, ext_inst_set, ext_inst_type, ext_inst_index]() {
88     spv_ext_inst_desc desc = nullptr;
89     if (_.grammar().lookupExtInst(ext_inst_type, ext_inst_index, &desc) !=
90             SPV_SUCCESS ||
91         !desc) {
92       return std::string("Unknown ExtInst");
93     }
94 
95     auto* import_inst = _.FindDef(ext_inst_set);
96     assert(import_inst);
97 
98     std::ostringstream ss;
99     ss << reinterpret_cast<const char*>(import_inst->words().data() + 2);
100     ss << " ";
101     ss << desc->name;
102 
103     return ss.str();
104   };
105 
106   if (ext_inst_type == SPV_EXT_INST_TYPE_GLSL_STD_450) {
107     const GLSLstd450 ext_inst_key = GLSLstd450(ext_inst_index);
108     switch (ext_inst_key) {
109       case GLSLstd450Round:
110       case GLSLstd450RoundEven:
111       case GLSLstd450FAbs:
112       case GLSLstd450Trunc:
113       case GLSLstd450FSign:
114       case GLSLstd450Floor:
115       case GLSLstd450Ceil:
116       case GLSLstd450Fract:
117       case GLSLstd450Sqrt:
118       case GLSLstd450InverseSqrt:
119       case GLSLstd450FMin:
120       case GLSLstd450FMax:
121       case GLSLstd450FClamp:
122       case GLSLstd450FMix:
123       case GLSLstd450Step:
124       case GLSLstd450SmoothStep:
125       case GLSLstd450Fma:
126       case GLSLstd450Normalize:
127       case GLSLstd450FaceForward:
128       case GLSLstd450Reflect:
129       case GLSLstd450NMin:
130       case GLSLstd450NMax:
131       case GLSLstd450NClamp: {
132         if (!_.IsFloatScalarOrVectorType(result_type)) {
133           return _.diag(SPV_ERROR_INVALID_DATA, inst)
134                  << ext_inst_name() << ": "
135                  << "expected Result Type to be a float scalar or vector type";
136         }
137 
138         for (uint32_t operand_index = 4; operand_index < num_operands;
139              ++operand_index) {
140           const uint32_t operand_type = _.GetOperandTypeId(inst, operand_index);
141           if (result_type != operand_type) {
142             return _.diag(SPV_ERROR_INVALID_DATA, inst)
143                    << ext_inst_name() << ": "
144                    << "expected types of all operands to be equal to Result "
145                       "Type";
146           }
147         }
148         break;
149       }
150 
151       case GLSLstd450SAbs:
152       case GLSLstd450SSign:
153       case GLSLstd450UMin:
154       case GLSLstd450SMin:
155       case GLSLstd450UMax:
156       case GLSLstd450SMax:
157       case GLSLstd450UClamp:
158       case GLSLstd450SClamp:
159       case GLSLstd450FindILsb:
160       case GLSLstd450FindUMsb:
161       case GLSLstd450FindSMsb: {
162         if (!_.IsIntScalarOrVectorType(result_type)) {
163           return _.diag(SPV_ERROR_INVALID_DATA, inst)
164                  << ext_inst_name() << ": "
165                  << "expected Result Type to be an int scalar or vector type";
166         }
167 
168         const uint32_t result_type_bit_width = _.GetBitWidth(result_type);
169         const uint32_t result_type_dimension = _.GetDimension(result_type);
170 
171         for (uint32_t operand_index = 4; operand_index < num_operands;
172              ++operand_index) {
173           const uint32_t operand_type = _.GetOperandTypeId(inst, operand_index);
174           if (!_.IsIntScalarOrVectorType(operand_type)) {
175             return _.diag(SPV_ERROR_INVALID_DATA, inst)
176                    << ext_inst_name() << ": "
177                    << "expected all operands to be int scalars or vectors";
178           }
179 
180           if (result_type_dimension != _.GetDimension(operand_type)) {
181             return _.diag(SPV_ERROR_INVALID_DATA, inst)
182                    << ext_inst_name() << ": "
183                    << "expected all operands to have the same dimension as "
184                    << "Result Type";
185           }
186 
187           if (result_type_bit_width != _.GetBitWidth(operand_type)) {
188             return _.diag(SPV_ERROR_INVALID_DATA, inst)
189                    << ext_inst_name() << ": "
190                    << "expected all operands to have the same bit width as "
191                    << "Result Type";
192           }
193 
194           if (ext_inst_key == GLSLstd450FindUMsb ||
195               ext_inst_key == GLSLstd450FindSMsb) {
196             if (result_type_bit_width != 32) {
197               return _.diag(SPV_ERROR_INVALID_DATA, inst)
198                      << ext_inst_name() << ": "
199                      << "this instruction is currently limited to 32-bit width "
200                      << "components";
201             }
202           }
203         }
204         break;
205       }
206 
207       case GLSLstd450Radians:
208       case GLSLstd450Degrees:
209       case GLSLstd450Sin:
210       case GLSLstd450Cos:
211       case GLSLstd450Tan:
212       case GLSLstd450Asin:
213       case GLSLstd450Acos:
214       case GLSLstd450Atan:
215       case GLSLstd450Sinh:
216       case GLSLstd450Cosh:
217       case GLSLstd450Tanh:
218       case GLSLstd450Asinh:
219       case GLSLstd450Acosh:
220       case GLSLstd450Atanh:
221       case GLSLstd450Exp:
222       case GLSLstd450Exp2:
223       case GLSLstd450Log:
224       case GLSLstd450Log2:
225       case GLSLstd450Atan2:
226       case GLSLstd450Pow: {
227         if (!_.IsFloatScalarOrVectorType(result_type)) {
228           return _.diag(SPV_ERROR_INVALID_DATA, inst)
229                  << ext_inst_name() << ": "
230                  << "expected Result Type to be a 16 or 32-bit scalar or "
231                     "vector float type";
232         }
233 
234         const uint32_t result_type_bit_width = _.GetBitWidth(result_type);
235         if (result_type_bit_width != 16 && result_type_bit_width != 32) {
236           return _.diag(SPV_ERROR_INVALID_DATA, inst)
237                  << ext_inst_name() << ": "
238                  << "expected Result Type to be a 16 or 32-bit scalar or "
239                     "vector float type";
240         }
241 
242         for (uint32_t operand_index = 4; operand_index < num_operands;
243              ++operand_index) {
244           const uint32_t operand_type = _.GetOperandTypeId(inst, operand_index);
245           if (result_type != operand_type) {
246             return _.diag(SPV_ERROR_INVALID_DATA, inst)
247                    << ext_inst_name() << ": "
248                    << "expected types of all operands to be equal to Result "
249                       "Type";
250           }
251         }
252         break;
253       }
254 
255       case GLSLstd450Determinant: {
256         const uint32_t x_type = _.GetOperandTypeId(inst, 4);
257         uint32_t num_rows = 0;
258         uint32_t num_cols = 0;
259         uint32_t col_type = 0;
260         uint32_t component_type = 0;
261         if (!_.GetMatrixTypeInfo(x_type, &num_rows, &num_cols, &col_type,
262                                  &component_type) ||
263             num_rows != num_cols) {
264           return _.diag(SPV_ERROR_INVALID_DATA, inst)
265                  << ext_inst_name() << ": "
266                  << "expected operand X to be a square matrix";
267         }
268 
269         if (result_type != component_type) {
270           return _.diag(SPV_ERROR_INVALID_DATA, inst)
271                  << ext_inst_name() << ": "
272                  << "expected operand X component type to be equal to "
273                  << "Result Type";
274         }
275         break;
276       }
277 
278       case GLSLstd450MatrixInverse: {
279         uint32_t num_rows = 0;
280         uint32_t num_cols = 0;
281         uint32_t col_type = 0;
282         uint32_t component_type = 0;
283         if (!_.GetMatrixTypeInfo(result_type, &num_rows, &num_cols, &col_type,
284                                  &component_type) ||
285             num_rows != num_cols) {
286           return _.diag(SPV_ERROR_INVALID_DATA, inst)
287                  << ext_inst_name() << ": "
288                  << "expected Result Type to be a square matrix";
289         }
290 
291         const uint32_t x_type = _.GetOperandTypeId(inst, 4);
292         if (result_type != x_type) {
293           return _.diag(SPV_ERROR_INVALID_DATA, inst)
294                  << ext_inst_name() << ": "
295                  << "expected operand X type to be equal to Result Type";
296         }
297         break;
298       }
299 
300       case GLSLstd450Modf: {
301         if (!_.IsFloatScalarOrVectorType(result_type)) {
302           return _.diag(SPV_ERROR_INVALID_DATA, inst)
303                  << ext_inst_name() << ": "
304                  << "expected Result Type to be a scalar or vector float type";
305         }
306 
307         const uint32_t x_type = _.GetOperandTypeId(inst, 4);
308         const uint32_t i_type = _.GetOperandTypeId(inst, 5);
309 
310         if (x_type != result_type) {
311           return _.diag(SPV_ERROR_INVALID_DATA, inst)
312                  << ext_inst_name() << ": "
313                  << "expected operand X type to be equal to Result Type";
314         }
315 
316         uint32_t i_storage_class = 0;
317         uint32_t i_data_type = 0;
318         if (!_.GetPointerTypeInfo(i_type, &i_data_type, &i_storage_class)) {
319           return _.diag(SPV_ERROR_INVALID_DATA, inst)
320                  << ext_inst_name() << ": "
321                  << "expected operand I to be a pointer";
322         }
323 
324         if (i_data_type != result_type) {
325           return _.diag(SPV_ERROR_INVALID_DATA, inst)
326                  << ext_inst_name() << ": "
327                  << "expected operand I data type to be equal to Result Type";
328         }
329 
330         break;
331       }
332 
333       case GLSLstd450ModfStruct: {
334         std::vector<uint32_t> result_types;
335         if (!_.GetStructMemberTypes(result_type, &result_types) ||
336             result_types.size() != 2 ||
337             !_.IsFloatScalarOrVectorType(result_types[0]) ||
338             result_types[1] != result_types[0]) {
339           return _.diag(SPV_ERROR_INVALID_DATA, inst)
340                  << ext_inst_name() << ": "
341                  << "expected Result Type to be a struct with two identical "
342                  << "scalar or vector float type members";
343         }
344 
345         const uint32_t x_type = _.GetOperandTypeId(inst, 4);
346         if (x_type != result_types[0]) {
347           return _.diag(SPV_ERROR_INVALID_DATA, inst)
348                  << ext_inst_name() << ": "
349                  << "expected operand X type to be equal to members of "
350                  << "Result Type struct";
351         }
352         break;
353       }
354 
355       case GLSLstd450Frexp: {
356         if (!_.IsFloatScalarOrVectorType(result_type)) {
357           return _.diag(SPV_ERROR_INVALID_DATA, inst)
358                  << ext_inst_name() << ": "
359                  << "expected Result Type to be a scalar or vector float type";
360         }
361 
362         const uint32_t x_type = _.GetOperandTypeId(inst, 4);
363         const uint32_t exp_type = _.GetOperandTypeId(inst, 5);
364 
365         if (x_type != result_type) {
366           return _.diag(SPV_ERROR_INVALID_DATA, inst)
367                  << ext_inst_name() << ": "
368                  << "expected operand X type to be equal to Result Type";
369         }
370 
371         uint32_t exp_storage_class = 0;
372         uint32_t exp_data_type = 0;
373         if (!_.GetPointerTypeInfo(exp_type, &exp_data_type,
374                                   &exp_storage_class)) {
375           return _.diag(SPV_ERROR_INVALID_DATA, inst)
376                  << ext_inst_name() << ": "
377                  << "expected operand Exp to be a pointer";
378         }
379 
380         if (!_.IsIntScalarOrVectorType(exp_data_type) ||
381             (!_.HasExtension(kSPV_AMD_gpu_shader_int16) &&
382              _.GetBitWidth(exp_data_type) != 32) ||
383             (_.HasExtension(kSPV_AMD_gpu_shader_int16) &&
384              _.GetBitWidth(exp_data_type) != 16 &&
385              _.GetBitWidth(exp_data_type) != 32)) {
386           return _.diag(SPV_ERROR_INVALID_DATA, inst)
387                  << ext_inst_name() << ": "
388                  << "expected operand Exp data type to be a "
389                  << (_.HasExtension(kSPV_AMD_gpu_shader_int16)
390                          ? "16-bit or 32-bit "
391                          : "32-bit ")
392                  << "int scalar or vector type";
393         }
394 
395         if (_.GetDimension(result_type) != _.GetDimension(exp_data_type)) {
396           return _.diag(SPV_ERROR_INVALID_DATA, inst)
397                  << ext_inst_name() << ": "
398                  << "expected operand Exp data type to have the same component "
399                  << "number as Result Type";
400         }
401 
402         break;
403       }
404 
405       case GLSLstd450Ldexp: {
406         if (!_.IsFloatScalarOrVectorType(result_type)) {
407           return _.diag(SPV_ERROR_INVALID_DATA, inst)
408                  << ext_inst_name() << ": "
409                  << "expected Result Type to be a scalar or vector float type";
410         }
411 
412         const uint32_t x_type = _.GetOperandTypeId(inst, 4);
413         const uint32_t exp_type = _.GetOperandTypeId(inst, 5);
414 
415         if (x_type != result_type) {
416           return _.diag(SPV_ERROR_INVALID_DATA, inst)
417                  << ext_inst_name() << ": "
418                  << "expected operand X type to be equal to Result Type";
419         }
420 
421         if (!_.IsIntScalarOrVectorType(exp_type)) {
422           return _.diag(SPV_ERROR_INVALID_DATA, inst)
423                  << ext_inst_name() << ": "
424                  << "expected operand Exp to be a 32-bit int scalar "
425                  << "or vector type";
426         }
427 
428         if (_.GetDimension(result_type) != _.GetDimension(exp_type)) {
429           return _.diag(SPV_ERROR_INVALID_DATA, inst)
430                  << ext_inst_name() << ": "
431                  << "expected operand Exp to have the same component "
432                  << "number as Result Type";
433         }
434 
435         break;
436       }
437 
438       case GLSLstd450FrexpStruct: {
439         std::vector<uint32_t> result_types;
440         if (!_.GetStructMemberTypes(result_type, &result_types) ||
441             result_types.size() != 2 ||
442             !_.IsFloatScalarOrVectorType(result_types[0]) ||
443             !_.IsIntScalarOrVectorType(result_types[1]) ||
444             (!_.HasExtension(kSPV_AMD_gpu_shader_int16) &&
445              _.GetBitWidth(result_types[1]) != 32) ||
446             (_.HasExtension(kSPV_AMD_gpu_shader_int16) &&
447              _.GetBitWidth(result_types[1]) != 16 &&
448              _.GetBitWidth(result_types[1]) != 32) ||
449             _.GetDimension(result_types[0]) !=
450                 _.GetDimension(result_types[1])) {
451           return _.diag(SPV_ERROR_INVALID_DATA, inst)
452                  << ext_inst_name() << ": "
453                  << "expected Result Type to be a struct with two members, "
454                  << "first member a float scalar or vector, second member a "
455                  << (_.HasExtension(kSPV_AMD_gpu_shader_int16)
456                          ? "16-bit or 32-bit "
457                          : "32-bit ")
458                  << "int scalar or vector with the same number of "
459                  << "components as the first member";
460         }
461 
462         const uint32_t x_type = _.GetOperandTypeId(inst, 4);
463         if (x_type != result_types[0]) {
464           return _.diag(SPV_ERROR_INVALID_DATA, inst)
465                  << ext_inst_name() << ": "
466                  << "expected operand X type to be equal to the first member "
467                  << "of Result Type struct";
468         }
469         break;
470       }
471 
472       case GLSLstd450PackSnorm4x8:
473       case GLSLstd450PackUnorm4x8: {
474         if (!_.IsIntScalarType(result_type) ||
475             _.GetBitWidth(result_type) != 32) {
476           return _.diag(SPV_ERROR_INVALID_DATA, inst)
477                  << ext_inst_name() << ": "
478                  << "expected Result Type to be 32-bit int scalar type";
479         }
480 
481         const uint32_t v_type = _.GetOperandTypeId(inst, 4);
482         if (!_.IsFloatVectorType(v_type) || _.GetDimension(v_type) != 4 ||
483             _.GetBitWidth(v_type) != 32) {
484           return _.diag(SPV_ERROR_INVALID_DATA, inst)
485                  << ext_inst_name() << ": "
486                  << "expected operand V to be a 32-bit float vector of size 4";
487         }
488         break;
489       }
490 
491       case GLSLstd450PackSnorm2x16:
492       case GLSLstd450PackUnorm2x16:
493       case GLSLstd450PackHalf2x16: {
494         if (!_.IsIntScalarType(result_type) ||
495             _.GetBitWidth(result_type) != 32) {
496           return _.diag(SPV_ERROR_INVALID_DATA, inst)
497                  << ext_inst_name() << ": "
498                  << "expected Result Type to be 32-bit int scalar type";
499         }
500 
501         const uint32_t v_type = _.GetOperandTypeId(inst, 4);
502         if (!_.IsFloatVectorType(v_type) || _.GetDimension(v_type) != 2 ||
503             _.GetBitWidth(v_type) != 32) {
504           return _.diag(SPV_ERROR_INVALID_DATA, inst)
505                  << ext_inst_name() << ": "
506                  << "expected operand V to be a 32-bit float vector of size 2";
507         }
508         break;
509       }
510 
511       case GLSLstd450PackDouble2x32: {
512         if (!_.IsFloatScalarType(result_type) ||
513             _.GetBitWidth(result_type) != 64) {
514           return _.diag(SPV_ERROR_INVALID_DATA, inst)
515                  << ext_inst_name() << ": "
516                  << "expected Result Type to be 64-bit float scalar type";
517         }
518 
519         const uint32_t v_type = _.GetOperandTypeId(inst, 4);
520         if (!_.IsIntVectorType(v_type) || _.GetDimension(v_type) != 2 ||
521             _.GetBitWidth(v_type) != 32) {
522           return _.diag(SPV_ERROR_INVALID_DATA, inst)
523                  << ext_inst_name() << ": "
524                  << "expected operand V to be a 32-bit int vector of size 2";
525         }
526         break;
527       }
528 
529       case GLSLstd450UnpackSnorm4x8:
530       case GLSLstd450UnpackUnorm4x8: {
531         if (!_.IsFloatVectorType(result_type) ||
532             _.GetDimension(result_type) != 4 ||
533             _.GetBitWidth(result_type) != 32) {
534           return _.diag(SPV_ERROR_INVALID_DATA, inst)
535                  << ext_inst_name() << ": "
536                  << "expected Result Type to be a 32-bit float vector of size "
537                     "4";
538         }
539 
540         const uint32_t v_type = _.GetOperandTypeId(inst, 4);
541         if (!_.IsIntScalarType(v_type) || _.GetBitWidth(v_type) != 32) {
542           return _.diag(SPV_ERROR_INVALID_DATA, inst)
543                  << ext_inst_name() << ": "
544                  << "expected operand P to be a 32-bit int scalar";
545         }
546         break;
547       }
548 
549       case GLSLstd450UnpackSnorm2x16:
550       case GLSLstd450UnpackUnorm2x16:
551       case GLSLstd450UnpackHalf2x16: {
552         if (!_.IsFloatVectorType(result_type) ||
553             _.GetDimension(result_type) != 2 ||
554             _.GetBitWidth(result_type) != 32) {
555           return _.diag(SPV_ERROR_INVALID_DATA, inst)
556                  << ext_inst_name() << ": "
557                  << "expected Result Type to be a 32-bit float vector of size "
558                     "2";
559         }
560 
561         const uint32_t v_type = _.GetOperandTypeId(inst, 4);
562         if (!_.IsIntScalarType(v_type) || _.GetBitWidth(v_type) != 32) {
563           return _.diag(SPV_ERROR_INVALID_DATA, inst)
564                  << ext_inst_name() << ": "
565                  << "expected operand P to be a 32-bit int scalar";
566         }
567         break;
568       }
569 
570       case GLSLstd450UnpackDouble2x32: {
571         if (!_.IsIntVectorType(result_type) ||
572             _.GetDimension(result_type) != 2 ||
573             _.GetBitWidth(result_type) != 32) {
574           return _.diag(SPV_ERROR_INVALID_DATA, inst)
575                  << ext_inst_name() << ": "
576                  << "expected Result Type to be a 32-bit int vector of size "
577                     "2";
578         }
579 
580         const uint32_t v_type = _.GetOperandTypeId(inst, 4);
581         if (!_.IsFloatScalarType(v_type) || _.GetBitWidth(v_type) != 64) {
582           return _.diag(SPV_ERROR_INVALID_DATA, inst)
583                  << ext_inst_name() << ": "
584                  << "expected operand V to be a 64-bit float scalar";
585         }
586         break;
587       }
588 
589       case GLSLstd450Length: {
590         if (!_.IsFloatScalarType(result_type)) {
591           return _.diag(SPV_ERROR_INVALID_DATA, inst)
592                  << ext_inst_name() << ": "
593                  << "expected Result Type to be a float scalar type";
594         }
595 
596         const uint32_t x_type = _.GetOperandTypeId(inst, 4);
597         if (!_.IsFloatScalarOrVectorType(x_type)) {
598           return _.diag(SPV_ERROR_INVALID_DATA, inst)
599                  << ext_inst_name() << ": "
600                  << "expected operand X to be of float scalar or vector type";
601         }
602 
603         if (result_type != _.GetComponentType(x_type)) {
604           return _.diag(SPV_ERROR_INVALID_DATA, inst)
605                  << ext_inst_name() << ": "
606                  << "expected operand X component type to be equal to Result "
607                     "Type";
608         }
609         break;
610       }
611 
612       case GLSLstd450Distance: {
613         if (!_.IsFloatScalarType(result_type)) {
614           return _.diag(SPV_ERROR_INVALID_DATA, inst)
615                  << ext_inst_name() << ": "
616                  << "expected Result Type to be a float scalar type";
617         }
618 
619         const uint32_t p0_type = _.GetOperandTypeId(inst, 4);
620         if (!_.IsFloatScalarOrVectorType(p0_type)) {
621           return _.diag(SPV_ERROR_INVALID_DATA, inst)
622                  << ext_inst_name() << ": "
623                  << "expected operand P0 to be of float scalar or vector type";
624         }
625 
626         if (result_type != _.GetComponentType(p0_type)) {
627           return _.diag(SPV_ERROR_INVALID_DATA, inst)
628                  << ext_inst_name() << ": "
629                  << "expected operand P0 component type to be equal to "
630                  << "Result Type";
631         }
632 
633         const uint32_t p1_type = _.GetOperandTypeId(inst, 5);
634         if (!_.IsFloatScalarOrVectorType(p1_type)) {
635           return _.diag(SPV_ERROR_INVALID_DATA, inst)
636                  << ext_inst_name() << ": "
637                  << "expected operand P1 to be of float scalar or vector type";
638         }
639 
640         if (result_type != _.GetComponentType(p1_type)) {
641           return _.diag(SPV_ERROR_INVALID_DATA, inst)
642                  << ext_inst_name() << ": "
643                  << "expected operand P1 component type to be equal to "
644                  << "Result Type";
645         }
646 
647         if (_.GetDimension(p0_type) != _.GetDimension(p1_type)) {
648           return _.diag(SPV_ERROR_INVALID_DATA, inst)
649                  << ext_inst_name() << ": "
650                  << "expected operands P0 and P1 to have the same number of "
651                  << "components";
652         }
653         break;
654       }
655 
656       case GLSLstd450Cross: {
657         if (!_.IsFloatVectorType(result_type)) {
658           return _.diag(SPV_ERROR_INVALID_DATA, inst)
659                  << ext_inst_name() << ": "
660                  << "expected Result Type to be a float vector type";
661         }
662 
663         if (_.GetDimension(result_type) != 3) {
664           return _.diag(SPV_ERROR_INVALID_DATA, inst)
665                  << ext_inst_name() << ": "
666                  << "expected Result Type to have 3 components";
667         }
668 
669         const uint32_t x_type = _.GetOperandTypeId(inst, 4);
670         const uint32_t y_type = _.GetOperandTypeId(inst, 5);
671 
672         if (x_type != result_type) {
673           return _.diag(SPV_ERROR_INVALID_DATA, inst)
674                  << ext_inst_name() << ": "
675                  << "expected operand X type to be equal to Result Type";
676         }
677 
678         if (y_type != result_type) {
679           return _.diag(SPV_ERROR_INVALID_DATA, inst)
680                  << ext_inst_name() << ": "
681                  << "expected operand Y type to be equal to Result Type";
682         }
683         break;
684       }
685 
686       case GLSLstd450Refract: {
687         if (!_.IsFloatScalarOrVectorType(result_type)) {
688           return _.diag(SPV_ERROR_INVALID_DATA, inst)
689                  << ext_inst_name() << ": "
690                  << "expected Result Type to be a float scalar or vector type";
691         }
692 
693         const uint32_t i_type = _.GetOperandTypeId(inst, 4);
694         const uint32_t n_type = _.GetOperandTypeId(inst, 5);
695         const uint32_t eta_type = _.GetOperandTypeId(inst, 6);
696 
697         if (result_type != i_type) {
698           return _.diag(SPV_ERROR_INVALID_DATA, inst)
699                  << ext_inst_name() << ": "
700                  << "expected operand I to be of type equal to Result Type";
701         }
702 
703         if (result_type != n_type) {
704           return _.diag(SPV_ERROR_INVALID_DATA, inst)
705                  << ext_inst_name() << ": "
706                  << "expected operand N to be of type equal to Result Type";
707         }
708 
709         if (!_.IsFloatScalarType(eta_type)) {
710           return _.diag(SPV_ERROR_INVALID_DATA, inst)
711                  << ext_inst_name() << ": "
712                  << "expected operand Eta to be a float scalar";
713         }
714         break;
715       }
716 
717       case GLSLstd450InterpolateAtCentroid:
718       case GLSLstd450InterpolateAtSample:
719       case GLSLstd450InterpolateAtOffset: {
720         if (!_.HasCapability(SpvCapabilityInterpolationFunction)) {
721           return _.diag(SPV_ERROR_INVALID_CAPABILITY, inst)
722                  << ext_inst_name()
723                  << " requires capability InterpolationFunction";
724         }
725 
726         if (!_.IsFloatScalarOrVectorType(result_type) ||
727             _.GetBitWidth(result_type) != 32) {
728           return _.diag(SPV_ERROR_INVALID_DATA, inst)
729                  << ext_inst_name() << ": "
730                  << "expected Result Type to be a 32-bit float scalar "
731                  << "or vector type";
732         }
733 
734         const uint32_t interpolant_type = _.GetOperandTypeId(inst, 4);
735         uint32_t interpolant_storage_class = 0;
736         uint32_t interpolant_data_type = 0;
737         if (!_.GetPointerTypeInfo(interpolant_type, &interpolant_data_type,
738                                   &interpolant_storage_class)) {
739           return _.diag(SPV_ERROR_INVALID_DATA, inst)
740                  << ext_inst_name() << ": "
741                  << "expected Interpolant to be a pointer";
742         }
743 
744         if (result_type != interpolant_data_type) {
745           return _.diag(SPV_ERROR_INVALID_DATA, inst)
746                  << ext_inst_name() << ": "
747                  << "expected Interpolant data type to be equal to Result Type";
748         }
749 
750         if (interpolant_storage_class != SpvStorageClassInput) {
751           return _.diag(SPV_ERROR_INVALID_DATA, inst)
752                  << ext_inst_name() << ": "
753                  << "expected Interpolant storage class to be Input";
754         }
755 
756         if (ext_inst_key == GLSLstd450InterpolateAtSample) {
757           const uint32_t sample_type = _.GetOperandTypeId(inst, 5);
758           if (!_.IsIntScalarType(sample_type) ||
759               _.GetBitWidth(sample_type) != 32) {
760             return _.diag(SPV_ERROR_INVALID_DATA, inst)
761                    << ext_inst_name() << ": "
762                    << "expected Sample to be 32-bit integer";
763           }
764         }
765 
766         if (ext_inst_key == GLSLstd450InterpolateAtOffset) {
767           const uint32_t offset_type = _.GetOperandTypeId(inst, 5);
768           if (!_.IsFloatVectorType(offset_type) ||
769               _.GetDimension(offset_type) != 2 ||
770               _.GetBitWidth(offset_type) != 32) {
771             return _.diag(SPV_ERROR_INVALID_DATA, inst)
772                    << ext_inst_name() << ": "
773                    << "expected Offset to be a vector of 2 32-bit floats";
774           }
775         }
776 
777         _.function(inst->function()->id())
778             ->RegisterExecutionModelLimitation(
779                 SpvExecutionModelFragment,
780                 ext_inst_name() +
781                     std::string(" requires Fragment execution model"));
782         break;
783       }
784 
785       case GLSLstd450IMix: {
786         return _.diag(SPV_ERROR_INVALID_DATA, inst)
787                << "Extended instruction GLSLstd450IMix is not supported";
788       }
789 
790       case GLSLstd450Bad: {
791         return _.diag(SPV_ERROR_INVALID_DATA, inst)
792                << "Encountered extended instruction GLSLstd450Bad";
793       }
794 
795       case GLSLstd450Count: {
796         assert(0);
797         break;
798       }
799     }
800   } else if (ext_inst_type == SPV_EXT_INST_TYPE_OPENCL_STD) {
801     const OpenCLLIB::Entrypoints ext_inst_key =
802         OpenCLLIB::Entrypoints(ext_inst_index);
803     switch (ext_inst_key) {
804       case OpenCLLIB::Acos:
805       case OpenCLLIB::Acosh:
806       case OpenCLLIB::Acospi:
807       case OpenCLLIB::Asin:
808       case OpenCLLIB::Asinh:
809       case OpenCLLIB::Asinpi:
810       case OpenCLLIB::Atan:
811       case OpenCLLIB::Atan2:
812       case OpenCLLIB::Atanh:
813       case OpenCLLIB::Atanpi:
814       case OpenCLLIB::Atan2pi:
815       case OpenCLLIB::Cbrt:
816       case OpenCLLIB::Ceil:
817       case OpenCLLIB::Copysign:
818       case OpenCLLIB::Cos:
819       case OpenCLLIB::Cosh:
820       case OpenCLLIB::Cospi:
821       case OpenCLLIB::Erfc:
822       case OpenCLLIB::Erf:
823       case OpenCLLIB::Exp:
824       case OpenCLLIB::Exp2:
825       case OpenCLLIB::Exp10:
826       case OpenCLLIB::Expm1:
827       case OpenCLLIB::Fabs:
828       case OpenCLLIB::Fdim:
829       case OpenCLLIB::Floor:
830       case OpenCLLIB::Fma:
831       case OpenCLLIB::Fmax:
832       case OpenCLLIB::Fmin:
833       case OpenCLLIB::Fmod:
834       case OpenCLLIB::Hypot:
835       case OpenCLLIB::Lgamma:
836       case OpenCLLIB::Log:
837       case OpenCLLIB::Log2:
838       case OpenCLLIB::Log10:
839       case OpenCLLIB::Log1p:
840       case OpenCLLIB::Logb:
841       case OpenCLLIB::Mad:
842       case OpenCLLIB::Maxmag:
843       case OpenCLLIB::Minmag:
844       case OpenCLLIB::Nextafter:
845       case OpenCLLIB::Pow:
846       case OpenCLLIB::Powr:
847       case OpenCLLIB::Remainder:
848       case OpenCLLIB::Rint:
849       case OpenCLLIB::Round:
850       case OpenCLLIB::Rsqrt:
851       case OpenCLLIB::Sin:
852       case OpenCLLIB::Sinh:
853       case OpenCLLIB::Sinpi:
854       case OpenCLLIB::Sqrt:
855       case OpenCLLIB::Tan:
856       case OpenCLLIB::Tanh:
857       case OpenCLLIB::Tanpi:
858       case OpenCLLIB::Tgamma:
859       case OpenCLLIB::Trunc:
860       case OpenCLLIB::Half_cos:
861       case OpenCLLIB::Half_divide:
862       case OpenCLLIB::Half_exp:
863       case OpenCLLIB::Half_exp2:
864       case OpenCLLIB::Half_exp10:
865       case OpenCLLIB::Half_log:
866       case OpenCLLIB::Half_log2:
867       case OpenCLLIB::Half_log10:
868       case OpenCLLIB::Half_powr:
869       case OpenCLLIB::Half_recip:
870       case OpenCLLIB::Half_rsqrt:
871       case OpenCLLIB::Half_sin:
872       case OpenCLLIB::Half_sqrt:
873       case OpenCLLIB::Half_tan:
874       case OpenCLLIB::Native_cos:
875       case OpenCLLIB::Native_divide:
876       case OpenCLLIB::Native_exp:
877       case OpenCLLIB::Native_exp2:
878       case OpenCLLIB::Native_exp10:
879       case OpenCLLIB::Native_log:
880       case OpenCLLIB::Native_log2:
881       case OpenCLLIB::Native_log10:
882       case OpenCLLIB::Native_powr:
883       case OpenCLLIB::Native_recip:
884       case OpenCLLIB::Native_rsqrt:
885       case OpenCLLIB::Native_sin:
886       case OpenCLLIB::Native_sqrt:
887       case OpenCLLIB::Native_tan:
888       case OpenCLLIB::FClamp:
889       case OpenCLLIB::Degrees:
890       case OpenCLLIB::FMax_common:
891       case OpenCLLIB::FMin_common:
892       case OpenCLLIB::Mix:
893       case OpenCLLIB::Radians:
894       case OpenCLLIB::Step:
895       case OpenCLLIB::Smoothstep:
896       case OpenCLLIB::Sign: {
897         if (!_.IsFloatScalarOrVectorType(result_type)) {
898           return _.diag(SPV_ERROR_INVALID_DATA, inst)
899                  << ext_inst_name() << ": "
900                  << "expected Result Type to be a float scalar or vector type";
901         }
902 
903         const uint32_t num_components = _.GetDimension(result_type);
904         if (num_components > 4 && num_components != 8 && num_components != 16) {
905           return _.diag(SPV_ERROR_INVALID_DATA, inst)
906                  << ext_inst_name() << ": "
907                  << "expected Result Type to be a scalar or a vector with 2, "
908                     "3, 4, 8 or 16 components";
909         }
910 
911         for (uint32_t operand_index = 4; operand_index < num_operands;
912              ++operand_index) {
913           const uint32_t operand_type = _.GetOperandTypeId(inst, operand_index);
914           if (result_type != operand_type) {
915             return _.diag(SPV_ERROR_INVALID_DATA, inst)
916                    << ext_inst_name() << ": "
917                    << "expected types of all operands to be equal to Result "
918                       "Type";
919           }
920         }
921         break;
922       }
923 
924       case OpenCLLIB::Fract:
925       case OpenCLLIB::Modf:
926       case OpenCLLIB::Sincos:
927       case OpenCLLIB::Remquo: {
928         if (!_.IsFloatScalarOrVectorType(result_type)) {
929           return _.diag(SPV_ERROR_INVALID_DATA, inst)
930                  << ext_inst_name() << ": "
931                  << "expected Result Type to be a float scalar or vector type";
932         }
933 
934         const uint32_t num_components = _.GetDimension(result_type);
935         if (num_components > 4 && num_components != 8 && num_components != 16) {
936           return _.diag(SPV_ERROR_INVALID_DATA, inst)
937                  << ext_inst_name() << ": "
938                  << "expected Result Type to be a scalar or a vector with 2, "
939                     "3, 4, 8 or 16 components";
940         }
941 
942         uint32_t operand_index = 4;
943         const uint32_t x_type = _.GetOperandTypeId(inst, operand_index++);
944         if (result_type != x_type) {
945           return _.diag(SPV_ERROR_INVALID_DATA, inst)
946                  << ext_inst_name() << ": "
947                  << "expected type of operand X to be equal to Result Type";
948         }
949 
950         if (ext_inst_key == OpenCLLIB::Remquo) {
951           const uint32_t y_type = _.GetOperandTypeId(inst, operand_index++);
952           if (result_type != y_type) {
953             return _.diag(SPV_ERROR_INVALID_DATA, inst)
954                    << ext_inst_name() << ": "
955                    << "expected type of operand Y to be equal to Result Type";
956           }
957         }
958 
959         const uint32_t p_type = _.GetOperandTypeId(inst, operand_index++);
960         uint32_t p_storage_class = 0;
961         uint32_t p_data_type = 0;
962         if (!_.GetPointerTypeInfo(p_type, &p_data_type, &p_storage_class)) {
963           return _.diag(SPV_ERROR_INVALID_DATA, inst)
964                  << ext_inst_name() << ": "
965                  << "expected the last operand to be a pointer";
966         }
967 
968         if (p_storage_class != SpvStorageClassGeneric &&
969             p_storage_class != SpvStorageClassCrossWorkgroup &&
970             p_storage_class != SpvStorageClassWorkgroup &&
971             p_storage_class != SpvStorageClassFunction) {
972           return _.diag(SPV_ERROR_INVALID_DATA, inst)
973                  << ext_inst_name() << ": "
974                  << "expected storage class of the pointer to be Generic, "
975                     "CrossWorkgroup, Workgroup or Function";
976         }
977 
978         if (result_type != p_data_type) {
979           return _.diag(SPV_ERROR_INVALID_DATA, inst)
980                  << ext_inst_name() << ": "
981                  << "expected data type of the pointer to be equal to Result "
982                     "Type";
983         }
984         break;
985       }
986 
987       case OpenCLLIB::Frexp:
988       case OpenCLLIB::Lgamma_r: {
989         if (!_.IsFloatScalarOrVectorType(result_type)) {
990           return _.diag(SPV_ERROR_INVALID_DATA, inst)
991                  << ext_inst_name() << ": "
992                  << "expected Result Type to be a float scalar or vector type";
993         }
994 
995         const uint32_t num_components = _.GetDimension(result_type);
996         if (num_components > 4 && num_components != 8 && num_components != 16) {
997           return _.diag(SPV_ERROR_INVALID_DATA, inst)
998                  << ext_inst_name() << ": "
999                  << "expected Result Type to be a scalar or a vector with 2, "
1000                     "3, 4, 8 or 16 components";
1001         }
1002 
1003         const uint32_t x_type = _.GetOperandTypeId(inst, 4);
1004         if (result_type != x_type) {
1005           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1006                  << ext_inst_name() << ": "
1007                  << "expected type of operand X to be equal to Result Type";
1008         }
1009 
1010         const uint32_t p_type = _.GetOperandTypeId(inst, 5);
1011         uint32_t p_storage_class = 0;
1012         uint32_t p_data_type = 0;
1013         if (!_.GetPointerTypeInfo(p_type, &p_data_type, &p_storage_class)) {
1014           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1015                  << ext_inst_name() << ": "
1016                  << "expected the last operand to be a pointer";
1017         }
1018 
1019         if (p_storage_class != SpvStorageClassGeneric &&
1020             p_storage_class != SpvStorageClassCrossWorkgroup &&
1021             p_storage_class != SpvStorageClassWorkgroup &&
1022             p_storage_class != SpvStorageClassFunction) {
1023           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1024                  << ext_inst_name() << ": "
1025                  << "expected storage class of the pointer to be Generic, "
1026                     "CrossWorkgroup, Workgroup or Function";
1027         }
1028 
1029         if (!_.IsIntScalarOrVectorType(p_data_type) ||
1030             _.GetBitWidth(p_data_type) != 32) {
1031           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1032                  << ext_inst_name() << ": "
1033                  << "expected data type of the pointer to be a 32-bit int "
1034                     "scalar or vector type";
1035         }
1036 
1037         if (_.GetDimension(p_data_type) != num_components) {
1038           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1039                  << ext_inst_name() << ": "
1040                  << "expected data type of the pointer to have the same number "
1041                     "of components as Result Type";
1042         }
1043         break;
1044       }
1045 
1046       case OpenCLLIB::Ilogb: {
1047         if (!_.IsIntScalarOrVectorType(result_type) ||
1048             _.GetBitWidth(result_type) != 32) {
1049           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1050                  << ext_inst_name() << ": "
1051                  << "expected Result Type to be a 32-bit int scalar or vector "
1052                     "type";
1053         }
1054 
1055         const uint32_t num_components = _.GetDimension(result_type);
1056         if (num_components > 4 && num_components != 8 && num_components != 16) {
1057           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1058                  << ext_inst_name() << ": "
1059                  << "expected Result Type to be a scalar or a vector with 2, "
1060                     "3, 4, 8 or 16 components";
1061         }
1062 
1063         const uint32_t x_type = _.GetOperandTypeId(inst, 4);
1064         if (!_.IsFloatScalarOrVectorType(x_type)) {
1065           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1066                  << ext_inst_name() << ": "
1067                  << "expected operand X to be a float scalar or vector";
1068         }
1069 
1070         if (_.GetDimension(x_type) != num_components) {
1071           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1072                  << ext_inst_name() << ": "
1073                  << "expected operand X to have the same number of components "
1074                     "as Result Type";
1075         }
1076         break;
1077       }
1078 
1079       case OpenCLLIB::Ldexp:
1080       case OpenCLLIB::Pown:
1081       case OpenCLLIB::Rootn: {
1082         if (!_.IsFloatScalarOrVectorType(result_type)) {
1083           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1084                  << ext_inst_name() << ": "
1085                  << "expected Result Type to be a float scalar or vector type";
1086         }
1087 
1088         const uint32_t num_components = _.GetDimension(result_type);
1089         if (num_components > 4 && num_components != 8 && num_components != 16) {
1090           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1091                  << ext_inst_name() << ": "
1092                  << "expected Result Type to be a scalar or a vector with 2, "
1093                     "3, 4, 8 or 16 components";
1094         }
1095 
1096         const uint32_t x_type = _.GetOperandTypeId(inst, 4);
1097         if (result_type != x_type) {
1098           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1099                  << ext_inst_name() << ": "
1100                  << "expected type of operand X to be equal to Result Type";
1101         }
1102 
1103         const uint32_t exp_type = _.GetOperandTypeId(inst, 5);
1104         if (!_.IsIntScalarOrVectorType(exp_type) ||
1105             _.GetBitWidth(exp_type) != 32) {
1106           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1107                  << ext_inst_name() << ": "
1108                  << "expected the exponent to be a 32-bit int scalar or vector";
1109         }
1110 
1111         if (_.GetDimension(exp_type) != num_components) {
1112           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1113                  << ext_inst_name() << ": "
1114                  << "expected the exponent to have the same number of "
1115                     "components as Result Type";
1116         }
1117         break;
1118       }
1119 
1120       case OpenCLLIB::Nan: {
1121         if (!_.IsFloatScalarOrVectorType(result_type)) {
1122           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1123                  << ext_inst_name() << ": "
1124                  << "expected Result Type to be a float scalar or vector type";
1125         }
1126 
1127         const uint32_t num_components = _.GetDimension(result_type);
1128         if (num_components > 4 && num_components != 8 && num_components != 16) {
1129           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1130                  << ext_inst_name() << ": "
1131                  << "expected Result Type to be a scalar or a vector with 2, "
1132                     "3, 4, 8 or 16 components";
1133         }
1134 
1135         const uint32_t nancode_type = _.GetOperandTypeId(inst, 4);
1136         if (!_.IsIntScalarOrVectorType(nancode_type)) {
1137           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1138                  << ext_inst_name() << ": "
1139                  << "expected Nancode to be an int scalar or vector type";
1140         }
1141 
1142         if (_.GetDimension(nancode_type) != num_components) {
1143           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1144                  << ext_inst_name() << ": "
1145                  << "expected Nancode to have the same number of components as "
1146                     "Result Type";
1147         }
1148 
1149         if (_.GetBitWidth(result_type) != _.GetBitWidth(nancode_type)) {
1150           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1151                  << ext_inst_name() << ": "
1152                  << "expected Nancode to have the same bit width as Result "
1153                     "Type";
1154         }
1155         break;
1156       }
1157 
1158       case OpenCLLIB::SAbs:
1159       case OpenCLLIB::SAbs_diff:
1160       case OpenCLLIB::SAdd_sat:
1161       case OpenCLLIB::UAdd_sat:
1162       case OpenCLLIB::SHadd:
1163       case OpenCLLIB::UHadd:
1164       case OpenCLLIB::SRhadd:
1165       case OpenCLLIB::URhadd:
1166       case OpenCLLIB::SClamp:
1167       case OpenCLLIB::UClamp:
1168       case OpenCLLIB::Clz:
1169       case OpenCLLIB::Ctz:
1170       case OpenCLLIB::SMad_hi:
1171       case OpenCLLIB::UMad_sat:
1172       case OpenCLLIB::SMad_sat:
1173       case OpenCLLIB::SMax:
1174       case OpenCLLIB::UMax:
1175       case OpenCLLIB::SMin:
1176       case OpenCLLIB::UMin:
1177       case OpenCLLIB::SMul_hi:
1178       case OpenCLLIB::Rotate:
1179       case OpenCLLIB::SSub_sat:
1180       case OpenCLLIB::USub_sat:
1181       case OpenCLLIB::Popcount:
1182       case OpenCLLIB::UAbs:
1183       case OpenCLLIB::UAbs_diff:
1184       case OpenCLLIB::UMul_hi:
1185       case OpenCLLIB::UMad_hi: {
1186         if (!_.IsIntScalarOrVectorType(result_type)) {
1187           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1188                  << ext_inst_name() << ": "
1189                  << "expected Result Type to be an int scalar or vector type";
1190         }
1191 
1192         const uint32_t num_components = _.GetDimension(result_type);
1193         if (num_components > 4 && num_components != 8 && num_components != 16) {
1194           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1195                  << ext_inst_name() << ": "
1196                  << "expected Result Type to be a scalar or a vector with 2, "
1197                     "3, 4, 8 or 16 components";
1198         }
1199 
1200         for (uint32_t operand_index = 4; operand_index < num_operands;
1201              ++operand_index) {
1202           const uint32_t operand_type = _.GetOperandTypeId(inst, operand_index);
1203           if (result_type != operand_type) {
1204             return _.diag(SPV_ERROR_INVALID_DATA, inst)
1205                    << ext_inst_name() << ": "
1206                    << "expected types of all operands to be equal to Result "
1207                       "Type";
1208           }
1209         }
1210         break;
1211       }
1212 
1213       case OpenCLLIB::U_Upsample:
1214       case OpenCLLIB::S_Upsample: {
1215         if (!_.IsIntScalarOrVectorType(result_type)) {
1216           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1217                  << ext_inst_name() << ": "
1218                  << "expected Result Type to be an int scalar or vector "
1219                     "type";
1220         }
1221 
1222         const uint32_t result_num_components = _.GetDimension(result_type);
1223         if (result_num_components > 4 && result_num_components != 8 &&
1224             result_num_components != 16) {
1225           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1226                  << ext_inst_name() << ": "
1227                  << "expected Result Type to be a scalar or a vector with 2, "
1228                     "3, 4, 8 or 16 components";
1229         }
1230 
1231         const uint32_t result_bit_width = _.GetBitWidth(result_type);
1232         if (result_bit_width != 16 && result_bit_width != 32 &&
1233             result_bit_width != 64) {
1234           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1235                  << ext_inst_name() << ": "
1236                  << "expected bit width of Result Type components to be 16, 32 "
1237                     "or 64";
1238         }
1239 
1240         const uint32_t hi_type = _.GetOperandTypeId(inst, 4);
1241         const uint32_t lo_type = _.GetOperandTypeId(inst, 5);
1242 
1243         if (hi_type != lo_type) {
1244           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1245                  << ext_inst_name() << ": "
1246                  << "expected Hi and Lo operands to have the same type";
1247         }
1248 
1249         if (result_num_components != _.GetDimension(hi_type)) {
1250           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1251                  << ext_inst_name() << ": "
1252                  << "expected Hi and Lo operands to have the same number of "
1253                     "components as Result Type";
1254         }
1255 
1256         if (result_bit_width != 2 * _.GetBitWidth(hi_type)) {
1257           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1258                  << ext_inst_name() << ": "
1259                  << "expected bit width of components of Hi and Lo operands to "
1260                     "be half of the bit width of components of Result Type";
1261         }
1262         break;
1263       }
1264 
1265       case OpenCLLIB::SMad24:
1266       case OpenCLLIB::UMad24:
1267       case OpenCLLIB::SMul24:
1268       case OpenCLLIB::UMul24: {
1269         if (!_.IsIntScalarOrVectorType(result_type) ||
1270             _.GetBitWidth(result_type) != 32) {
1271           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1272                  << ext_inst_name() << ": "
1273                  << "expected Result Type to be a 32-bit int scalar or vector "
1274                     "type";
1275         }
1276 
1277         const uint32_t num_components = _.GetDimension(result_type);
1278         if (num_components > 4 && num_components != 8 && num_components != 16) {
1279           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1280                  << ext_inst_name() << ": "
1281                  << "expected Result Type to be a scalar or a vector with 2, "
1282                     "3, 4, 8 or 16 components";
1283         }
1284 
1285         for (uint32_t operand_index = 4; operand_index < num_operands;
1286              ++operand_index) {
1287           const uint32_t operand_type = _.GetOperandTypeId(inst, operand_index);
1288           if (result_type != operand_type) {
1289             return _.diag(SPV_ERROR_INVALID_DATA, inst)
1290                    << ext_inst_name() << ": "
1291                    << "expected types of all operands to be equal to Result "
1292                       "Type";
1293           }
1294         }
1295         break;
1296       }
1297 
1298       case OpenCLLIB::Cross: {
1299         if (!_.IsFloatVectorType(result_type)) {
1300           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1301                  << ext_inst_name() << ": "
1302                  << "expected Result Type to be a float vector type";
1303         }
1304 
1305         const uint32_t num_components = _.GetDimension(result_type);
1306         if (num_components != 3 && num_components != 4) {
1307           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1308                  << ext_inst_name() << ": "
1309                  << "expected Result Type to have 3 or 4 components";
1310         }
1311 
1312         const uint32_t x_type = _.GetOperandTypeId(inst, 4);
1313         const uint32_t y_type = _.GetOperandTypeId(inst, 5);
1314 
1315         if (x_type != result_type) {
1316           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1317                  << ext_inst_name() << ": "
1318                  << "expected operand X type to be equal to Result Type";
1319         }
1320 
1321         if (y_type != result_type) {
1322           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1323                  << ext_inst_name() << ": "
1324                  << "expected operand Y type to be equal to Result Type";
1325         }
1326         break;
1327       }
1328 
1329       case OpenCLLIB::Distance:
1330       case OpenCLLIB::Fast_distance: {
1331         if (!_.IsFloatScalarType(result_type)) {
1332           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1333                  << ext_inst_name() << ": "
1334                  << "expected Result Type to be a float scalar type";
1335         }
1336 
1337         const uint32_t p0_type = _.GetOperandTypeId(inst, 4);
1338         if (!_.IsFloatScalarOrVectorType(p0_type)) {
1339           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1340                  << ext_inst_name() << ": "
1341                  << "expected operand P0 to be of float scalar or vector type";
1342         }
1343 
1344         const uint32_t num_components = _.GetDimension(p0_type);
1345         if (num_components > 4) {
1346           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1347                  << ext_inst_name() << ": "
1348                  << "expected operand P0 to have no more than 4 components";
1349         }
1350 
1351         if (result_type != _.GetComponentType(p0_type)) {
1352           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1353                  << ext_inst_name() << ": "
1354                  << "expected operand P0 component type to be equal to "
1355                  << "Result Type";
1356         }
1357 
1358         const uint32_t p1_type = _.GetOperandTypeId(inst, 5);
1359         if (p0_type != p1_type) {
1360           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1361                  << ext_inst_name() << ": "
1362                  << "expected operands P0 and P1 to be of the same type";
1363         }
1364         break;
1365       }
1366 
1367       case OpenCLLIB::Length:
1368       case OpenCLLIB::Fast_length: {
1369         if (!_.IsFloatScalarType(result_type)) {
1370           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1371                  << ext_inst_name() << ": "
1372                  << "expected Result Type to be a float scalar type";
1373         }
1374 
1375         const uint32_t p_type = _.GetOperandTypeId(inst, 4);
1376         if (!_.IsFloatScalarOrVectorType(p_type)) {
1377           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1378                  << ext_inst_name() << ": "
1379                  << "expected operand P to be a float scalar or vector";
1380         }
1381 
1382         const uint32_t num_components = _.GetDimension(p_type);
1383         if (num_components > 4) {
1384           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1385                  << ext_inst_name() << ": "
1386                  << "expected operand P to have no more than 4 components";
1387         }
1388 
1389         if (result_type != _.GetComponentType(p_type)) {
1390           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1391                  << ext_inst_name() << ": "
1392                  << "expected operand P component type to be equal to Result "
1393                     "Type";
1394         }
1395         break;
1396       }
1397 
1398       case OpenCLLIB::Normalize:
1399       case OpenCLLIB::Fast_normalize: {
1400         if (!_.IsFloatScalarOrVectorType(result_type)) {
1401           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1402                  << ext_inst_name() << ": "
1403                  << "expected Result Type to be a float scalar or vector type";
1404         }
1405 
1406         const uint32_t num_components = _.GetDimension(result_type);
1407         if (num_components > 4) {
1408           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1409                  << ext_inst_name() << ": "
1410                  << "expected Result Type to have no more than 4 components";
1411         }
1412 
1413         const uint32_t p_type = _.GetOperandTypeId(inst, 4);
1414         if (p_type != result_type) {
1415           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1416                  << ext_inst_name() << ": "
1417                  << "expected operand P type to be equal to Result Type";
1418         }
1419         break;
1420       }
1421 
1422       case OpenCLLIB::Bitselect: {
1423         if (!_.IsFloatScalarOrVectorType(result_type) &&
1424             !_.IsIntScalarOrVectorType(result_type)) {
1425           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1426                  << ext_inst_name() << ": "
1427                  << "expected Result Type to be an int or float scalar or "
1428                     "vector type";
1429         }
1430 
1431         const uint32_t num_components = _.GetDimension(result_type);
1432         if (num_components > 4 && num_components != 8 && num_components != 16) {
1433           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1434                  << ext_inst_name() << ": "
1435                  << "expected Result Type to be a scalar or a vector with 2, "
1436                     "3, 4, 8 or 16 components";
1437         }
1438 
1439         for (uint32_t operand_index = 4; operand_index < num_operands;
1440              ++operand_index) {
1441           const uint32_t operand_type = _.GetOperandTypeId(inst, operand_index);
1442           if (result_type != operand_type) {
1443             return _.diag(SPV_ERROR_INVALID_DATA, inst)
1444                    << ext_inst_name() << ": "
1445                    << "expected types of all operands to be equal to Result "
1446                       "Type";
1447           }
1448         }
1449         break;
1450       }
1451 
1452       case OpenCLLIB::Select: {
1453         if (!_.IsFloatScalarOrVectorType(result_type) &&
1454             !_.IsIntScalarOrVectorType(result_type)) {
1455           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1456                  << ext_inst_name() << ": "
1457                  << "expected Result Type to be an int or float scalar or "
1458                     "vector type";
1459         }
1460 
1461         const uint32_t num_components = _.GetDimension(result_type);
1462         if (num_components > 4 && num_components != 8 && num_components != 16) {
1463           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1464                  << ext_inst_name() << ": "
1465                  << "expected Result Type to be a scalar or a vector with 2, "
1466                     "3, 4, 8 or 16 components";
1467         }
1468 
1469         const uint32_t a_type = _.GetOperandTypeId(inst, 4);
1470         const uint32_t b_type = _.GetOperandTypeId(inst, 5);
1471         const uint32_t c_type = _.GetOperandTypeId(inst, 6);
1472 
1473         if (result_type != a_type) {
1474           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1475                  << ext_inst_name() << ": "
1476                  << "expected operand A type to be equal to Result Type";
1477         }
1478 
1479         if (result_type != b_type) {
1480           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1481                  << ext_inst_name() << ": "
1482                  << "expected operand B type to be equal to Result Type";
1483         }
1484 
1485         if (!_.IsIntScalarOrVectorType(c_type)) {
1486           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1487                  << ext_inst_name() << ": "
1488                  << "expected operand C to be an int scalar or vector";
1489         }
1490 
1491         if (num_components != _.GetDimension(c_type)) {
1492           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1493                  << ext_inst_name() << ": "
1494                  << "expected operand C to have the same number of components "
1495                     "as Result Type";
1496         }
1497 
1498         if (_.GetBitWidth(result_type) != _.GetBitWidth(c_type)) {
1499           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1500                  << ext_inst_name() << ": "
1501                  << "expected operand C to have the same bit width as Result "
1502                     "Type";
1503         }
1504         break;
1505       }
1506 
1507       case OpenCLLIB::Vloadn: {
1508         if (!_.IsFloatVectorType(result_type) &&
1509             !_.IsIntVectorType(result_type)) {
1510           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1511                  << ext_inst_name() << ": "
1512                  << "expected Result Type to be an int or float vector type";
1513         }
1514 
1515         const uint32_t num_components = _.GetDimension(result_type);
1516         if (num_components > 4 && num_components != 8 && num_components != 16) {
1517           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1518                  << ext_inst_name() << ": "
1519                  << "expected Result Type to have 2, 3, 4, 8 or 16 components";
1520         }
1521 
1522         const uint32_t offset_type = _.GetOperandTypeId(inst, 4);
1523         const uint32_t p_type = _.GetOperandTypeId(inst, 5);
1524 
1525         const uint32_t size_t_bit_width = GetSizeTBitWidth(_);
1526         if (!size_t_bit_width) {
1527           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1528                  << ext_inst_name()
1529                  << " can only be used with physical addressing models";
1530         }
1531 
1532         if (!_.IsIntScalarType(offset_type) ||
1533             _.GetBitWidth(offset_type) != size_t_bit_width) {
1534           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1535                  << ext_inst_name() << ": "
1536                  << "expected operand Offset to be of type size_t ("
1537                  << size_t_bit_width
1538                  << "-bit integer for the addressing model used in the module)";
1539         }
1540 
1541         uint32_t p_storage_class = 0;
1542         uint32_t p_data_type = 0;
1543         if (!_.GetPointerTypeInfo(p_type, &p_data_type, &p_storage_class)) {
1544           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1545                  << ext_inst_name() << ": "
1546                  << "expected operand P to be a pointer";
1547         }
1548 
1549         if (p_storage_class != SpvStorageClassUniformConstant &&
1550             p_storage_class != SpvStorageClassGeneric) {
1551           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1552                  << ext_inst_name() << ": "
1553                  << "expected operand P storage class to be UniformConstant or "
1554                     "Generic";
1555         }
1556 
1557         if (_.GetComponentType(result_type) != p_data_type) {
1558           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1559                  << ext_inst_name() << ": "
1560                  << "expected operand P data type to be equal to component "
1561                     "type of Result Type";
1562         }
1563 
1564         const uint32_t n_value = inst->word(7);
1565         if (num_components != n_value) {
1566           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1567                  << ext_inst_name() << ": "
1568                  << "expected literal N to be equal to the number of "
1569                     "components of Result Type";
1570         }
1571         break;
1572       }
1573 
1574       case OpenCLLIB::Vstoren: {
1575         if (_.GetIdOpcode(result_type) != SpvOpTypeVoid) {
1576           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1577                  << ext_inst_name() << ": expected Result Type to be void";
1578         }
1579 
1580         const uint32_t data_type = _.GetOperandTypeId(inst, 4);
1581         const uint32_t offset_type = _.GetOperandTypeId(inst, 5);
1582         const uint32_t p_type = _.GetOperandTypeId(inst, 6);
1583 
1584         if (!_.IsFloatVectorType(data_type) && !_.IsIntVectorType(data_type)) {
1585           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1586                  << ext_inst_name() << ": "
1587                  << "expected Data to be an int or float vector";
1588         }
1589 
1590         const uint32_t num_components = _.GetDimension(data_type);
1591         if (num_components > 4 && num_components != 8 && num_components != 16) {
1592           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1593                  << ext_inst_name() << ": "
1594                  << "expected Data to have 2, 3, 4, 8 or 16 components";
1595         }
1596 
1597         const uint32_t size_t_bit_width = GetSizeTBitWidth(_);
1598         if (!size_t_bit_width) {
1599           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1600                  << ext_inst_name()
1601                  << " can only be used with physical addressing models";
1602         }
1603 
1604         if (!_.IsIntScalarType(offset_type) ||
1605             _.GetBitWidth(offset_type) != size_t_bit_width) {
1606           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1607                  << ext_inst_name() << ": "
1608                  << "expected operand Offset to be of type size_t ("
1609                  << size_t_bit_width
1610                  << "-bit integer for the addressing model used in the module)";
1611         }
1612 
1613         uint32_t p_storage_class = 0;
1614         uint32_t p_data_type = 0;
1615         if (!_.GetPointerTypeInfo(p_type, &p_data_type, &p_storage_class)) {
1616           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1617                  << ext_inst_name() << ": "
1618                  << "expected operand P to be a pointer";
1619         }
1620 
1621         if (p_storage_class != SpvStorageClassGeneric) {
1622           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1623                  << ext_inst_name() << ": "
1624                  << "expected operand P storage class to be Generic";
1625         }
1626 
1627         if (_.GetComponentType(data_type) != p_data_type) {
1628           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1629                  << ext_inst_name() << ": "
1630                  << "expected operand P data type to be equal to the type of "
1631                     "operand Data components";
1632         }
1633         break;
1634       }
1635 
1636       case OpenCLLIB::Vload_half: {
1637         if (!_.IsFloatScalarType(result_type)) {
1638           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1639                  << ext_inst_name() << ": "
1640                  << "expected Result Type to be a float scalar type";
1641         }
1642 
1643         const uint32_t offset_type = _.GetOperandTypeId(inst, 4);
1644         const uint32_t p_type = _.GetOperandTypeId(inst, 5);
1645 
1646         const uint32_t size_t_bit_width = GetSizeTBitWidth(_);
1647         if (!size_t_bit_width) {
1648           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1649                  << ext_inst_name()
1650                  << " can only be used with physical addressing models";
1651         }
1652 
1653         if (!_.IsIntScalarType(offset_type) ||
1654             _.GetBitWidth(offset_type) != size_t_bit_width) {
1655           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1656                  << ext_inst_name() << ": "
1657                  << "expected operand Offset to be of type size_t ("
1658                  << size_t_bit_width
1659                  << "-bit integer for the addressing model used in the module)";
1660         }
1661 
1662         uint32_t p_storage_class = 0;
1663         uint32_t p_data_type = 0;
1664         if (!_.GetPointerTypeInfo(p_type, &p_data_type, &p_storage_class)) {
1665           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1666                  << ext_inst_name() << ": "
1667                  << "expected operand P to be a pointer";
1668         }
1669 
1670         if (p_storage_class != SpvStorageClassUniformConstant &&
1671             p_storage_class != SpvStorageClassGeneric &&
1672             p_storage_class != SpvStorageClassCrossWorkgroup &&
1673             p_storage_class != SpvStorageClassWorkgroup &&
1674             p_storage_class != SpvStorageClassFunction) {
1675           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1676                  << ext_inst_name() << ": "
1677                  << "expected operand P storage class to be UniformConstant, "
1678                     "Generic, CrossWorkgroup, Workgroup or Function";
1679         }
1680 
1681         if (!_.IsFloatScalarType(p_data_type) ||
1682             _.GetBitWidth(p_data_type) != 16) {
1683           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1684                  << ext_inst_name() << ": "
1685                  << "expected operand P data type to be 16-bit float scalar";
1686         }
1687         break;
1688       }
1689 
1690       case OpenCLLIB::Vload_halfn:
1691       case OpenCLLIB::Vloada_halfn: {
1692         if (!_.IsFloatVectorType(result_type)) {
1693           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1694                  << ext_inst_name() << ": "
1695                  << "expected Result Type to be a float vector type";
1696         }
1697 
1698         const uint32_t num_components = _.GetDimension(result_type);
1699         if (num_components > 4 && num_components != 8 && num_components != 16) {
1700           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1701                  << ext_inst_name() << ": "
1702                  << "expected Result Type to have 2, 3, 4, 8 or 16 components";
1703         }
1704 
1705         const uint32_t offset_type = _.GetOperandTypeId(inst, 4);
1706         const uint32_t p_type = _.GetOperandTypeId(inst, 5);
1707 
1708         const uint32_t size_t_bit_width = GetSizeTBitWidth(_);
1709         if (!size_t_bit_width) {
1710           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1711                  << ext_inst_name()
1712                  << " can only be used with physical addressing models";
1713         }
1714 
1715         if (!_.IsIntScalarType(offset_type) ||
1716             _.GetBitWidth(offset_type) != size_t_bit_width) {
1717           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1718                  << ext_inst_name() << ": "
1719                  << "expected operand Offset to be of type size_t ("
1720                  << size_t_bit_width
1721                  << "-bit integer for the addressing model used in the module)";
1722         }
1723 
1724         uint32_t p_storage_class = 0;
1725         uint32_t p_data_type = 0;
1726         if (!_.GetPointerTypeInfo(p_type, &p_data_type, &p_storage_class)) {
1727           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1728                  << ext_inst_name() << ": "
1729                  << "expected operand P to be a pointer";
1730         }
1731 
1732         if (p_storage_class != SpvStorageClassUniformConstant &&
1733             p_storage_class != SpvStorageClassGeneric &&
1734             p_storage_class != SpvStorageClassCrossWorkgroup &&
1735             p_storage_class != SpvStorageClassWorkgroup &&
1736             p_storage_class != SpvStorageClassFunction) {
1737           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1738                  << ext_inst_name() << ": "
1739                  << "expected operand P storage class to be UniformConstant, "
1740                     "Generic, CrossWorkgroup, Workgroup or Function";
1741         }
1742 
1743         if (!_.IsFloatScalarType(p_data_type) ||
1744             _.GetBitWidth(p_data_type) != 16) {
1745           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1746                  << ext_inst_name() << ": "
1747                  << "expected operand P data type to be 16-bit float scalar";
1748         }
1749 
1750         const uint32_t n_value = inst->word(7);
1751         if (num_components != n_value) {
1752           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1753                  << ext_inst_name() << ": "
1754                  << "expected literal N to be equal to the number of "
1755                     "components of Result Type";
1756         }
1757         break;
1758       }
1759 
1760       case OpenCLLIB::Vstore_half:
1761       case OpenCLLIB::Vstore_half_r:
1762       case OpenCLLIB::Vstore_halfn:
1763       case OpenCLLIB::Vstore_halfn_r:
1764       case OpenCLLIB::Vstorea_halfn:
1765       case OpenCLLIB::Vstorea_halfn_r: {
1766         if (_.GetIdOpcode(result_type) != SpvOpTypeVoid) {
1767           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1768                  << ext_inst_name() << ": expected Result Type to be void";
1769         }
1770 
1771         const uint32_t data_type = _.GetOperandTypeId(inst, 4);
1772         const uint32_t offset_type = _.GetOperandTypeId(inst, 5);
1773         const uint32_t p_type = _.GetOperandTypeId(inst, 6);
1774         const uint32_t data_type_bit_width = _.GetBitWidth(data_type);
1775 
1776         if (ext_inst_key == OpenCLLIB::Vstore_half ||
1777             ext_inst_key == OpenCLLIB::Vstore_half_r) {
1778           if (!_.IsFloatScalarType(data_type) ||
1779               (data_type_bit_width != 32 && data_type_bit_width != 64)) {
1780             return _.diag(SPV_ERROR_INVALID_DATA, inst)
1781                    << ext_inst_name() << ": "
1782                    << "expected Data to be a 32 or 64-bit float scalar";
1783           }
1784         } else {
1785           if (!_.IsFloatVectorType(data_type) ||
1786               (data_type_bit_width != 32 && data_type_bit_width != 64)) {
1787             return _.diag(SPV_ERROR_INVALID_DATA, inst)
1788                    << ext_inst_name() << ": "
1789                    << "expected Data to be a 32 or 64-bit float vector";
1790           }
1791 
1792           const uint32_t num_components = _.GetDimension(data_type);
1793           if (num_components > 4 && num_components != 8 &&
1794               num_components != 16) {
1795             return _.diag(SPV_ERROR_INVALID_DATA, inst)
1796                    << ext_inst_name() << ": "
1797                    << "expected Data to have 2, 3, 4, 8 or 16 components";
1798           }
1799         }
1800 
1801         const uint32_t size_t_bit_width = GetSizeTBitWidth(_);
1802         if (!size_t_bit_width) {
1803           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1804                  << ext_inst_name()
1805                  << " can only be used with physical addressing models";
1806         }
1807 
1808         if (!_.IsIntScalarType(offset_type) ||
1809             _.GetBitWidth(offset_type) != size_t_bit_width) {
1810           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1811                  << ext_inst_name() << ": "
1812                  << "expected operand Offset to be of type size_t ("
1813                  << size_t_bit_width
1814                  << "-bit integer for the addressing model used in the module)";
1815         }
1816 
1817         uint32_t p_storage_class = 0;
1818         uint32_t p_data_type = 0;
1819         if (!_.GetPointerTypeInfo(p_type, &p_data_type, &p_storage_class)) {
1820           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1821                  << ext_inst_name() << ": "
1822                  << "expected operand P to be a pointer";
1823         }
1824 
1825         if (p_storage_class != SpvStorageClassGeneric &&
1826             p_storage_class != SpvStorageClassCrossWorkgroup &&
1827             p_storage_class != SpvStorageClassWorkgroup &&
1828             p_storage_class != SpvStorageClassFunction) {
1829           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1830                  << ext_inst_name() << ": "
1831                  << "expected operand P storage class to be Generic, "
1832                     "CrossWorkgroup, Workgroup or Function";
1833         }
1834 
1835         if (!_.IsFloatScalarType(p_data_type) ||
1836             _.GetBitWidth(p_data_type) != 16) {
1837           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1838                  << ext_inst_name() << ": "
1839                  << "expected operand P data type to be 16-bit float scalar";
1840         }
1841 
1842         // Rounding mode enum is checked by assembler.
1843         break;
1844       }
1845 
1846       case OpenCLLIB::Shuffle:
1847       case OpenCLLIB::Shuffle2: {
1848         if (!_.IsFloatVectorType(result_type) &&
1849             !_.IsIntVectorType(result_type)) {
1850           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1851                  << ext_inst_name() << ": "
1852                  << "expected Result Type to be an int or float vector type";
1853         }
1854 
1855         const uint32_t result_num_components = _.GetDimension(result_type);
1856         if (result_num_components != 2 && result_num_components != 4 &&
1857             result_num_components != 8 && result_num_components != 16) {
1858           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1859                  << ext_inst_name() << ": "
1860                  << "expected Result Type to have 2, 4, 8 or 16 components";
1861         }
1862 
1863         uint32_t operand_index = 4;
1864         const uint32_t x_type = _.GetOperandTypeId(inst, operand_index++);
1865 
1866         if (ext_inst_key == OpenCLLIB::Shuffle2) {
1867           const uint32_t y_type = _.GetOperandTypeId(inst, operand_index++);
1868           if (x_type != y_type) {
1869             return _.diag(SPV_ERROR_INVALID_DATA, inst)
1870                    << ext_inst_name() << ": "
1871                    << "expected operands X and Y to be of the same type";
1872           }
1873         }
1874 
1875         const uint32_t shuffle_mask_type =
1876             _.GetOperandTypeId(inst, operand_index++);
1877 
1878         if (!_.IsFloatVectorType(x_type) && !_.IsIntVectorType(x_type)) {
1879           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1880                  << ext_inst_name() << ": "
1881                  << "expected operand X to be an int or float vector";
1882         }
1883 
1884         const uint32_t x_num_components = _.GetDimension(x_type);
1885         if (x_num_components != 2 && x_num_components != 4 &&
1886             x_num_components != 8 && x_num_components != 16) {
1887           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1888                  << ext_inst_name() << ": "
1889                  << "expected operand X to have 2, 4, 8 or 16 components";
1890         }
1891 
1892         const uint32_t result_component_type = _.GetComponentType(result_type);
1893 
1894         if (result_component_type != _.GetComponentType(x_type)) {
1895           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1896                  << ext_inst_name() << ": "
1897                  << "expected operand X and Result Type to have equal "
1898                     "component types";
1899         }
1900 
1901         if (!_.IsIntVectorType(shuffle_mask_type)) {
1902           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1903                  << ext_inst_name() << ": "
1904                  << "expected operand Shuffle Mask to be an int vector";
1905         }
1906 
1907         if (result_num_components != _.GetDimension(shuffle_mask_type)) {
1908           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1909                  << ext_inst_name() << ": "
1910                  << "expected operand Shuffle Mask to have the same number of "
1911                     "components as Result Type";
1912         }
1913 
1914         if (_.GetBitWidth(result_component_type) !=
1915             _.GetBitWidth(shuffle_mask_type)) {
1916           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1917                  << ext_inst_name() << ": "
1918                  << "expected operand Shuffle Mask components to have the same "
1919                     "bit width as Result Type components";
1920         }
1921         break;
1922       }
1923 
1924       case OpenCLLIB::Printf: {
1925         if (!_.IsIntScalarType(result_type) ||
1926             _.GetBitWidth(result_type) != 32) {
1927           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1928                  << ext_inst_name() << ": "
1929                  << "expected Result Type to be a 32-bit int type";
1930         }
1931 
1932         const uint32_t format_type = _.GetOperandTypeId(inst, 4);
1933         uint32_t format_storage_class = 0;
1934         uint32_t format_data_type = 0;
1935         if (!_.GetPointerTypeInfo(format_type, &format_data_type,
1936                                   &format_storage_class)) {
1937           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1938                  << ext_inst_name() << ": "
1939                  << "expected operand Format to be a pointer";
1940         }
1941 
1942         if (format_storage_class != SpvStorageClassUniformConstant) {
1943           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1944                  << ext_inst_name() << ": "
1945                  << "expected Format storage class to be UniformConstant";
1946         }
1947 
1948         if (!_.IsIntScalarType(format_data_type) ||
1949             _.GetBitWidth(format_data_type) != 8) {
1950           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1951                  << ext_inst_name() << ": "
1952                  << "expected Format data type to be 8-bit int";
1953         }
1954         break;
1955       }
1956 
1957       case OpenCLLIB::Prefetch: {
1958         if (_.GetIdOpcode(result_type) != SpvOpTypeVoid) {
1959           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1960                  << ext_inst_name() << ": expected Result Type to be void";
1961         }
1962 
1963         const uint32_t p_type = _.GetOperandTypeId(inst, 4);
1964         const uint32_t num_elements_type = _.GetOperandTypeId(inst, 5);
1965 
1966         uint32_t p_storage_class = 0;
1967         uint32_t p_data_type = 0;
1968         if (!_.GetPointerTypeInfo(p_type, &p_data_type, &p_storage_class)) {
1969           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1970                  << ext_inst_name() << ": "
1971                  << "expected operand Ptr to be a pointer";
1972         }
1973 
1974         if (p_storage_class != SpvStorageClassCrossWorkgroup) {
1975           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1976                  << ext_inst_name() << ": "
1977                  << "expected operand Ptr storage class to be CrossWorkgroup";
1978         }
1979 
1980         if (!_.IsFloatScalarOrVectorType(p_data_type) &&
1981             !_.IsIntScalarOrVectorType(p_data_type)) {
1982           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1983                  << ext_inst_name() << ": "
1984                  << "expected Ptr data type to be int or float scalar or "
1985                     "vector";
1986         }
1987 
1988         const uint32_t num_components = _.GetDimension(p_data_type);
1989         if (num_components > 4 && num_components != 8 && num_components != 16) {
1990           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1991                  << ext_inst_name() << ": "
1992                  << "expected Result Type to be a scalar or a vector with 2, "
1993                     "3, 4, 8 or 16 components";
1994         }
1995 
1996         const uint32_t size_t_bit_width = GetSizeTBitWidth(_);
1997         if (!size_t_bit_width) {
1998           return _.diag(SPV_ERROR_INVALID_DATA, inst)
1999                  << ext_inst_name()
2000                  << " can only be used with physical addressing models";
2001         }
2002 
2003         if (!_.IsIntScalarType(num_elements_type) ||
2004             _.GetBitWidth(num_elements_type) != size_t_bit_width) {
2005           return _.diag(SPV_ERROR_INVALID_DATA, inst)
2006                  << ext_inst_name() << ": "
2007                  << "expected operand Num Elements to be of type size_t ("
2008                  << size_t_bit_width
2009                  << "-bit integer for the addressing model used in the module)";
2010         }
2011         break;
2012       }
2013     }
2014   }
2015 
2016   return SPV_SUCCESS;
2017 }
2018 
ExtensionPass(ValidationState_t & _,const Instruction * inst)2019 spv_result_t ExtensionPass(ValidationState_t& _, const Instruction* inst) {
2020   const SpvOp opcode = inst->opcode();
2021   if (opcode == SpvOpExtension) return ValidateExtension(_, inst);
2022   if (opcode == SpvOpExtInstImport) return ValidateExtInstImport(_, inst);
2023   if (opcode == SpvOpExtInst) return ValidateExtInst(_, inst);
2024 
2025   return SPV_SUCCESS;
2026 }
2027 
2028 }  // namespace val
2029 }  // namespace spvtools
2030