| 344 | } |
| 345 | |
| 346 | spv_result_t ValidateDecorateId(ValidationState_t& _, const Instruction* inst) { |
| 347 | const auto target_id = inst->GetOperandAs<uint32_t>(0); |
| 348 | const auto target = _.FindDef(target_id); |
| 349 | if (target && spv::Op::OpDecorationGroup == target->opcode()) { |
| 350 | return _.diag(SPV_ERROR_INVALID_ID, inst) |
| 351 | << "OpMemberDecorate Target <id> " << _.getIdName(target_id) |
| 352 | << " must not be an OpDecorationGroup instruction."; |
| 353 | } |
| 354 | |
| 355 | const auto decoration = inst->GetOperandAs<spv::Decoration>(1); |
| 356 | if (!DecorationTakesIdParameters(decoration)) { |
| 357 | return _.diag(SPV_ERROR_INVALID_ID, inst) |
| 358 | << "Decorations that don't take ID parameters may not be used with " |
| 359 | "OpDecorateId"; |
| 360 | } |
| 361 | |
| 362 | if (decoration == spv::Decoration::ArrayStrideIdEXT) { |
| 363 | if (target->opcode() != spv::Op::OpTypeArray && |
| 364 | target->opcode() != spv::Op::OpTypeRuntimeArray) { |
| 365 | // ArrayStrideIdEXT is suppose to identical to ArrayStride, which would |
| 366 | // allow it to be a OpTypePointer/OpTypeUntypedPointerKHR |
| 367 | return _.diag(SPV_ERROR_INVALID_ID, inst) |
| 368 | << "ArrayStrideIdEXT decoration must only be applied to array " |
| 369 | "types."; |
| 370 | } else { |
| 371 | const uint32_t operand_id = inst->GetOperandAs<uint32_t>(2); |
| 372 | if (!_.IsIntScalarType(_.GetTypeId(operand_id), 32)) { |
| 373 | return _.diag(SPV_ERROR_INVALID_ID, inst) |
| 374 | << "ArrayStrideIdEXT extra operand must be a 32-bit int " |
| 375 | "scalar type."; |
| 376 | } |
| 377 | |
| 378 | // Even if spec constant, validation layers will test when frozen |
| 379 | uint64_t stride_value = 0; |
| 380 | if (_.EvalConstantValUint64(operand_id, &stride_value)) { |
| 381 | if (stride_value == 0) { |
| 382 | return _.diag(SPV_ERROR_INVALID_ID, inst) |
| 383 | << "ArrayStrideIdEXT contains a stride of zero."; |
| 384 | } |
| 385 | } |
| 386 | |
| 387 | // Strip array and should be the descriptor type |
| 388 | const uint32_t element_type = |
| 389 | _.FindDef(target_id)->GetOperandAs<uint32_t>(1); |
| 390 | if (!_.IsDescriptorType(element_type)) { |
| 391 | return _.diag(SPV_ERROR_INVALID_ID, inst) |
| 392 | << "ArrayStrideIdEXT decoration must only be applied to" |
| 393 | << " array type containing a Descriptor type."; |
| 394 | } |
| 395 | } |
| 396 | } |
| 397 | |
| 398 | for (uint32_t i = 2; i < inst->operands().size(); ++i) { |
| 399 | const auto param_id = inst->GetOperandAs<uint32_t>(i); |
| 400 | const auto param = _.FindDef(param_id); |
| 401 | |
| 402 | // Both target and param are elements of ordered_instructions we can |
| 403 | // determine their relative positions in the SPIR-V module by comparing |
no test coverage detected