| 3392 | } |
| 3393 | |
| 3394 | spv_result_t ValidatePtrComparison(ValidationState_t& _, |
| 3395 | const Instruction* inst) { |
| 3396 | const auto op1 = _.FindDef(inst->GetOperandAs<uint32_t>(2u)); |
| 3397 | const auto op2 = _.FindDef(inst->GetOperandAs<uint32_t>(3u)); |
| 3398 | const auto op1_type = _.FindDef(op1->type_id()); |
| 3399 | const auto op2_type = _.FindDef(op2->type_id()); |
| 3400 | spv::StorageClass sc = op1_type->GetOperandAs<spv::StorageClass>(1u); |
| 3401 | if ((_.addressing_model() == spv::AddressingModel::Logical || |
| 3402 | _.addressing_model() == spv::AddressingModel::PhysicalStorageBuffer64) && |
| 3403 | sc != spv::StorageClass::PhysicalStorageBuffer && |
| 3404 | !_.features().variable_pointers) { |
| 3405 | return _.diag(SPV_ERROR_INVALID_ID, inst) |
| 3406 | << "Instruction on logical pointers cannot be used without " |
| 3407 | "a variable pointers capability"; |
| 3408 | } |
| 3409 | |
| 3410 | const auto result_type = _.FindDef(inst->type_id()); |
| 3411 | if (inst->opcode() == spv::Op::OpPtrDiff) { |
| 3412 | if (!result_type || result_type->opcode() != spv::Op::OpTypeInt) { |
| 3413 | return _.diag(SPV_ERROR_INVALID_ID, inst) |
| 3414 | << "Result Type must be an integer scalar"; |
| 3415 | } |
| 3416 | } else { |
| 3417 | if (!result_type || result_type->opcode() != spv::Op::OpTypeBool) { |
| 3418 | return _.diag(SPV_ERROR_INVALID_ID, inst) |
| 3419 | << "Result Type must be OpTypeBool"; |
| 3420 | } |
| 3421 | } |
| 3422 | |
| 3423 | if (!op1_type || (op1_type->opcode() != spv::Op::OpTypePointer && |
| 3424 | op1_type->opcode() != spv::Op::OpTypeUntypedPointerKHR)) { |
| 3425 | return _.diag(SPV_ERROR_INVALID_ID, inst) |
| 3426 | << "Operand type must be a pointer"; |
| 3427 | } |
| 3428 | |
| 3429 | if (!op2_type || (op2_type->opcode() != spv::Op::OpTypePointer && |
| 3430 | op2_type->opcode() != spv::Op::OpTypeUntypedPointerKHR)) { |
| 3431 | return _.diag(SPV_ERROR_INVALID_ID, inst) |
| 3432 | << "Operand type must be a pointer"; |
| 3433 | } |
| 3434 | |
| 3435 | if (inst->opcode() == spv::Op::OpPtrDiff) { |
| 3436 | if (op1->type_id() != op2->type_id()) { |
| 3437 | return _.diag(SPV_ERROR_INVALID_ID, inst) |
| 3438 | << "The types of Operand 1 and Operand 2 must match"; |
| 3439 | } |
| 3440 | } else { |
| 3441 | const auto either_untyped = |
| 3442 | op1_type->opcode() == spv::Op::OpTypeUntypedPointerKHR || |
| 3443 | op2_type->opcode() == spv::Op::OpTypeUntypedPointerKHR; |
| 3444 | if (either_untyped) { |
| 3445 | const auto sc1 = op1_type->GetOperandAs<spv::StorageClass>(1); |
| 3446 | const auto sc2 = op2_type->GetOperandAs<spv::StorageClass>(1); |
| 3447 | if (sc1 != sc2) { |
| 3448 | return _.diag(SPV_ERROR_INVALID_ID, inst) |
| 3449 | << "Pointer storage classes must match"; |
| 3450 | } |
| 3451 | } else if (op1->type_id() != op2->type_id()) { |
no test coverage detected