(
&self,
block: Block,
inst: Inst,
errors: &mut VerifierErrors,
)
| 445 | } |
| 446 | |
| 447 | fn block_integrity( |
| 448 | &self, |
| 449 | block: Block, |
| 450 | inst: Inst, |
| 451 | errors: &mut VerifierErrors, |
| 452 | ) -> VerifierStepResult { |
| 453 | let is_terminator = self.func.dfg.insts[inst].opcode().is_terminator(); |
| 454 | let is_last_inst = self.func.layout.last_inst(block) == Some(inst); |
| 455 | |
| 456 | if is_terminator && !is_last_inst { |
| 457 | // Terminating instructions only occur at the end of blocks. |
| 458 | return errors.fatal(( |
| 459 | inst, |
| 460 | self.context(inst), |
| 461 | format!("a terminator instruction was encountered before the end of {block}"), |
| 462 | )); |
| 463 | } |
| 464 | if is_last_inst && !is_terminator { |
| 465 | return errors.fatal((block, "block does not end in a terminator instruction")); |
| 466 | } |
| 467 | |
| 468 | // Instructions belong to the correct block. |
| 469 | let inst_block = self.func.layout.inst_block(inst); |
| 470 | if inst_block != Some(block) { |
| 471 | return errors.fatal(( |
| 472 | inst, |
| 473 | self.context(inst), |
| 474 | format!("should belong to {block} not {inst_block:?}"), |
| 475 | )); |
| 476 | } |
| 477 | |
| 478 | // Parameters belong to the correct block. |
| 479 | for &arg in self.func.dfg.block_params(block) { |
| 480 | match self.func.dfg.value_def(arg) { |
| 481 | ValueDef::Param(arg_block, _) => { |
| 482 | if block != arg_block { |
| 483 | return errors.fatal((arg, format!("does not belong to {block}"))); |
| 484 | } |
| 485 | } |
| 486 | _ => { |
| 487 | return errors.fatal((arg, "expected an argument, found a result")); |
| 488 | } |
| 489 | } |
| 490 | } |
| 491 | |
| 492 | Ok(()) |
| 493 | } |
| 494 | |
| 495 | fn instruction_integrity(&self, inst: Inst, errors: &mut VerifierErrors) -> VerifierStepResult { |
| 496 | let inst_data = &self.func.dfg.insts[inst]; |
no test coverage detected