validate_conversion.cpp 23 KB

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