| 2313 | } |
| 2314 | |
| 2315 | spv_result_t ValidateArrayLength(ValidationState_t& state, |
| 2316 | const Instruction* inst) { |
| 2317 | const spv::Op opcode = inst->opcode(); |
| 2318 | |
| 2319 | // Result type must be a 32- or 64-bit unsigned int. |
| 2320 | // 64-bit requires CapabilityShader64BitIndexingEXT or a pipeline/shader |
| 2321 | // flag and is validated in VVL. |
| 2322 | const uint32_t result_type_id = inst->type_id(); |
| 2323 | if (!state.IsIntScalarTypeWithSignedness(result_type_id, 0)) { |
| 2324 | return state.diag(SPV_ERROR_INVALID_ID, inst) |
| 2325 | << "The Result Type of Op" << spvOpcodeString(opcode) << " <id> " |
| 2326 | << state.getIdName(inst->id()) |
| 2327 | << " must be OpTypeInt with width 32 or 64 and signedness 0."; |
| 2328 | } |
| 2329 | const uint32_t result_type_width = state.GetBitWidth(inst->type_id()); |
| 2330 | if (result_type_width != 32 && result_type_width != 64) { |
| 2331 | return state.diag(SPV_ERROR_INVALID_ID, inst) |
| 2332 | << "The Result Type of Op" << spvOpcodeString(opcode) << " <id> " |
| 2333 | << state.getIdName(inst->id()) |
| 2334 | << " must be OpTypeInt with width 32 or 64 and signedness 0."; |
| 2335 | } |
| 2336 | |
| 2337 | const bool untyped = inst->opcode() == spv::Op::OpUntypedArrayLengthKHR; |
| 2338 | auto pointer_ty_id = state.GetOperandTypeId(inst, (untyped ? 3 : 2)); |
| 2339 | auto pointer_ty = state.FindDef(pointer_ty_id); |
| 2340 | if (untyped) { |
| 2341 | if (!pointer_ty || |
| 2342 | pointer_ty->opcode() != spv::Op::OpTypeUntypedPointerKHR) { |
| 2343 | return state.diag(SPV_ERROR_INVALID_ID, inst) |
| 2344 | << "Pointer must be an untyped pointer object"; |
| 2345 | } |
| 2346 | } else if (pointer_ty->opcode() != spv::Op::OpTypePointer) { |
| 2347 | return state.diag(SPV_ERROR_INVALID_ID, inst) |
| 2348 | << "The Structure's type in Op" << spvOpcodeString(opcode) |
| 2349 | << " <id> " << state.getIdName(inst->id()) |
| 2350 | << " must be a pointer to an OpTypeStruct."; |
| 2351 | } |
| 2352 | |
| 2353 | Instruction* structure_type = nullptr; |
| 2354 | if (untyped) { |
| 2355 | structure_type = state.FindDef(inst->GetOperandAs<uint32_t>(2)); |
| 2356 | } else { |
| 2357 | structure_type = state.FindDef(pointer_ty->GetOperandAs<uint32_t>(2)); |
| 2358 | } |
| 2359 | |
| 2360 | if (structure_type->opcode() != spv::Op::OpTypeStruct) { |
| 2361 | return state.diag(SPV_ERROR_INVALID_ID, inst) |
| 2362 | << "The Structure's type in Op" << spvOpcodeString(opcode) |
| 2363 | << " <id> " << state.getIdName(inst->id()) |
| 2364 | << " must be a pointer to an OpTypeStruct."; |
| 2365 | } |
| 2366 | |
| 2367 | auto num_of_members = structure_type->operands().size() - 1; |
| 2368 | auto last_member = |
| 2369 | state.FindDef(structure_type->GetOperandAs<uint32_t>(num_of_members)); |
| 2370 | if (last_member->opcode() != spv::Op::OpTypeRuntimeArray) { |
| 2371 | return state.diag(SPV_ERROR_INVALID_ID, inst) |
| 2372 | << "The Structure's last member in Op" << spvOpcodeString(opcode) |
no test coverage detected