| 88 | } |
| 89 | |
| 90 | spv_result_t ValidateGroupAsyncCopy(ValidationState_t& _, |
| 91 | const Instruction* inst) { |
| 92 | if (_.FindDef(inst->type_id())->opcode() != spv::Op::OpTypeEvent) { |
| 93 | return _.diag(SPV_ERROR_INVALID_DATA, inst) |
| 94 | << "The result type must be OpTypeEvent."; |
| 95 | } |
| 96 | |
| 97 | const uint32_t destination = _.GetOperandTypeId(inst, 3); |
| 98 | const Instruction* destination_pointer = _.FindDef(destination); |
| 99 | if (destination_pointer->opcode() != spv::Op::OpTypePointer) { |
| 100 | return _.diag(SPV_ERROR_INVALID_DATA, inst) |
| 101 | << "Expected Destination to be a pointer."; |
| 102 | } |
| 103 | const auto destination_sc = |
| 104 | destination_pointer->GetOperandAs<spv::StorageClass>(1); |
| 105 | if (destination_sc != spv::StorageClass::Workgroup && |
| 106 | destination_sc != spv::StorageClass::CrossWorkgroup) { |
| 107 | return _.diag(SPV_ERROR_INVALID_DATA, inst) |
| 108 | << "Expected Destination to be a pointer with storage class " |
| 109 | "Workgroup or CrossWorkgroup."; |
| 110 | } |
| 111 | const uint32_t destination_type = |
| 112 | destination_pointer->GetOperandAs<uint32_t>(2); |
| 113 | if (!_.IsIntScalarOrVectorType(destination_type) && |
| 114 | !_.IsFloatScalarOrVectorType(destination_type)) { |
| 115 | return _.diag(SPV_ERROR_INVALID_DATA, inst) |
| 116 | << "Expected Destination to be a pointer to scalar or vector of " |
| 117 | "floating-point type or integer type."; |
| 118 | } |
| 119 | |
| 120 | const uint32_t source = _.GetOperandTypeId(inst, 4); |
| 121 | const Instruction* source_pointer = _.FindDef(source); |
| 122 | const auto source_sc = source_pointer->GetOperandAs<spv::StorageClass>(1); |
| 123 | const uint32_t source_type = source_pointer->GetOperandAs<uint32_t>(2); |
| 124 | if (destination_type != source_type) { |
| 125 | return _.diag(SPV_ERROR_INVALID_DATA, inst) |
| 126 | << "Expected Destination and Source to be the same type."; |
| 127 | } |
| 128 | |
| 129 | if (destination_sc == spv::StorageClass::Workgroup && |
| 130 | source_sc != spv::StorageClass::CrossWorkgroup) { |
| 131 | return _.diag(SPV_ERROR_INVALID_DATA, inst) |
| 132 | << "If Destination storage class is Workgroup, then the Source " |
| 133 | "storage class must be CrossWorkgroup."; |
| 134 | } else if (destination_sc == spv::StorageClass::CrossWorkgroup && |
| 135 | source_sc != spv::StorageClass::Workgroup) { |
| 136 | return _.diag(SPV_ERROR_INVALID_DATA, inst) |
| 137 | << "If Destination storage class is CrossWorkgroup, then the Source " |
| 138 | "storage class must be Workgroup."; |
| 139 | } |
| 140 | |
| 141 | const bool is_physical_64 = |
| 142 | _.addressing_model() == spv::AddressingModel::Physical64; |
| 143 | const uint32_t bit_width = is_physical_64 ? 64 : 32; |
| 144 | |
| 145 | const uint32_t num_elements_type = |
| 146 | _.GetTypeId(inst->GetOperandAs<uint32_t>(5)); |
| 147 | if (!_.IsIntScalarType(num_elements_type, bit_width)) { |
no test coverage detected