| 151 | } |
| 152 | |
| 153 | spv_result_t ValidateBranchConditional(ValidationState_t& _, |
| 154 | const Instruction* inst) { |
| 155 | // num_operands is either 3 or 5 --- if 5, the last two need to be literal |
| 156 | // integers |
| 157 | const auto num_operands = inst->operands().size(); |
| 158 | if (num_operands != 3 && num_operands != 5) { |
| 159 | return _.diag(SPV_ERROR_INVALID_ID, inst) |
| 160 | << "OpBranchConditional requires either 3 or 5 parameters"; |
| 161 | } |
| 162 | |
| 163 | // grab the condition operand and check that it is a bool |
| 164 | const auto cond_id = inst->GetOperandAs<uint32_t>(0); |
| 165 | const auto cond_op = _.FindDef(cond_id); |
| 166 | if (!cond_op || !cond_op->type_id() || |
| 167 | !_.IsBoolScalarType(cond_op->type_id())) { |
| 168 | return _.diag(SPV_ERROR_INVALID_ID, inst) << "Condition operand for " |
| 169 | "OpBranchConditional must be " |
| 170 | "of boolean type"; |
| 171 | } |
| 172 | |
| 173 | // target operands must be OpLabel |
| 174 | // note that we don't need to check that the target labels are in the same |
| 175 | // function, |
| 176 | // PerformCfgChecks already checks for that |
| 177 | const auto true_id = inst->GetOperandAs<uint32_t>(1); |
| 178 | const auto true_target = _.FindDef(true_id); |
| 179 | if (!true_target || spv::Op::OpLabel != true_target->opcode()) { |
| 180 | return _.diag(SPV_ERROR_INVALID_ID, inst) |
| 181 | << "The 'True Label' operand for OpBranchConditional must be the " |
| 182 | "ID of an OpLabel instruction"; |
| 183 | } |
| 184 | |
| 185 | const auto false_id = inst->GetOperandAs<uint32_t>(2); |
| 186 | const auto false_target = _.FindDef(false_id); |
| 187 | if (!false_target || spv::Op::OpLabel != false_target->opcode()) { |
| 188 | return _.diag(SPV_ERROR_INVALID_ID, inst) |
| 189 | << "The 'False Label' operand for OpBranchConditional must be the " |
| 190 | "ID of an OpLabel instruction"; |
| 191 | } |
| 192 | |
| 193 | // A similar requirement for SPV_KHR_maximal_reconvergence is deferred until |
| 194 | // entry point call trees have been reconrded. |
| 195 | if (_.version() >= SPV_SPIRV_VERSION_WORD(1, 6) && true_id == false_id) { |
| 196 | return _.diag(SPV_ERROR_INVALID_ID, inst) |
| 197 | << "In SPIR-V 1.6 or later, True Label and False Label must be " |
| 198 | "different labels"; |
| 199 | } |
| 200 | |
| 201 | return SPV_SUCCESS; |
| 202 | } |
| 203 | |
| 204 | spv_result_t ValidateSwitch(ValidationState_t& _, const Instruction* inst) { |
| 205 | const auto num_operands = inst->operands().size(); |
no test coverage detected