1 // Copyright (c) 2017 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 conversion instructions.
16 
17 #include "source/val/validate.h"
18 
19 #include "source/diagnostic.h"
20 #include "source/opcode.h"
21 #include "source/spirv_constant.h"
22 #include "source/val/instruction.h"
23 #include "source/val/validation_state.h"
24 
25 namespace spvtools {
26 namespace val {
27 
28 // Validates correctness of conversion instructions.
ConversionPass(ValidationState_t & _,const Instruction * inst)29 spv_result_t ConversionPass(ValidationState_t& _, const Instruction* inst) {
30   const SpvOp opcode = inst->opcode();
31   const uint32_t result_type = inst->type_id();
32 
33   switch (opcode) {
34     case SpvOpConvertFToU: {
35       if (!_.IsUnsignedIntScalarType(result_type) &&
36           !_.IsUnsignedIntVectorType(result_type) &&
37           !_.IsUnsignedIntCooperativeMatrixType(result_type))
38         return _.diag(SPV_ERROR_INVALID_DATA, inst)
39                << "Expected unsigned int scalar or vector type as Result Type: "
40                << spvOpcodeString(opcode);
41 
42       const uint32_t input_type = _.GetOperandTypeId(inst, 2);
43       if (!input_type || (!_.IsFloatScalarType(input_type) &&
44                           !_.IsFloatVectorType(input_type) &&
45                           !_.IsFloatCooperativeMatrixType(input_type)))
46         return _.diag(SPV_ERROR_INVALID_DATA, inst)
47                << "Expected input to be float scalar or vector: "
48                << spvOpcodeString(opcode);
49 
50       if (_.IsCooperativeMatrixType(result_type) ||
51           _.IsCooperativeMatrixType(input_type)) {
52         spv_result_t ret =
53             _.CooperativeMatrixShapesMatch(inst, result_type, input_type);
54         if (ret != SPV_SUCCESS) return ret;
55       } else {
56         if (_.GetDimension(result_type) != _.GetDimension(input_type))
57           return _.diag(SPV_ERROR_INVALID_DATA, inst)
58                  << "Expected input to have the same dimension as Result Type: "
59                  << spvOpcodeString(opcode);
60       }
61 
62       break;
63     }
64 
65     case SpvOpConvertFToS: {
66       if (!_.IsIntScalarType(result_type) && !_.IsIntVectorType(result_type) &&
67           !_.IsIntCooperativeMatrixType(result_type))
68         return _.diag(SPV_ERROR_INVALID_DATA, inst)
69                << "Expected int scalar or vector type as Result Type: "
70                << spvOpcodeString(opcode);
71 
72       const uint32_t input_type = _.GetOperandTypeId(inst, 2);
73       if (!input_type || (!_.IsFloatScalarType(input_type) &&
74                           !_.IsFloatVectorType(input_type) &&
75                           !_.IsFloatCooperativeMatrixType(input_type)))
76         return _.diag(SPV_ERROR_INVALID_DATA, inst)
77                << "Expected input to be float scalar or vector: "
78                << spvOpcodeString(opcode);
79 
80       if (_.IsCooperativeMatrixType(result_type) ||
81           _.IsCooperativeMatrixType(input_type)) {
82         spv_result_t ret =
83             _.CooperativeMatrixShapesMatch(inst, result_type, input_type);
84         if (ret != SPV_SUCCESS) return ret;
85       } else {
86         if (_.GetDimension(result_type) != _.GetDimension(input_type))
87           return _.diag(SPV_ERROR_INVALID_DATA, inst)
88                  << "Expected input to have the same dimension as Result Type: "
89                  << spvOpcodeString(opcode);
90       }
91 
92       break;
93     }
94 
95     case SpvOpConvertSToF:
96     case SpvOpConvertUToF: {
97       if (!_.IsFloatScalarType(result_type) &&
98           !_.IsFloatVectorType(result_type) &&
99           !_.IsFloatCooperativeMatrixType(result_type))
100         return _.diag(SPV_ERROR_INVALID_DATA, inst)
101                << "Expected float scalar or vector type as Result Type: "
102                << spvOpcodeString(opcode);
103 
104       const uint32_t input_type = _.GetOperandTypeId(inst, 2);
105       if (!input_type ||
106           (!_.IsIntScalarType(input_type) && !_.IsIntVectorType(input_type) &&
107            !_.IsIntCooperativeMatrixType(input_type)))
108         return _.diag(SPV_ERROR_INVALID_DATA, inst)
109                << "Expected input to be int scalar or vector: "
110                << spvOpcodeString(opcode);
111 
112       if (_.IsCooperativeMatrixType(result_type) ||
113           _.IsCooperativeMatrixType(input_type)) {
114         spv_result_t ret =
115             _.CooperativeMatrixShapesMatch(inst, result_type, input_type);
116         if (ret != SPV_SUCCESS) return ret;
117       } else {
118         if (_.GetDimension(result_type) != _.GetDimension(input_type))
119           return _.diag(SPV_ERROR_INVALID_DATA, inst)
120                  << "Expected input to have the same dimension as Result Type: "
121                  << spvOpcodeString(opcode);
122       }
123 
124       break;
125     }
126 
127     case SpvOpUConvert: {
128       if (!_.IsUnsignedIntScalarType(result_type) &&
129           !_.IsUnsignedIntVectorType(result_type) &&
130           !_.IsUnsignedIntCooperativeMatrixType(result_type))
131         return _.diag(SPV_ERROR_INVALID_DATA, inst)
132                << "Expected unsigned int scalar or vector type as Result Type: "
133                << spvOpcodeString(opcode);
134 
135       const uint32_t input_type = _.GetOperandTypeId(inst, 2);
136       if (!input_type ||
137           (!_.IsIntScalarType(input_type) && !_.IsIntVectorType(input_type) &&
138            !_.IsIntCooperativeMatrixType(input_type)))
139         return _.diag(SPV_ERROR_INVALID_DATA, inst)
140                << "Expected input to be int scalar or vector: "
141                << spvOpcodeString(opcode);
142 
143       if (_.IsCooperativeMatrixType(result_type) ||
144           _.IsCooperativeMatrixType(input_type)) {
145         spv_result_t ret =
146             _.CooperativeMatrixShapesMatch(inst, result_type, input_type);
147         if (ret != SPV_SUCCESS) return ret;
148       } else {
149         if (_.GetDimension(result_type) != _.GetDimension(input_type))
150           return _.diag(SPV_ERROR_INVALID_DATA, inst)
151                  << "Expected input to have the same dimension as Result Type: "
152                  << spvOpcodeString(opcode);
153       }
154 
155       if (_.GetBitWidth(result_type) == _.GetBitWidth(input_type))
156         return _.diag(SPV_ERROR_INVALID_DATA, inst)
157                << "Expected input to have different bit width from Result "
158                   "Type: "
159                << spvOpcodeString(opcode);
160       break;
161     }
162 
163     case SpvOpSConvert: {
164       if (!_.IsIntScalarType(result_type) && !_.IsIntVectorType(result_type) &&
165           !_.IsIntCooperativeMatrixType(result_type))
166         return _.diag(SPV_ERROR_INVALID_DATA, inst)
167                << "Expected int scalar or vector type as Result Type: "
168                << spvOpcodeString(opcode);
169 
170       const uint32_t input_type = _.GetOperandTypeId(inst, 2);
171       if (!input_type ||
172           (!_.IsIntScalarType(input_type) && !_.IsIntVectorType(input_type) &&
173            !_.IsIntCooperativeMatrixType(input_type)))
174         return _.diag(SPV_ERROR_INVALID_DATA, inst)
175                << "Expected input to be int scalar or vector: "
176                << spvOpcodeString(opcode);
177 
178       if (_.IsCooperativeMatrixType(result_type) ||
179           _.IsCooperativeMatrixType(input_type)) {
180         spv_result_t ret =
181             _.CooperativeMatrixShapesMatch(inst, result_type, input_type);
182         if (ret != SPV_SUCCESS) return ret;
183       } else {
184         if (_.GetDimension(result_type) != _.GetDimension(input_type))
185           return _.diag(SPV_ERROR_INVALID_DATA, inst)
186                  << "Expected input to have the same dimension as Result Type: "
187                  << spvOpcodeString(opcode);
188       }
189 
190       if (_.GetBitWidth(result_type) == _.GetBitWidth(input_type))
191         return _.diag(SPV_ERROR_INVALID_DATA, inst)
192                << "Expected input to have different bit width from Result "
193                   "Type: "
194                << spvOpcodeString(opcode);
195       break;
196     }
197 
198     case SpvOpFConvert: {
199       if (!_.IsFloatScalarType(result_type) &&
200           !_.IsFloatVectorType(result_type) &&
201           !_.IsFloatCooperativeMatrixType(result_type))
202         return _.diag(SPV_ERROR_INVALID_DATA, inst)
203                << "Expected float scalar or vector type as Result Type: "
204                << spvOpcodeString(opcode);
205 
206       const uint32_t input_type = _.GetOperandTypeId(inst, 2);
207       if (!input_type || (!_.IsFloatScalarType(input_type) &&
208                           !_.IsFloatVectorType(input_type) &&
209                           !_.IsFloatCooperativeMatrixType(input_type)))
210         return _.diag(SPV_ERROR_INVALID_DATA, inst)
211                << "Expected input to be float scalar or vector: "
212                << spvOpcodeString(opcode);
213 
214       if (_.IsCooperativeMatrixType(result_type) ||
215           _.IsCooperativeMatrixType(input_type)) {
216         spv_result_t ret =
217             _.CooperativeMatrixShapesMatch(inst, result_type, input_type);
218         if (ret != SPV_SUCCESS) return ret;
219       } else {
220         if (_.GetDimension(result_type) != _.GetDimension(input_type))
221           return _.diag(SPV_ERROR_INVALID_DATA, inst)
222                  << "Expected input to have the same dimension as Result Type: "
223                  << spvOpcodeString(opcode);
224       }
225 
226       if (_.GetBitWidth(result_type) == _.GetBitWidth(input_type))
227         return _.diag(SPV_ERROR_INVALID_DATA, inst)
228                << "Expected input to have different bit width from Result "
229                   "Type: "
230                << spvOpcodeString(opcode);
231       break;
232     }
233 
234     case SpvOpQuantizeToF16: {
235       if ((!_.IsFloatScalarType(result_type) &&
236            !_.IsFloatVectorType(result_type)) ||
237           _.GetBitWidth(result_type) != 32)
238         return _.diag(SPV_ERROR_INVALID_DATA, inst)
239                << "Expected 32-bit float scalar or vector type as Result Type: "
240                << spvOpcodeString(opcode);
241 
242       const uint32_t input_type = _.GetOperandTypeId(inst, 2);
243       if (input_type != result_type)
244         return _.diag(SPV_ERROR_INVALID_DATA, inst)
245                << "Expected input type to be equal to Result Type: "
246                << spvOpcodeString(opcode);
247       break;
248     }
249 
250     case SpvOpConvertPtrToU: {
251       if (!_.IsUnsignedIntScalarType(result_type))
252         return _.diag(SPV_ERROR_INVALID_DATA, inst)
253                << "Expected unsigned int scalar type as Result Type: "
254                << spvOpcodeString(opcode);
255 
256       const uint32_t input_type = _.GetOperandTypeId(inst, 2);
257       if (!_.IsPointerType(input_type))
258         return _.diag(SPV_ERROR_INVALID_DATA, inst)
259                << "Expected input to be a pointer: " << spvOpcodeString(opcode);
260 
261       if (_.addressing_model() == SpvAddressingModelLogical)
262         return _.diag(SPV_ERROR_INVALID_DATA, inst)
263                << "Logical addressing not supported: "
264                << spvOpcodeString(opcode);
265 
266       if (_.addressing_model() ==
267           SpvAddressingModelPhysicalStorageBuffer64EXT) {
268         uint32_t input_storage_class = 0;
269         uint32_t input_data_type = 0;
270         _.GetPointerTypeInfo(input_type, &input_data_type,
271                              &input_storage_class);
272         if (input_storage_class != SpvStorageClassPhysicalStorageBufferEXT)
273           return _.diag(SPV_ERROR_INVALID_DATA, inst)
274                  << "Pointer storage class must be PhysicalStorageBufferEXT: "
275                  << spvOpcodeString(opcode);
276       }
277       break;
278     }
279 
280     case SpvOpSatConvertSToU:
281     case SpvOpSatConvertUToS: {
282       if (!_.IsIntScalarType(result_type) && !_.IsIntVectorType(result_type))
283         return _.diag(SPV_ERROR_INVALID_DATA, inst)
284                << "Expected int scalar or vector type as Result Type: "
285                << spvOpcodeString(opcode);
286 
287       const uint32_t input_type = _.GetOperandTypeId(inst, 2);
288       if (!input_type ||
289           (!_.IsIntScalarType(input_type) && !_.IsIntVectorType(input_type)))
290         return _.diag(SPV_ERROR_INVALID_DATA, inst)
291                << "Expected int scalar or vector as input: "
292                << spvOpcodeString(opcode);
293 
294       if (_.GetDimension(result_type) != _.GetDimension(input_type))
295         return _.diag(SPV_ERROR_INVALID_DATA, inst)
296                << "Expected input to have the same dimension as Result Type: "
297                << spvOpcodeString(opcode);
298       break;
299     }
300 
301     case SpvOpConvertUToPtr: {
302       if (!_.IsPointerType(result_type))
303         return _.diag(SPV_ERROR_INVALID_DATA, inst)
304                << "Expected Result Type to be a pointer: "
305                << spvOpcodeString(opcode);
306 
307       const uint32_t input_type = _.GetOperandTypeId(inst, 2);
308       if (!input_type || !_.IsIntScalarType(input_type))
309         return _.diag(SPV_ERROR_INVALID_DATA, inst)
310                << "Expected int scalar as input: " << spvOpcodeString(opcode);
311 
312       if (_.addressing_model() == SpvAddressingModelLogical)
313         return _.diag(SPV_ERROR_INVALID_DATA, inst)
314                << "Logical addressing not supported: "
315                << spvOpcodeString(opcode);
316 
317       if (_.addressing_model() ==
318           SpvAddressingModelPhysicalStorageBuffer64EXT) {
319         uint32_t result_storage_class = 0;
320         uint32_t result_data_type = 0;
321         _.GetPointerTypeInfo(result_type, &result_data_type,
322                              &result_storage_class);
323         if (result_storage_class != SpvStorageClassPhysicalStorageBufferEXT)
324           return _.diag(SPV_ERROR_INVALID_DATA, inst)
325                  << "Pointer storage class must be PhysicalStorageBufferEXT: "
326                  << spvOpcodeString(opcode);
327       }
328       break;
329     }
330 
331     case SpvOpPtrCastToGeneric: {
332       uint32_t result_storage_class = 0;
333       uint32_t result_data_type = 0;
334       if (!_.GetPointerTypeInfo(result_type, &result_data_type,
335                                 &result_storage_class))
336         return _.diag(SPV_ERROR_INVALID_DATA, inst)
337                << "Expected Result Type to be a pointer: "
338                << spvOpcodeString(opcode);
339 
340       if (result_storage_class != SpvStorageClassGeneric)
341         return _.diag(SPV_ERROR_INVALID_DATA, inst)
342                << "Expected Result Type to have storage class Generic: "
343                << spvOpcodeString(opcode);
344 
345       const uint32_t input_type = _.GetOperandTypeId(inst, 2);
346       uint32_t input_storage_class = 0;
347       uint32_t input_data_type = 0;
348       if (!_.GetPointerTypeInfo(input_type, &input_data_type,
349                                 &input_storage_class))
350         return _.diag(SPV_ERROR_INVALID_DATA, inst)
351                << "Expected input to be a pointer: " << spvOpcodeString(opcode);
352 
353       if (input_storage_class != SpvStorageClassWorkgroup &&
354           input_storage_class != SpvStorageClassCrossWorkgroup &&
355           input_storage_class != SpvStorageClassFunction)
356         return _.diag(SPV_ERROR_INVALID_DATA, inst)
357                << "Expected input to have storage class Workgroup, "
358                << "CrossWorkgroup or Function: " << spvOpcodeString(opcode);
359 
360       if (result_data_type != input_data_type)
361         return _.diag(SPV_ERROR_INVALID_DATA, inst)
362                << "Expected input and Result Type to point to the same type: "
363                << spvOpcodeString(opcode);
364       break;
365     }
366 
367     case SpvOpGenericCastToPtr: {
368       uint32_t result_storage_class = 0;
369       uint32_t result_data_type = 0;
370       if (!_.GetPointerTypeInfo(result_type, &result_data_type,
371                                 &result_storage_class))
372         return _.diag(SPV_ERROR_INVALID_DATA, inst)
373                << "Expected Result Type to be a pointer: "
374                << spvOpcodeString(opcode);
375 
376       if (result_storage_class != SpvStorageClassWorkgroup &&
377           result_storage_class != SpvStorageClassCrossWorkgroup &&
378           result_storage_class != SpvStorageClassFunction)
379         return _.diag(SPV_ERROR_INVALID_DATA, inst)
380                << "Expected Result Type to have storage class Workgroup, "
381                << "CrossWorkgroup or Function: " << spvOpcodeString(opcode);
382 
383       const uint32_t input_type = _.GetOperandTypeId(inst, 2);
384       uint32_t input_storage_class = 0;
385       uint32_t input_data_type = 0;
386       if (!_.GetPointerTypeInfo(input_type, &input_data_type,
387                                 &input_storage_class))
388         return _.diag(SPV_ERROR_INVALID_DATA, inst)
389                << "Expected input to be a pointer: " << spvOpcodeString(opcode);
390 
391       if (input_storage_class != SpvStorageClassGeneric)
392         return _.diag(SPV_ERROR_INVALID_DATA, inst)
393                << "Expected input to have storage class Generic: "
394                << spvOpcodeString(opcode);
395 
396       if (result_data_type != input_data_type)
397         return _.diag(SPV_ERROR_INVALID_DATA, inst)
398                << "Expected input and Result Type to point to the same type: "
399                << spvOpcodeString(opcode);
400       break;
401     }
402 
403     case SpvOpGenericCastToPtrExplicit: {
404       uint32_t result_storage_class = 0;
405       uint32_t result_data_type = 0;
406       if (!_.GetPointerTypeInfo(result_type, &result_data_type,
407                                 &result_storage_class))
408         return _.diag(SPV_ERROR_INVALID_DATA, inst)
409                << "Expected Result Type to be a pointer: "
410                << spvOpcodeString(opcode);
411 
412       const uint32_t target_storage_class = inst->word(4);
413       if (result_storage_class != target_storage_class)
414         return _.diag(SPV_ERROR_INVALID_DATA, inst)
415                << "Expected Result Type to be of target storage class: "
416                << spvOpcodeString(opcode);
417 
418       const uint32_t input_type = _.GetOperandTypeId(inst, 2);
419       uint32_t input_storage_class = 0;
420       uint32_t input_data_type = 0;
421       if (!_.GetPointerTypeInfo(input_type, &input_data_type,
422                                 &input_storage_class))
423         return _.diag(SPV_ERROR_INVALID_DATA, inst)
424                << "Expected input to be a pointer: " << spvOpcodeString(opcode);
425 
426       if (input_storage_class != SpvStorageClassGeneric)
427         return _.diag(SPV_ERROR_INVALID_DATA, inst)
428                << "Expected input to have storage class Generic: "
429                << spvOpcodeString(opcode);
430 
431       if (result_data_type != input_data_type)
432         return _.diag(SPV_ERROR_INVALID_DATA, inst)
433                << "Expected input and Result Type to point to the same type: "
434                << spvOpcodeString(opcode);
435 
436       if (target_storage_class != SpvStorageClassWorkgroup &&
437           target_storage_class != SpvStorageClassCrossWorkgroup &&
438           target_storage_class != SpvStorageClassFunction)
439         return _.diag(SPV_ERROR_INVALID_DATA, inst)
440                << "Expected target storage class to be Workgroup, "
441                << "CrossWorkgroup or Function: " << spvOpcodeString(opcode);
442       break;
443     }
444 
445     case SpvOpBitcast: {
446       const uint32_t input_type = _.GetOperandTypeId(inst, 2);
447       if (!input_type)
448         return _.diag(SPV_ERROR_INVALID_DATA, inst)
449                << "Expected input to have a type: " << spvOpcodeString(opcode);
450 
451       const bool result_is_pointer = _.IsPointerType(result_type);
452       const bool result_is_int_scalar = _.IsIntScalarType(result_type);
453       const bool input_is_pointer = _.IsPointerType(input_type);
454       const bool input_is_int_scalar = _.IsIntScalarType(input_type);
455 
456       if (!result_is_pointer && !result_is_int_scalar &&
457           !_.IsIntVectorType(result_type) &&
458           !_.IsFloatScalarType(result_type) &&
459           !_.IsFloatVectorType(result_type))
460         return _.diag(SPV_ERROR_INVALID_DATA, inst)
461                << "Expected Result Type to be a pointer or int or float vector "
462                << "or scalar type: " << spvOpcodeString(opcode);
463 
464       if (!input_is_pointer && !input_is_int_scalar &&
465           !_.IsIntVectorType(input_type) && !_.IsFloatScalarType(input_type) &&
466           !_.IsFloatVectorType(input_type))
467         return _.diag(SPV_ERROR_INVALID_DATA, inst)
468                << "Expected input to be a pointer or int or float vector "
469                << "or scalar: " << spvOpcodeString(opcode);
470 
471       if (_.version() >= SPV_SPIRV_VERSION_WORD(1, 5) ||
472           _.HasExtension(kSPV_KHR_physical_storage_buffer)) {
473         const bool result_is_int_vector = _.IsIntVectorType(result_type);
474         const bool result_has_int32 =
475             _.ContainsSizedIntOrFloatType(result_type, SpvOpTypeInt, 32);
476         const bool input_is_int_vector = _.IsIntVectorType(input_type);
477         const bool input_has_int32 =
478             _.ContainsSizedIntOrFloatType(input_type, SpvOpTypeInt, 32);
479         if (result_is_pointer && !input_is_pointer && !input_is_int_scalar &&
480             !(input_is_int_vector && input_has_int32))
481           return _.diag(SPV_ERROR_INVALID_DATA, inst)
482                  << "Expected input to be a pointer, int scalar or 32-bit int "
483                     "vector if Result Type is pointer: "
484                  << spvOpcodeString(opcode);
485 
486         if (input_is_pointer && !result_is_pointer && !result_is_int_scalar &&
487             !(result_is_int_vector && result_has_int32))
488           return _.diag(SPV_ERROR_INVALID_DATA, inst)
489                  << "Pointer can only be converted to another pointer, int "
490                     "scalar or 32-bit int vector: "
491                  << spvOpcodeString(opcode);
492       } else {
493         if (result_is_pointer && !input_is_pointer && !input_is_int_scalar)
494           return _.diag(SPV_ERROR_INVALID_DATA, inst)
495                  << "Expected input to be a pointer or int scalar if Result "
496                     "Type is pointer: "
497                  << spvOpcodeString(opcode);
498 
499         if (input_is_pointer && !result_is_pointer && !result_is_int_scalar)
500           return _.diag(SPV_ERROR_INVALID_DATA, inst)
501                  << "Pointer can only be converted to another pointer or int "
502                     "scalar: "
503                  << spvOpcodeString(opcode);
504       }
505 
506       if (!result_is_pointer && !input_is_pointer) {
507         const uint32_t result_size =
508             _.GetBitWidth(result_type) * _.GetDimension(result_type);
509         const uint32_t input_size =
510             _.GetBitWidth(input_type) * _.GetDimension(input_type);
511         if (result_size != input_size)
512           return _.diag(SPV_ERROR_INVALID_DATA, inst)
513                  << "Expected input to have the same total bit width as "
514                  << "Result Type: " << spvOpcodeString(opcode);
515       }
516       break;
517     }
518 
519     default:
520       break;
521   }
522 
523   if (_.HasCapability(SpvCapabilityShader)) {
524     switch (inst->opcode()) {
525       case SpvOpConvertFToU:
526       case SpvOpConvertFToS:
527       case SpvOpConvertSToF:
528       case SpvOpConvertUToF:
529       case SpvOpBitcast:
530         if (_.ContainsLimitedUseIntOrFloatType(inst->type_id()) ||
531             _.ContainsLimitedUseIntOrFloatType(_.GetOperandTypeId(inst, 2u))) {
532           return _.diag(SPV_ERROR_INVALID_DATA, inst)
533                  << "8- or 16-bit types can only be used with width-only "
534                     "conversions";
535         }
536         break;
537       default:
538         break;
539     }
540   }
541 
542   return SPV_SUCCESS;
543 }
544 
545 }  // namespace val
546 }  // namespace spvtools
547