validate_conversion.cpp 21 KB

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