validate_bitwise.cpp 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  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 bitwise 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 bitwise instructions.
  23. spv_result_t BitwisePass(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 SpvOpShiftRightLogical:
  28. case SpvOpShiftRightArithmetic:
  29. case SpvOpShiftLeftLogical: {
  30. if (!_.IsIntScalarType(result_type) && !_.IsIntVectorType(result_type))
  31. return _.diag(SPV_ERROR_INVALID_DATA, inst)
  32. << "Expected int scalar or vector type as Result Type: "
  33. << spvOpcodeString(opcode);
  34. const uint32_t result_dimension = _.GetDimension(result_type);
  35. const uint32_t base_type = _.GetOperandTypeId(inst, 2);
  36. const uint32_t shift_type = _.GetOperandTypeId(inst, 3);
  37. if (!base_type ||
  38. (!_.IsIntScalarType(base_type) && !_.IsIntVectorType(base_type)))
  39. return _.diag(SPV_ERROR_INVALID_DATA, inst)
  40. << "Expected Base to be int scalar or vector: "
  41. << spvOpcodeString(opcode);
  42. if (_.GetDimension(base_type) != result_dimension)
  43. return _.diag(SPV_ERROR_INVALID_DATA, inst)
  44. << "Expected Base to have the same dimension "
  45. << "as Result Type: " << spvOpcodeString(opcode);
  46. if (_.GetBitWidth(base_type) != _.GetBitWidth(result_type))
  47. return _.diag(SPV_ERROR_INVALID_DATA, inst)
  48. << "Expected Base to have the same bit width "
  49. << "as Result Type: " << spvOpcodeString(opcode);
  50. if (!shift_type ||
  51. (!_.IsIntScalarType(shift_type) && !_.IsIntVectorType(shift_type)))
  52. return _.diag(SPV_ERROR_INVALID_DATA, inst)
  53. << "Expected Shift to be int scalar or vector: "
  54. << spvOpcodeString(opcode);
  55. if (_.GetDimension(shift_type) != result_dimension)
  56. return _.diag(SPV_ERROR_INVALID_DATA, inst)
  57. << "Expected Shift to have the same dimension "
  58. << "as Result Type: " << spvOpcodeString(opcode);
  59. break;
  60. }
  61. case SpvOpBitwiseOr:
  62. case SpvOpBitwiseXor:
  63. case SpvOpBitwiseAnd:
  64. case SpvOpNot: {
  65. if (!_.IsIntScalarType(result_type) && !_.IsIntVectorType(result_type))
  66. return _.diag(SPV_ERROR_INVALID_DATA, inst)
  67. << "Expected int scalar or vector type as Result Type: "
  68. << spvOpcodeString(opcode);
  69. const uint32_t result_dimension = _.GetDimension(result_type);
  70. const uint32_t result_bit_width = _.GetBitWidth(result_type);
  71. for (size_t operand_index = 2; operand_index < inst->operands().size();
  72. ++operand_index) {
  73. const uint32_t type_id = _.GetOperandTypeId(inst, operand_index);
  74. if (!type_id ||
  75. (!_.IsIntScalarType(type_id) && !_.IsIntVectorType(type_id)))
  76. return _.diag(SPV_ERROR_INVALID_DATA, inst)
  77. << "Expected int scalar or vector as operand: "
  78. << spvOpcodeString(opcode) << " operand index "
  79. << operand_index;
  80. if (_.GetDimension(type_id) != result_dimension)
  81. return _.diag(SPV_ERROR_INVALID_DATA, inst)
  82. << "Expected operands to have the same dimension "
  83. << "as Result Type: " << spvOpcodeString(opcode)
  84. << " operand index " << operand_index;
  85. if (_.GetBitWidth(type_id) != result_bit_width)
  86. return _.diag(SPV_ERROR_INVALID_DATA, inst)
  87. << "Expected operands to have the same bit width "
  88. << "as Result Type: " << spvOpcodeString(opcode)
  89. << " operand index " << operand_index;
  90. }
  91. break;
  92. }
  93. case SpvOpBitFieldInsert: {
  94. if (!_.IsIntScalarType(result_type) && !_.IsIntVectorType(result_type))
  95. return _.diag(SPV_ERROR_INVALID_DATA, inst)
  96. << "Expected int scalar or vector type as Result Type: "
  97. << spvOpcodeString(opcode);
  98. const uint32_t base_type = _.GetOperandTypeId(inst, 2);
  99. const uint32_t insert_type = _.GetOperandTypeId(inst, 3);
  100. const uint32_t offset_type = _.GetOperandTypeId(inst, 4);
  101. const uint32_t count_type = _.GetOperandTypeId(inst, 5);
  102. if (base_type != result_type)
  103. return _.diag(SPV_ERROR_INVALID_DATA, inst)
  104. << "Expected Base Type to be equal to Result Type: "
  105. << spvOpcodeString(opcode);
  106. if (insert_type != result_type)
  107. return _.diag(SPV_ERROR_INVALID_DATA, inst)
  108. << "Expected Insert Type to be equal to Result Type: "
  109. << spvOpcodeString(opcode);
  110. if (!offset_type || !_.IsIntScalarType(offset_type))
  111. return _.diag(SPV_ERROR_INVALID_DATA, inst)
  112. << "Expected Offset Type to be int scalar: "
  113. << spvOpcodeString(opcode);
  114. if (!count_type || !_.IsIntScalarType(count_type))
  115. return _.diag(SPV_ERROR_INVALID_DATA, inst)
  116. << "Expected Count Type to be int scalar: "
  117. << spvOpcodeString(opcode);
  118. break;
  119. }
  120. case SpvOpBitFieldSExtract:
  121. case SpvOpBitFieldUExtract: {
  122. if (!_.IsIntScalarType(result_type) && !_.IsIntVectorType(result_type))
  123. return _.diag(SPV_ERROR_INVALID_DATA, inst)
  124. << "Expected int scalar or vector type as Result Type: "
  125. << spvOpcodeString(opcode);
  126. const uint32_t base_type = _.GetOperandTypeId(inst, 2);
  127. const uint32_t offset_type = _.GetOperandTypeId(inst, 3);
  128. const uint32_t count_type = _.GetOperandTypeId(inst, 4);
  129. if (base_type != result_type)
  130. return _.diag(SPV_ERROR_INVALID_DATA, inst)
  131. << "Expected Base Type to be equal to Result Type: "
  132. << spvOpcodeString(opcode);
  133. if (!offset_type || !_.IsIntScalarType(offset_type))
  134. return _.diag(SPV_ERROR_INVALID_DATA, inst)
  135. << "Expected Offset Type to be int scalar: "
  136. << spvOpcodeString(opcode);
  137. if (!count_type || !_.IsIntScalarType(count_type))
  138. return _.diag(SPV_ERROR_INVALID_DATA, inst)
  139. << "Expected Count Type to be int scalar: "
  140. << spvOpcodeString(opcode);
  141. break;
  142. }
  143. case SpvOpBitReverse: {
  144. if (!_.IsIntScalarType(result_type) && !_.IsIntVectorType(result_type))
  145. return _.diag(SPV_ERROR_INVALID_DATA, inst)
  146. << "Expected int scalar or vector type as Result Type: "
  147. << spvOpcodeString(opcode);
  148. const uint32_t base_type = _.GetOperandTypeId(inst, 2);
  149. if (base_type != result_type)
  150. return _.diag(SPV_ERROR_INVALID_DATA, inst)
  151. << "Expected Base Type to be equal to Result Type: "
  152. << spvOpcodeString(opcode);
  153. break;
  154. }
  155. case SpvOpBitCount: {
  156. if (!_.IsIntScalarType(result_type) && !_.IsIntVectorType(result_type))
  157. return _.diag(SPV_ERROR_INVALID_DATA, inst)
  158. << "Expected int scalar or vector type as Result Type: "
  159. << spvOpcodeString(opcode);
  160. const uint32_t base_type = _.GetOperandTypeId(inst, 2);
  161. if (!base_type ||
  162. (!_.IsIntScalarType(base_type) && !_.IsIntVectorType(base_type)))
  163. return _.diag(SPV_ERROR_INVALID_DATA, inst)
  164. << "Expected Base Type to be int scalar or vector: "
  165. << spvOpcodeString(opcode);
  166. const uint32_t base_dimension = _.GetDimension(base_type);
  167. const uint32_t result_dimension = _.GetDimension(result_type);
  168. if (base_dimension != result_dimension)
  169. return _.diag(SPV_ERROR_INVALID_DATA, inst)
  170. << "Expected Base dimension to be equal to Result Type "
  171. "dimension: "
  172. << spvOpcodeString(opcode);
  173. break;
  174. }
  175. default:
  176. break;
  177. }
  178. return SPV_SUCCESS;
  179. }
  180. } // namespace val
  181. } // namespace spvtools