| 2113 | } |
| 2114 | |
| 2115 | spv_result_t ValidateRawAccessChain(ValidationState_t& _, |
| 2116 | const Instruction* inst) { |
| 2117 | const spv::Op opcode = inst->opcode(); |
| 2118 | // The result type must be OpTypePointer. |
| 2119 | const auto result_type = _.FindDef(inst->type_id()); |
| 2120 | if (spv::Op::OpTypePointer != result_type->opcode()) { |
| 2121 | return _.diag(SPV_ERROR_INVALID_DATA, inst) |
| 2122 | << "The Result Type of Op" << spvOpcodeString(opcode) << " <id> " |
| 2123 | << _.getIdName(inst->id()) << " must be OpTypePointer. Found Op" |
| 2124 | << spvOpcodeString(result_type->opcode()) << '.'; |
| 2125 | } |
| 2126 | |
| 2127 | // The pointed storage class must be valid. |
| 2128 | const auto storage_class = result_type->GetOperandAs<spv::StorageClass>(1); |
| 2129 | if (storage_class != spv::StorageClass::StorageBuffer && |
| 2130 | storage_class != spv::StorageClass::PhysicalStorageBuffer && |
| 2131 | storage_class != spv::StorageClass::Uniform) { |
| 2132 | return _.diag(SPV_ERROR_INVALID_DATA, inst) |
| 2133 | << "The Result Type of Op" << spvOpcodeString(opcode) << " <id> " |
| 2134 | << _.getIdName(inst->id()) |
| 2135 | << " must point to a storage class of " |
| 2136 | "StorageBuffer, PhysicalStorageBuffer, or Uniform."; |
| 2137 | } |
| 2138 | |
| 2139 | // The pointed type must not be one in the list below. |
| 2140 | const auto result_type_pointee = |
| 2141 | _.FindDef(result_type->GetOperandAs<uint32_t>(2)); |
| 2142 | if (result_type_pointee->opcode() == spv::Op::OpTypeArray || |
| 2143 | result_type_pointee->opcode() == spv::Op::OpTypeMatrix || |
| 2144 | result_type_pointee->opcode() == spv::Op::OpTypeStruct) { |
| 2145 | return _.diag(SPV_ERROR_INVALID_DATA, inst) |
| 2146 | << "The Result Type of Op" << spvOpcodeString(opcode) << " <id> " |
| 2147 | << _.getIdName(inst->id()) |
| 2148 | << " must not point to " |
| 2149 | "OpTypeArray, OpTypeMatrix, or OpTypeStruct."; |
| 2150 | } |
| 2151 | |
| 2152 | // Validate Stride is a OpConstant. |
| 2153 | const auto stride = _.FindDef(inst->GetOperandAs<uint32_t>(3)); |
| 2154 | if (stride->opcode() != spv::Op::OpConstant) { |
| 2155 | return _.diag(SPV_ERROR_INVALID_DATA, inst) |
| 2156 | << "The Stride of Op" << spvOpcodeString(opcode) << " <id> " |
| 2157 | << _.getIdName(inst->id()) << " must be OpConstant. Found Op" |
| 2158 | << spvOpcodeString(stride->opcode()) << '.'; |
| 2159 | } |
| 2160 | // Stride type must be OpTypeInt |
| 2161 | const auto stride_type = _.FindDef(stride->type_id()); |
| 2162 | if (stride_type->opcode() != spv::Op::OpTypeInt) { |
| 2163 | return _.diag(SPV_ERROR_INVALID_DATA, inst) |
| 2164 | << "The type of Stride of Op" << spvOpcodeString(opcode) << " <id> " |
| 2165 | << _.getIdName(inst->id()) << " must be OpTypeInt. Found Op" |
| 2166 | << spvOpcodeString(stride_type->opcode()) << '.'; |
| 2167 | } |
| 2168 | |
| 2169 | // Index and Offset type must be OpTypeInt with a width of 32 |
| 2170 | const auto ValidateType = [&](const char* name, |
| 2171 | int operandIndex) -> spv_result_t { |
| 2172 | const auto value = _.FindDef(inst->GetOperandAs<uint32_t>(operandIndex)); |
no test coverage detected