1use self::flags::verify_flags;
60use crate::dbg::DisplayList;
61use crate::dominator_tree::DominatorTree;
62use crate::entity::SparseSet;
63use crate::flowgraph::{BasicBlock, ControlFlowGraph};
64use crate::ir;
65use crate::ir::entities::AnyEntity;
66use crate::ir::instructions::{BranchInfo, CallInfo, InstructionFormat, ResolvedConstraint};
67use crate::ir::{
68 types, ArgumentLoc, Ebb, FuncRef, Function, GlobalValue, Inst, InstructionData, JumpTable,
69 Opcode, SigRef, StackSlot, StackSlotKind, Type, Value, ValueDef, ValueList, ValueLoc,
70};
71use crate::isa::TargetIsa;
72use crate::iterators::IteratorExtras;
73use crate::print_errors::pretty_verifier_error;
74use crate::settings::FlagsOrIsa;
75use crate::timing;
76use alloc::collections::BTreeSet;
77use alloc::string::{String, ToString};
78use alloc::vec::Vec;
79use core::cmp::Ordering;
80use core::fmt::{self, Display, Formatter, Write};
81use log::debug;
82use thiserror::Error;
83
84pub use self::cssa::verify_cssa;
85pub use self::liveness::verify_liveness;
86pub use self::locations::verify_locations;
87
88mod cssa;
89mod flags;
90mod liveness;
91mod locations;
92
93#[derive(Error, Debug, PartialEq, Eq, Clone)]
95#[error("{}{}: {}", .location, format_context(.context), .message)]
96pub struct VerifierError {
97 pub location: AnyEntity,
99 pub context: Option<String>,
102 pub message: String,
104}
105
106fn format_context(context: &Option<String>) -> String {
108 match context {
109 None => "".to_string(),
110 Some(c) => format!(" ({})", c),
111 }
112}
113
114impl<L, C, M> From<(L, C, M)> for VerifierError
125where
126 L: Into<AnyEntity>,
127 C: Into<String>,
128 M: Into<String>,
129{
130 fn from(items: (L, C, M)) -> Self {
131 let (location, context, message) = items;
132 Self {
133 location: location.into(),
134 context: Some(context.into()),
135 message: message.into(),
136 }
137 }
138}
139
140impl<L, M> From<(L, M)> for VerifierError
144where
145 L: Into<AnyEntity>,
146 M: Into<String>,
147{
148 fn from(items: (L, M)) -> Self {
149 let (location, message) = items;
150 Self {
151 location: location.into(),
152 context: None,
153 message: message.into(),
154 }
155 }
156}
157
158pub type VerifierStepResult<T> = Result<T, ()>;
169
170pub type VerifierResult<T> = Result<T, VerifierErrors>;
175
176#[derive(Error, Debug, Default, PartialEq, Eq, Clone)]
178pub struct VerifierErrors(pub Vec<VerifierError>);
179
180impl VerifierErrors {
181 #[inline]
183 pub fn new() -> Self {
184 Self(Vec::new())
185 }
186
187 #[inline]
189 pub fn is_empty(&self) -> bool {
190 self.0.is_empty()
191 }
192
193 #[inline]
195 pub fn has_error(&self) -> bool {
196 !self.0.is_empty()
197 }
198
199 #[inline]
202 pub fn as_result(&self) -> VerifierStepResult<()> {
203 if self.is_empty() {
204 Ok(())
205 } else {
206 Err(())
207 }
208 }
209
210 pub fn report(&mut self, error: impl Into<VerifierError>) {
212 self.0.push(error.into());
213 }
214
215 pub fn fatal(&mut self, error: impl Into<VerifierError>) -> VerifierStepResult<()> {
217 self.report(error);
218 Err(())
219 }
220
221 pub fn nonfatal(&mut self, error: impl Into<VerifierError>) -> VerifierStepResult<()> {
223 self.report(error);
224 Ok(())
225 }
226}
227
228impl From<Vec<VerifierError>> for VerifierErrors {
229 fn from(v: Vec<VerifierError>) -> Self {
230 Self(v)
231 }
232}
233
234impl Into<Vec<VerifierError>> for VerifierErrors {
235 fn into(self) -> Vec<VerifierError> {
236 self.0
237 }
238}
239
240impl Into<VerifierResult<()>> for VerifierErrors {
241 fn into(self) -> VerifierResult<()> {
242 if self.is_empty() {
243 Ok(())
244 } else {
245 Err(self)
246 }
247 }
248}
249
250impl Display for VerifierErrors {
251 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
252 for err in &self.0 {
253 writeln!(f, "- {}", err)?;
254 }
255 Ok(())
256 }
257}
258
259pub fn verify_function<'a, FOI: Into<FlagsOrIsa<'a>>>(
261 func: &Function,
262 fisa: FOI,
263) -> VerifierResult<()> {
264 let _tt = timing::verifier();
265 let mut errors = VerifierErrors::default();
266 let verifier = Verifier::new(func, fisa.into());
267 let result = verifier.run(&mut errors);
268 if errors.is_empty() {
269 result.unwrap();
270 Ok(())
271 } else {
272 Err(errors)
273 }
274}
275
276pub fn verify_context<'a, FOI: Into<FlagsOrIsa<'a>>>(
279 func: &Function,
280 cfg: &ControlFlowGraph,
281 domtree: &DominatorTree,
282 fisa: FOI,
283 errors: &mut VerifierErrors,
284) -> VerifierStepResult<()> {
285 let _tt = timing::verifier();
286 let verifier = Verifier::new(func, fisa.into());
287 if cfg.is_valid() {
288 verifier.cfg_integrity(cfg, errors)?;
289 }
290 if domtree.is_valid() {
291 verifier.domtree_integrity(domtree, errors)?;
292 }
293 verifier.run(errors)
294}
295
296struct Verifier<'a> {
297 func: &'a Function,
298 expected_cfg: ControlFlowGraph,
299 expected_domtree: DominatorTree,
300 isa: Option<&'a dyn TargetIsa>,
301}
302
303impl<'a> Verifier<'a> {
304 pub fn new(func: &'a Function, fisa: FlagsOrIsa<'a>) -> Self {
305 let expected_cfg = ControlFlowGraph::with_function(func);
306 let expected_domtree = DominatorTree::with_function(func, &expected_cfg);
307 Self {
308 func,
309 expected_cfg,
310 expected_domtree,
311 isa: fisa.isa,
312 }
313 }
314
315 #[inline]
317 fn context(&self, inst: Inst) -> String {
318 self.func.dfg.display_inst(inst, self.isa).to_string()
319 }
320
321 fn verify_global_values(&self, errors: &mut VerifierErrors) -> VerifierStepResult<()> {
325 let mut cycle_seen = false;
326 let mut seen = SparseSet::new();
327
328 'gvs: for gv in self.func.global_values.keys() {
329 seen.clear();
330 seen.insert(gv);
331
332 let mut cur = gv;
333 loop {
334 match self.func.global_values[cur] {
335 ir::GlobalValueData::Load { base, .. }
336 | ir::GlobalValueData::IAddImm { base, .. } => {
337 if seen.insert(base).is_some() {
338 if !cycle_seen {
339 errors.report((
340 gv,
341 format!("global value cycle: {}", DisplayList(seen.as_slice())),
342 ));
343 cycle_seen = true;
345 }
346 continue 'gvs;
347 }
348
349 cur = base;
350 }
351 _ => break,
352 }
353 }
354
355 match self.func.global_values[gv] {
356 ir::GlobalValueData::VMContext { .. } => {
357 if self
358 .func
359 .special_param(ir::ArgumentPurpose::VMContext)
360 .is_none()
361 {
362 errors.report((gv, format!("undeclared vmctx reference {}", gv)));
363 }
364 }
365 ir::GlobalValueData::IAddImm {
366 base, global_type, ..
367 } => {
368 if !global_type.is_int() {
369 errors.report((
370 gv,
371 format!("iadd_imm global value with non-int type {}", global_type),
372 ));
373 } else if let Some(isa) = self.isa {
374 let base_type = self.func.global_values[base].global_type(isa);
375 if global_type != base_type {
376 errors.report((
377 gv,
378 format!(
379 "iadd_imm type {} differs from operand type {}",
380 global_type, base_type
381 ),
382 ));
383 }
384 }
385 }
386 ir::GlobalValueData::Load { base, .. } => {
387 if let Some(isa) = self.isa {
388 let base_type = self.func.global_values[base].global_type(isa);
389 let pointer_type = isa.pointer_type();
390 if base_type != pointer_type {
391 errors.report((
392 gv,
393 format!(
394 "base {} has type {}, which is not the pointer type {}",
395 base, base_type, pointer_type
396 ),
397 ));
398 }
399 }
400 }
401 _ => {}
402 }
403 }
404
405 Ok(())
407 }
408
409 fn verify_heaps(&self, errors: &mut VerifierErrors) -> VerifierStepResult<()> {
410 if let Some(isa) = self.isa {
411 for (heap, heap_data) in &self.func.heaps {
412 let base = heap_data.base;
413 if !self.func.global_values.is_valid(base) {
414 return errors.nonfatal((heap, format!("invalid base global value {}", base)));
415 }
416
417 let pointer_type = isa.pointer_type();
418 let base_type = self.func.global_values[base].global_type(isa);
419 if base_type != pointer_type {
420 errors.report((
421 heap,
422 format!(
423 "heap base has type {}, which is not the pointer type {}",
424 base_type, pointer_type
425 ),
426 ));
427 }
428
429 if let ir::HeapStyle::Dynamic { bound_gv, .. } = heap_data.style {
430 if !self.func.global_values.is_valid(bound_gv) {
431 return errors
432 .nonfatal((heap, format!("invalid bound global value {}", bound_gv)));
433 }
434
435 let index_type = heap_data.index_type;
436 let bound_type = self.func.global_values[bound_gv].global_type(isa);
437 if index_type != bound_type {
438 errors.report((
439 heap,
440 format!(
441 "heap index type {} differs from the type of its bound, {}",
442 index_type, bound_type
443 ),
444 ));
445 }
446 }
447 }
448 }
449
450 Ok(())
451 }
452
453 fn verify_tables(&self, errors: &mut VerifierErrors) -> VerifierStepResult<()> {
454 if let Some(isa) = self.isa {
455 for (table, table_data) in &self.func.tables {
456 let base = table_data.base_gv;
457 if !self.func.global_values.is_valid(base) {
458 return errors.nonfatal((table, format!("invalid base global value {}", base)));
459 }
460
461 let pointer_type = isa.pointer_type();
462 let base_type = self.func.global_values[base].global_type(isa);
463 if base_type != pointer_type {
464 errors.report((
465 table,
466 format!(
467 "table base has type {}, which is not the pointer type {}",
468 base_type, pointer_type
469 ),
470 ));
471 }
472
473 let bound_gv = table_data.bound_gv;
474 if !self.func.global_values.is_valid(bound_gv) {
475 return errors
476 .nonfatal((table, format!("invalid bound global value {}", bound_gv)));
477 }
478
479 let index_type = table_data.index_type;
480 let bound_type = self.func.global_values[bound_gv].global_type(isa);
481 if index_type != bound_type {
482 errors.report((
483 table,
484 format!(
485 "table index type {} differs from the type of its bound, {}",
486 index_type, bound_type
487 ),
488 ));
489 }
490 }
491 }
492
493 Ok(())
494 }
495
496 fn verify_jump_tables(&self, errors: &mut VerifierErrors) -> VerifierStepResult<()> {
497 for (jt, jt_data) in &self.func.jump_tables {
498 for &ebb in jt_data.iter() {
499 self.verify_ebb(jt, ebb, errors)?;
500 }
501 }
502 Ok(())
503 }
504
505 #[cfg(feature = "basic-blocks")]
508 fn encodable_as_bb(&self, ebb: Ebb, errors: &mut VerifierErrors) -> VerifierStepResult<()> {
509 match self.func.is_ebb_basic(ebb) {
510 Ok(()) => Ok(()),
511 Err((inst, message)) => errors.fatal((inst, self.context(inst), message)),
512 }
513 }
514
515 fn ebb_integrity(
516 &self,
517 ebb: Ebb,
518 inst: Inst,
519 errors: &mut VerifierErrors,
520 ) -> VerifierStepResult<()> {
521 let is_terminator = self.func.dfg[inst].opcode().is_terminator();
522 let is_last_inst = self.func.layout.last_inst(ebb) == Some(inst);
523
524 if is_terminator && !is_last_inst {
525 return errors.fatal((
527 inst,
528 self.context(inst),
529 format!(
530 "a terminator instruction was encountered before the end of {}",
531 ebb
532 ),
533 ));
534 }
535 if is_last_inst && !is_terminator {
536 return errors.fatal((ebb, "block does not end in a terminator instruction"));
537 }
538
539 let inst_ebb = self.func.layout.inst_ebb(inst);
541 if inst_ebb != Some(ebb) {
542 return errors.fatal((
543 inst,
544 self.context(inst),
545 format!("should belong to {} not {:?}", ebb, inst_ebb),
546 ));
547 }
548
549 for &arg in self.func.dfg.ebb_params(ebb) {
551 match self.func.dfg.value_def(arg) {
552 ValueDef::Param(arg_ebb, _) => {
553 if ebb != arg_ebb {
554 return errors.fatal((arg, format!("does not belong to {}", ebb)));
555 }
556 }
557 _ => {
558 return errors.fatal((arg, "expected an argument, found a result"));
559 }
560 }
561 }
562
563 Ok(())
564 }
565
566 fn instruction_integrity(
567 &self,
568 inst: Inst,
569 errors: &mut VerifierErrors,
570 ) -> VerifierStepResult<()> {
571 let inst_data = &self.func.dfg[inst];
572 let dfg = &self.func.dfg;
573
574 if inst_data.opcode().format() != InstructionFormat::from(inst_data) {
576 return errors.fatal((
577 inst,
578 self.context(inst),
579 "instruction opcode doesn't match instruction format",
580 ));
581 }
582
583 let num_fixed_results = inst_data.opcode().constraints().num_fixed_results();
584 let var_results = dfg
586 .call_signature(inst)
587 .map_or(0, |sig| dfg.signatures[sig].returns.len());
588 let total_results = num_fixed_results + var_results;
589
590 let got_results = dfg.inst_results(inst).len();
592 if got_results != total_results {
593 return errors.fatal((
594 inst,
595 self.context(inst),
596 format!(
597 "expected {} result values, found {}",
598 total_results, got_results,
599 ),
600 ));
601 }
602
603 self.verify_entity_references(inst, errors)
604 }
605
606 fn verify_entity_references(
607 &self,
608 inst: Inst,
609 errors: &mut VerifierErrors,
610 ) -> VerifierStepResult<()> {
611 use crate::ir::instructions::InstructionData::*;
612
613 for &arg in self.func.dfg.inst_args(inst) {
614 self.verify_inst_arg(inst, arg, errors)?;
615
616 let original = self.func.dfg.resolve_aliases(arg);
618 if !self.func.dfg.value_is_attached(original) {
619 errors.report((
620 inst,
621 self.context(inst),
622 format!("argument {} -> {} is not attached", arg, original),
623 ));
624 }
625 }
626
627 for &res in self.func.dfg.inst_results(inst) {
628 self.verify_inst_result(inst, res, errors)?;
629 }
630
631 match self.func.dfg[inst] {
632 MultiAry { ref args, .. } => {
633 self.verify_value_list(inst, args, errors)?;
634 }
635 Jump {
636 destination,
637 ref args,
638 ..
639 }
640 | Branch {
641 destination,
642 ref args,
643 ..
644 }
645 | BranchInt {
646 destination,
647 ref args,
648 ..
649 }
650 | BranchFloat {
651 destination,
652 ref args,
653 ..
654 }
655 | BranchIcmp {
656 destination,
657 ref args,
658 ..
659 } => {
660 self.verify_ebb(inst, destination, errors)?;
661 self.verify_value_list(inst, args, errors)?;
662 }
663 BranchTable {
664 table, destination, ..
665 } => {
666 self.verify_ebb(inst, destination, errors)?;
667 self.verify_jump_table(inst, table, errors)?;
668 }
669 BranchTableBase { table, .. }
670 | BranchTableEntry { table, .. }
671 | IndirectJump { table, .. } => {
672 self.verify_jump_table(inst, table, errors)?;
673 }
674 Call {
675 func_ref, ref args, ..
676 } => {
677 self.verify_func_ref(inst, func_ref, errors)?;
678 self.verify_value_list(inst, args, errors)?;
679 }
680 CallIndirect {
681 sig_ref, ref args, ..
682 } => {
683 self.verify_sig_ref(inst, sig_ref, errors)?;
684 self.verify_value_list(inst, args, errors)?;
685 }
686 FuncAddr { func_ref, .. } => {
687 self.verify_func_ref(inst, func_ref, errors)?;
688 }
689 StackLoad { stack_slot, .. } | StackStore { stack_slot, .. } => {
690 self.verify_stack_slot(inst, stack_slot, errors)?;
691 }
692 UnaryGlobalValue { global_value, .. } => {
693 self.verify_global_value(inst, global_value, errors)?;
694 }
695 HeapAddr { heap, .. } => {
696 self.verify_heap(inst, heap, errors)?;
697 }
698 TableAddr { table, .. } => {
699 self.verify_table(inst, table, errors)?;
700 }
701 RegSpill { dst, .. } => {
702 self.verify_stack_slot(inst, dst, errors)?;
703 }
704 RegFill { src, .. } => {
705 self.verify_stack_slot(inst, src, errors)?;
706 }
707 LoadComplex { ref args, .. } => {
708 self.verify_value_list(inst, args, errors)?;
709 }
710 StoreComplex { ref args, .. } => {
711 self.verify_value_list(inst, args, errors)?;
712 }
713
714 NullAry {
715 opcode: Opcode::GetPinnedReg,
716 }
717 | Unary {
718 opcode: Opcode::SetPinnedReg,
719 ..
720 } => {
721 if let Some(isa) = &self.isa {
722 if !isa.flags().enable_pinned_reg() {
723 return errors.fatal((
724 inst,
725 self.context(inst),
726 "GetPinnedReg/SetPinnedReg cannot be used without enable_pinned_reg",
727 ));
728 }
729 } else {
730 return errors.fatal((
731 inst,
732 self.context(inst),
733 "GetPinnedReg/SetPinnedReg need an ISA!",
734 ));
735 }
736 }
737
738 Unary {
739 opcode: Opcode::Bitcast,
740 arg,
741 } => {
742 self.verify_bitcast(inst, arg, errors)?;
743 }
744
745 Unary { .. }
747 | UnaryImm { .. }
748 | UnaryIeee32 { .. }
749 | UnaryIeee64 { .. }
750 | UnaryBool { .. }
751 | Binary { .. }
752 | BinaryImm { .. }
753 | Ternary { .. }
754 | InsertLane { .. }
755 | ExtractLane { .. }
756 | UnaryConst { .. }
757 | Shuffle { .. }
758 | IntCompare { .. }
759 | IntCompareImm { .. }
760 | IntCond { .. }
761 | FloatCompare { .. }
762 | FloatCond { .. }
763 | IntSelect { .. }
764 | Load { .. }
765 | Store { .. }
766 | RegMove { .. }
767 | CopySpecial { .. }
768 | CopyToSsa { .. }
769 | Trap { .. }
770 | CondTrap { .. }
771 | IntCondTrap { .. }
772 | FloatCondTrap { .. }
773 | NullAry { .. } => {}
774 }
775
776 Ok(())
777 }
778
779 fn verify_ebb(
780 &self,
781 loc: impl Into<AnyEntity>,
782 e: Ebb,
783 errors: &mut VerifierErrors,
784 ) -> VerifierStepResult<()> {
785 if !self.func.dfg.ebb_is_valid(e) || !self.func.layout.is_ebb_inserted(e) {
786 return errors.fatal((loc, format!("invalid ebb reference {}", e)));
787 }
788 if let Some(entry_block) = self.func.layout.entry_block() {
789 if e == entry_block {
790 return errors.fatal((loc, format!("invalid reference to entry ebb {}", e)));
791 }
792 }
793 Ok(())
794 }
795
796 fn verify_sig_ref(
797 &self,
798 inst: Inst,
799 s: SigRef,
800 errors: &mut VerifierErrors,
801 ) -> VerifierStepResult<()> {
802 if !self.func.dfg.signatures.is_valid(s) {
803 errors.fatal((
804 inst,
805 self.context(inst),
806 format!("invalid signature reference {}", s),
807 ))
808 } else {
809 Ok(())
810 }
811 }
812
813 fn verify_func_ref(
814 &self,
815 inst: Inst,
816 f: FuncRef,
817 errors: &mut VerifierErrors,
818 ) -> VerifierStepResult<()> {
819 if !self.func.dfg.ext_funcs.is_valid(f) {
820 errors.nonfatal((
821 inst,
822 self.context(inst),
823 format!("invalid function reference {}", f),
824 ))
825 } else {
826 Ok(())
827 }
828 }
829
830 fn verify_stack_slot(
831 &self,
832 inst: Inst,
833 ss: StackSlot,
834 errors: &mut VerifierErrors,
835 ) -> VerifierStepResult<()> {
836 if !self.func.stack_slots.is_valid(ss) {
837 errors.nonfatal((
838 inst,
839 self.context(inst),
840 format!("invalid stack slot {}", ss),
841 ))
842 } else {
843 Ok(())
844 }
845 }
846
847 fn verify_global_value(
848 &self,
849 inst: Inst,
850 gv: GlobalValue,
851 errors: &mut VerifierErrors,
852 ) -> VerifierStepResult<()> {
853 if !self.func.global_values.is_valid(gv) {
854 errors.nonfatal((
855 inst,
856 self.context(inst),
857 format!("invalid global value {}", gv),
858 ))
859 } else {
860 Ok(())
861 }
862 }
863
864 fn verify_heap(
865 &self,
866 inst: Inst,
867 heap: ir::Heap,
868 errors: &mut VerifierErrors,
869 ) -> VerifierStepResult<()> {
870 if !self.func.heaps.is_valid(heap) {
871 errors.nonfatal((inst, self.context(inst), format!("invalid heap {}", heap)))
872 } else {
873 Ok(())
874 }
875 }
876
877 fn verify_table(
878 &self,
879 inst: Inst,
880 table: ir::Table,
881 errors: &mut VerifierErrors,
882 ) -> VerifierStepResult<()> {
883 if !self.func.tables.is_valid(table) {
884 errors.nonfatal((inst, self.context(inst), format!("invalid table {}", table)))
885 } else {
886 Ok(())
887 }
888 }
889
890 fn verify_value_list(
891 &self,
892 inst: Inst,
893 l: &ValueList,
894 errors: &mut VerifierErrors,
895 ) -> VerifierStepResult<()> {
896 if !l.is_valid(&self.func.dfg.value_lists) {
897 errors.nonfatal((
898 inst,
899 self.context(inst),
900 format!("invalid value list reference {:?}", l),
901 ))
902 } else {
903 Ok(())
904 }
905 }
906
907 fn verify_jump_table(
908 &self,
909 inst: Inst,
910 j: JumpTable,
911 errors: &mut VerifierErrors,
912 ) -> VerifierStepResult<()> {
913 if !self.func.jump_tables.is_valid(j) {
914 errors.nonfatal((
915 inst,
916 self.context(inst),
917 format!("invalid jump table reference {}", j),
918 ))
919 } else {
920 Ok(())
921 }
922 }
923
924 fn verify_value(
925 &self,
926 loc_inst: Inst,
927 v: Value,
928 errors: &mut VerifierErrors,
929 ) -> VerifierStepResult<()> {
930 let dfg = &self.func.dfg;
931 if !dfg.value_is_valid(v) {
932 errors.nonfatal((
933 loc_inst,
934 self.context(loc_inst),
935 format!("invalid value reference {}", v),
936 ))
937 } else {
938 Ok(())
939 }
940 }
941
942 fn verify_inst_arg(
943 &self,
944 loc_inst: Inst,
945 v: Value,
946 errors: &mut VerifierErrors,
947 ) -> VerifierStepResult<()> {
948 self.verify_value(loc_inst, v, errors)?;
949
950 let dfg = &self.func.dfg;
951 let loc_ebb = self.func.layout.pp_ebb(loc_inst);
952 let is_reachable = self.expected_domtree.is_reachable(loc_ebb);
953
954 match dfg.value_def(v) {
956 ValueDef::Result(def_inst, _) => {
957 if !dfg.inst_is_valid(def_inst) {
959 return errors.fatal((
960 loc_inst,
961 self.context(loc_inst),
962 format!("{} is defined by invalid instruction {}", v, def_inst),
963 ));
964 }
965 if self.func.layout.inst_ebb(def_inst) == None {
967 return errors.fatal((
968 loc_inst,
969 self.context(loc_inst),
970 format!("{} is defined by {} which has no EBB", v, def_inst),
971 ));
972 }
973 if is_reachable {
975 if !self
976 .expected_domtree
977 .dominates(def_inst, loc_inst, &self.func.layout)
978 {
979 return errors.fatal((
980 loc_inst,
981 self.context(loc_inst),
982 format!("uses value {} from non-dominating {}", v, def_inst),
983 ));
984 }
985 if def_inst == loc_inst {
986 return errors.fatal((
987 loc_inst,
988 self.context(loc_inst),
989 format!("uses value {} from itself", v),
990 ));
991 }
992 }
993 }
994 ValueDef::Param(ebb, _) => {
995 if !dfg.ebb_is_valid(ebb) {
997 return errors.fatal((
998 loc_inst,
999 self.context(loc_inst),
1000 format!("{} is defined by invalid EBB {}", v, ebb),
1001 ));
1002 }
1003 if !self.func.layout.is_ebb_inserted(ebb) {
1005 return errors.fatal((
1006 loc_inst,
1007 self.context(loc_inst),
1008 format!("{} is defined by {} which is not in the layout", v, ebb),
1009 ));
1010 }
1011 if is_reachable
1013 && !self
1014 .expected_domtree
1015 .dominates(ebb, loc_inst, &self.func.layout)
1016 {
1017 return errors.fatal((
1018 loc_inst,
1019 self.context(loc_inst),
1020 format!("uses value arg from non-dominating {}", ebb),
1021 ));
1022 }
1023 }
1024 }
1025 Ok(())
1026 }
1027
1028 fn verify_inst_result(
1029 &self,
1030 loc_inst: Inst,
1031 v: Value,
1032 errors: &mut VerifierErrors,
1033 ) -> VerifierStepResult<()> {
1034 self.verify_value(loc_inst, v, errors)?;
1035
1036 match self.func.dfg.value_def(v) {
1037 ValueDef::Result(def_inst, _) => {
1038 if def_inst != loc_inst {
1039 errors.fatal((
1040 loc_inst,
1041 self.context(loc_inst),
1042 format!("instruction result {} is not defined by the instruction", v),
1043 ))
1044 } else {
1045 Ok(())
1046 }
1047 }
1048 ValueDef::Param(_, _) => errors.fatal((
1049 loc_inst,
1050 self.context(loc_inst),
1051 format!("instruction result {} is not defined by the instruction", v),
1052 )),
1053 }
1054 }
1055
1056 fn verify_bitcast(
1057 &self,
1058 inst: Inst,
1059 arg: Value,
1060 errors: &mut VerifierErrors,
1061 ) -> VerifierStepResult<()> {
1062 let typ = self.func.dfg.ctrl_typevar(inst);
1063 let value_type = self.func.dfg.value_type(arg);
1064
1065 if typ.lane_bits() < value_type.lane_bits() {
1066 errors.fatal((
1067 inst,
1068 format!(
1069 "The bitcast argument {} doesn't fit in a type of {} bits",
1070 arg,
1071 typ.lane_bits()
1072 ),
1073 ))
1074 } else {
1075 Ok(())
1076 }
1077 }
1078
1079 fn domtree_integrity(
1080 &self,
1081 domtree: &DominatorTree,
1082 errors: &mut VerifierErrors,
1083 ) -> VerifierStepResult<()> {
1084 for ebb in self.func.layout.ebbs() {
1088 let expected = self.expected_domtree.idom(ebb);
1089 let got = domtree.idom(ebb);
1090 if got != expected {
1091 return errors.fatal((
1092 ebb,
1093 format!(
1094 "invalid domtree, expected idom({}) = {:?}, got {:?}",
1095 ebb, expected, got
1096 ),
1097 ));
1098 }
1099 }
1100 if domtree.cfg_postorder().len() != self.expected_domtree.cfg_postorder().len() {
1102 return errors.fatal((
1103 AnyEntity::Function,
1104 "incorrect number of Ebbs in postorder traversal",
1105 ));
1106 }
1107 for (index, (&test_ebb, &true_ebb)) in domtree
1108 .cfg_postorder()
1109 .iter()
1110 .zip(self.expected_domtree.cfg_postorder().iter())
1111 .enumerate()
1112 {
1113 if test_ebb != true_ebb {
1114 return errors.fatal((
1115 test_ebb,
1116 format!(
1117 "invalid domtree, postorder ebb number {} should be {}, got {}",
1118 index, true_ebb, test_ebb
1119 ),
1120 ));
1121 }
1122 }
1123 for (&prev_ebb, &next_ebb) in domtree.cfg_postorder().iter().adjacent_pairs() {
1125 if self
1126 .expected_domtree
1127 .rpo_cmp(prev_ebb, next_ebb, &self.func.layout)
1128 != Ordering::Greater
1129 {
1130 return errors.fatal((
1131 next_ebb,
1132 format!(
1133 "invalid domtree, rpo_cmp does not says {} is greater than {}",
1134 prev_ebb, next_ebb
1135 ),
1136 ));
1137 }
1138 }
1139 Ok(())
1140 }
1141
1142 fn typecheck_entry_block_params(&self, errors: &mut VerifierErrors) -> VerifierStepResult<()> {
1143 if let Some(ebb) = self.func.layout.entry_block() {
1144 let expected_types = &self.func.signature.params;
1145 let ebb_param_count = self.func.dfg.num_ebb_params(ebb);
1146
1147 if ebb_param_count != expected_types.len() {
1148 return errors.fatal((
1149 ebb,
1150 format!(
1151 "entry block parameters ({}) must match function signature ({})",
1152 ebb_param_count,
1153 expected_types.len()
1154 ),
1155 ));
1156 }
1157
1158 for (i, &arg) in self.func.dfg.ebb_params(ebb).iter().enumerate() {
1159 let arg_type = self.func.dfg.value_type(arg);
1160 if arg_type != expected_types[i].value_type {
1161 errors.report((
1162 ebb,
1163 format!(
1164 "entry block parameter {} expected to have type {}, got {}",
1165 i, expected_types[i], arg_type
1166 ),
1167 ));
1168 }
1169 }
1170 }
1171
1172 errors.as_result()
1173 }
1174
1175 fn typecheck(&self, inst: Inst, errors: &mut VerifierErrors) -> VerifierStepResult<()> {
1176 let inst_data = &self.func.dfg[inst];
1177 let constraints = inst_data.opcode().constraints();
1178
1179 let ctrl_type = if let Some(value_typeset) = constraints.ctrl_typeset() {
1180 let ctrl_type = self.func.dfg.ctrl_typevar(inst);
1182
1183 if !value_typeset.contains(ctrl_type) {
1184 errors.report((
1185 inst,
1186 self.context(inst),
1187 format!("has an invalid controlling type {}", ctrl_type),
1188 ));
1189 }
1190
1191 ctrl_type
1192 } else {
1193 types::INVALID
1196 };
1197
1198 let _ = self.typecheck_results(inst, ctrl_type, errors);
1200 let _ = self.typecheck_fixed_args(inst, ctrl_type, errors);
1201 let _ = self.typecheck_variable_args(inst, errors);
1202 let _ = self.typecheck_return(inst, errors);
1203 let _ = self.typecheck_special(inst, ctrl_type, errors);
1204
1205 self.typecheck_copy_nop(inst, errors)?;
1207
1208 Ok(())
1209 }
1210
1211 fn typecheck_results(
1212 &self,
1213 inst: Inst,
1214 ctrl_type: Type,
1215 errors: &mut VerifierErrors,
1216 ) -> VerifierStepResult<()> {
1217 let mut i = 0;
1218 for &result in self.func.dfg.inst_results(inst) {
1219 let result_type = self.func.dfg.value_type(result);
1220 let expected_type = self.func.dfg.compute_result_type(inst, i, ctrl_type);
1221 if let Some(expected_type) = expected_type {
1222 if result_type != expected_type {
1223 errors.report((
1224 inst,
1225 self.context(inst),
1226 format!(
1227 "expected result {} ({}) to have type {}, found {}",
1228 i, result, expected_type, result_type
1229 ),
1230 ));
1231 }
1232 } else {
1233 return errors.nonfatal((
1234 inst,
1235 self.context(inst),
1236 "has more result values than expected",
1237 ));
1238 }
1239 i += 1;
1240 }
1241
1242 if self.func.dfg.compute_result_type(inst, i, ctrl_type) != None {
1244 return errors.nonfatal((
1245 inst,
1246 self.context(inst),
1247 "has fewer result values than expected",
1248 ));
1249 }
1250 Ok(())
1251 }
1252
1253 fn typecheck_fixed_args(
1254 &self,
1255 inst: Inst,
1256 ctrl_type: Type,
1257 errors: &mut VerifierErrors,
1258 ) -> VerifierStepResult<()> {
1259 let constraints = self.func.dfg[inst].opcode().constraints();
1260
1261 for (i, &arg) in self.func.dfg.inst_fixed_args(inst).iter().enumerate() {
1262 let arg_type = self.func.dfg.value_type(arg);
1263 match constraints.value_argument_constraint(i, ctrl_type) {
1264 ResolvedConstraint::Bound(expected_type) => {
1265 if arg_type != expected_type {
1266 errors.report((
1267 inst,
1268 self.context(inst),
1269 format!(
1270 "arg {} ({}) has type {}, expected {}",
1271 i, arg, arg_type, expected_type
1272 ),
1273 ));
1274 }
1275 }
1276 ResolvedConstraint::Free(type_set) => {
1277 if !type_set.contains(arg_type) {
1278 errors.report((
1279 inst,
1280 self.context(inst),
1281 format!(
1282 "arg {} ({}) with type {} failed to satisfy type set {:?}",
1283 i, arg, arg_type, type_set
1284 ),
1285 ));
1286 }
1287 }
1288 }
1289 }
1290 Ok(())
1291 }
1292
1293 fn typecheck_variable_args(
1294 &self,
1295 inst: Inst,
1296 errors: &mut VerifierErrors,
1297 ) -> VerifierStepResult<()> {
1298 match self.func.dfg.analyze_branch(inst) {
1299 BranchInfo::SingleDest(ebb, _) => {
1300 let iter = self
1301 .func
1302 .dfg
1303 .ebb_params(ebb)
1304 .iter()
1305 .map(|&v| self.func.dfg.value_type(v));
1306 self.typecheck_variable_args_iterator(inst, iter, errors)?;
1307 }
1308 BranchInfo::Table(table, ebb) => {
1309 if let Some(ebb) = ebb {
1310 let arg_count = self.func.dfg.num_ebb_params(ebb);
1311 if arg_count != 0 {
1312 return errors.nonfatal((
1313 inst,
1314 self.context(inst),
1315 format!(
1316 "takes no arguments, but had target {} with {} arguments",
1317 ebb, arg_count,
1318 ),
1319 ));
1320 }
1321 }
1322 for ebb in self.func.jump_tables[table].iter() {
1323 let arg_count = self.func.dfg.num_ebb_params(*ebb);
1324 if arg_count != 0 {
1325 return errors.nonfatal((
1326 inst,
1327 self.context(inst),
1328 format!(
1329 "takes no arguments, but had target {} with {} arguments",
1330 ebb, arg_count,
1331 ),
1332 ));
1333 }
1334 }
1335 }
1336 BranchInfo::NotABranch => {}
1337 }
1338
1339 match self.func.dfg[inst].analyze_call(&self.func.dfg.value_lists) {
1340 CallInfo::Direct(func_ref, _) => {
1341 let sig_ref = self.func.dfg.ext_funcs[func_ref].signature;
1342 let arg_types = self.func.dfg.signatures[sig_ref]
1343 .params
1344 .iter()
1345 .map(|a| a.value_type);
1346 self.typecheck_variable_args_iterator(inst, arg_types, errors)?;
1347 self.check_outgoing_args(inst, sig_ref, errors)?;
1348 }
1349 CallInfo::Indirect(sig_ref, _) => {
1350 let arg_types = self.func.dfg.signatures[sig_ref]
1351 .params
1352 .iter()
1353 .map(|a| a.value_type);
1354 self.typecheck_variable_args_iterator(inst, arg_types, errors)?;
1355 self.check_outgoing_args(inst, sig_ref, errors)?;
1356 }
1357 CallInfo::NotACall => {}
1358 }
1359 Ok(())
1360 }
1361
1362 fn typecheck_variable_args_iterator<I: Iterator<Item = Type>>(
1363 &self,
1364 inst: Inst,
1365 iter: I,
1366 errors: &mut VerifierErrors,
1367 ) -> VerifierStepResult<()> {
1368 let variable_args = self.func.dfg.inst_variable_args(inst);
1369 let mut i = 0;
1370
1371 for expected_type in iter {
1372 if i >= variable_args.len() {
1373 i += 1;
1375 continue;
1376 }
1377 let arg = variable_args[i];
1378 let arg_type = self.func.dfg.value_type(arg);
1379 if expected_type != arg_type {
1380 errors.report((
1381 inst,
1382 self.context(inst),
1383 format!(
1384 "arg {} ({}) has type {}, expected {}",
1385 i, variable_args[i], arg_type, expected_type
1386 ),
1387 ));
1388 }
1389 i += 1;
1390 }
1391 if i != variable_args.len() {
1392 return errors.nonfatal((
1393 inst,
1394 self.context(inst),
1395 format!(
1396 "mismatched argument count for `{}`: got {}, expected {}",
1397 self.func.dfg.display_inst(inst, None),
1398 variable_args.len(),
1399 i,
1400 ),
1401 ));
1402 }
1403 Ok(())
1404 }
1405
1406 fn check_outgoing_args(
1411 &self,
1412 inst: Inst,
1413 sig_ref: SigRef,
1414 errors: &mut VerifierErrors,
1415 ) -> VerifierStepResult<()> {
1416 let sig = &self.func.dfg.signatures[sig_ref];
1417
1418 let args = self.func.dfg.inst_variable_args(inst);
1419 let expected_args = &sig.params[..];
1420
1421 for (&arg, &abi) in args.iter().zip(expected_args) {
1422 if let ArgumentLoc::Stack(offset) = abi.location {
1424 let arg_loc = self.func.locations[arg];
1425 if let ValueLoc::Stack(ss) = arg_loc {
1426 self.verify_stack_slot(inst, ss, errors)?;
1428 let slot = &self.func.stack_slots[ss];
1429 if slot.kind != StackSlotKind::OutgoingArg {
1430 return errors.fatal((
1431 inst,
1432 self.context(inst),
1433 format!(
1434 "Outgoing stack argument {} in wrong stack slot: {} = {}",
1435 arg, ss, slot,
1436 ),
1437 ));
1438 }
1439 if slot.offset != Some(offset) {
1440 return errors.fatal((
1441 inst,
1442 self.context(inst),
1443 format!(
1444 "Outgoing stack argument {} should have offset {}: {} = {}",
1445 arg, offset, ss, slot,
1446 ),
1447 ));
1448 }
1449 if slot.size != abi.value_type.bytes() {
1450 return errors.fatal((
1451 inst,
1452 self.context(inst),
1453 format!(
1454 "Outgoing stack argument {} wrong size for {}: {} = {}",
1455 arg, abi.value_type, ss, slot,
1456 ),
1457 ));
1458 }
1459 } else {
1460 let reginfo = self.isa.map(|i| i.register_info());
1461 return errors.fatal((
1462 inst,
1463 self.context(inst),
1464 format!(
1465 "Outgoing stack argument {} in wrong location: {}",
1466 arg,
1467 arg_loc.display(reginfo.as_ref())
1468 ),
1469 ));
1470 }
1471 }
1472 }
1473 Ok(())
1474 }
1475
1476 fn typecheck_return(&self, inst: Inst, errors: &mut VerifierErrors) -> VerifierStepResult<()> {
1477 if self.func.dfg[inst].opcode().is_return() {
1478 let args = self.func.dfg.inst_variable_args(inst);
1479 let expected_types = &self.func.signature.returns;
1480 if args.len() != expected_types.len() {
1481 return errors.nonfatal((
1482 inst,
1483 self.context(inst),
1484 "arguments of return must match function signature",
1485 ));
1486 }
1487 for (i, (&arg, &expected_type)) in args.iter().zip(expected_types).enumerate() {
1488 let arg_type = self.func.dfg.value_type(arg);
1489 if arg_type != expected_type.value_type {
1490 errors.report((
1491 inst,
1492 self.context(inst),
1493 format!(
1494 "arg {} ({}) has type {}, must match function signature of {}",
1495 i, arg, arg_type, expected_type
1496 ),
1497 ));
1498 }
1499 }
1500 }
1501 Ok(())
1502 }
1503
1504 fn typecheck_special(
1507 &self,
1508 inst: Inst,
1509 ctrl_type: Type,
1510 errors: &mut VerifierErrors,
1511 ) -> VerifierStepResult<()> {
1512 match self.func.dfg[inst] {
1513 ir::InstructionData::Unary { opcode, arg } => {
1514 let arg_type = self.func.dfg.value_type(arg);
1515 match opcode {
1516 Opcode::Bextend | Opcode::Uextend | Opcode::Sextend | Opcode::Fpromote => {
1517 if arg_type.lane_count() != ctrl_type.lane_count() {
1518 return errors.nonfatal((
1519 inst,
1520 self.context(inst),
1521 format!(
1522 "input {} and output {} must have same number of lanes",
1523 arg_type, ctrl_type,
1524 ),
1525 ));
1526 }
1527 if arg_type.lane_bits() >= ctrl_type.lane_bits() {
1528 return errors.nonfatal((
1529 inst,
1530 self.context(inst),
1531 format!(
1532 "input {} must be smaller than output {}",
1533 arg_type, ctrl_type,
1534 ),
1535 ));
1536 }
1537 }
1538 Opcode::Breduce | Opcode::Ireduce | Opcode::Fdemote => {
1539 if arg_type.lane_count() != ctrl_type.lane_count() {
1540 return errors.nonfatal((
1541 inst,
1542 self.context(inst),
1543 format!(
1544 "input {} and output {} must have same number of lanes",
1545 arg_type, ctrl_type,
1546 ),
1547 ));
1548 }
1549 if arg_type.lane_bits() <= ctrl_type.lane_bits() {
1550 return errors.nonfatal((
1551 inst,
1552 self.context(inst),
1553 format!(
1554 "input {} must be larger than output {}",
1555 arg_type, ctrl_type,
1556 ),
1557 ));
1558 }
1559 }
1560 _ => {}
1561 }
1562 }
1563 ir::InstructionData::HeapAddr { heap, arg, .. } => {
1564 let index_type = self.func.dfg.value_type(arg);
1565 let heap_index_type = self.func.heaps[heap].index_type;
1566 if index_type != heap_index_type {
1567 return errors.nonfatal((
1568 inst,
1569 self.context(inst),
1570 format!(
1571 "index type {} differs from heap index type {}",
1572 index_type, heap_index_type,
1573 ),
1574 ));
1575 }
1576 }
1577 ir::InstructionData::TableAddr { table, arg, .. } => {
1578 let index_type = self.func.dfg.value_type(arg);
1579 let table_index_type = self.func.tables[table].index_type;
1580 if index_type != table_index_type {
1581 return errors.nonfatal((
1582 inst,
1583 self.context(inst),
1584 format!(
1585 "index type {} differs from table index type {}",
1586 index_type, table_index_type,
1587 ),
1588 ));
1589 }
1590 }
1591 ir::InstructionData::UnaryGlobalValue { global_value, .. } => {
1592 if let Some(isa) = self.isa {
1593 let inst_type = self.func.dfg.value_type(self.func.dfg.first_result(inst));
1594 let global_type = self.func.global_values[global_value].global_type(isa);
1595 if inst_type != global_type {
1596 return errors.nonfatal((
1597 inst, self.context(inst),
1598 format!(
1599 "global_value instruction with type {} references global value with type {}",
1600 inst_type, global_type
1601 )),
1602 );
1603 }
1604 }
1605 }
1606 _ => {}
1607 }
1608 Ok(())
1609 }
1610
1611 fn typecheck_copy_nop(
1612 &self,
1613 inst: Inst,
1614 errors: &mut VerifierErrors,
1615 ) -> VerifierStepResult<()> {
1616 if let InstructionData::Unary {
1617 opcode: Opcode::CopyNop,
1618 arg,
1619 } = self.func.dfg[inst]
1620 {
1621 let dst_vals = self.func.dfg.inst_results(inst);
1622 if dst_vals.len() != 1 {
1623 return errors.fatal((
1624 inst,
1625 self.context(inst),
1626 "copy_nop must produce exactly one result",
1627 ));
1628 }
1629 let dst_val = dst_vals[0];
1630 if self.func.dfg.value_type(dst_val) != self.func.dfg.value_type(arg) {
1631 return errors.fatal((
1632 inst,
1633 self.context(inst),
1634 "copy_nop src and dst types must be the same",
1635 ));
1636 }
1637 let src_loc = self.func.locations[arg];
1638 let dst_loc = self.func.locations[dst_val];
1639 let locs_ok = match (src_loc, dst_loc) {
1640 (ValueLoc::Stack(src_slot), ValueLoc::Stack(dst_slot)) => src_slot == dst_slot,
1641 _ => false,
1642 };
1643 if !locs_ok {
1644 return errors.fatal((
1645 inst,
1646 self.context(inst),
1647 format!(
1648 "copy_nop must refer to identical stack slots, but found {:?} vs {:?}",
1649 src_loc, dst_loc,
1650 ),
1651 ));
1652 }
1653 }
1654 Ok(())
1655 }
1656
1657 fn cfg_integrity(
1658 &self,
1659 cfg: &ControlFlowGraph,
1660 errors: &mut VerifierErrors,
1661 ) -> VerifierStepResult<()> {
1662 let mut expected_succs = BTreeSet::<Ebb>::new();
1663 let mut got_succs = BTreeSet::<Ebb>::new();
1664 let mut expected_preds = BTreeSet::<Inst>::new();
1665 let mut got_preds = BTreeSet::<Inst>::new();
1666
1667 for ebb in self.func.layout.ebbs() {
1668 expected_succs.extend(self.expected_cfg.succ_iter(ebb));
1669 got_succs.extend(cfg.succ_iter(ebb));
1670
1671 let missing_succs: Vec<Ebb> = expected_succs.difference(&got_succs).cloned().collect();
1672 if !missing_succs.is_empty() {
1673 errors.report((
1674 ebb,
1675 format!("cfg lacked the following successor(s) {:?}", missing_succs),
1676 ));
1677 continue;
1678 }
1679
1680 let excess_succs: Vec<Ebb> = got_succs.difference(&expected_succs).cloned().collect();
1681 if !excess_succs.is_empty() {
1682 errors.report((
1683 ebb,
1684 format!("cfg had unexpected successor(s) {:?}", excess_succs),
1685 ));
1686 continue;
1687 }
1688
1689 expected_preds.extend(
1690 self.expected_cfg
1691 .pred_iter(ebb)
1692 .map(|BasicBlock { inst, .. }| inst),
1693 );
1694 got_preds.extend(cfg.pred_iter(ebb).map(|BasicBlock { inst, .. }| inst));
1695
1696 let missing_preds: Vec<Inst> = expected_preds.difference(&got_preds).cloned().collect();
1697 if !missing_preds.is_empty() {
1698 errors.report((
1699 ebb,
1700 format!(
1701 "cfg lacked the following predecessor(s) {:?}",
1702 missing_preds
1703 ),
1704 ));
1705 continue;
1706 }
1707
1708 let excess_preds: Vec<Inst> = got_preds.difference(&expected_preds).cloned().collect();
1709 if !excess_preds.is_empty() {
1710 errors.report((
1711 ebb,
1712 format!("cfg had unexpected predecessor(s) {:?}", excess_preds),
1713 ));
1714 continue;
1715 }
1716
1717 expected_succs.clear();
1718 got_succs.clear();
1719 expected_preds.clear();
1720 got_preds.clear();
1721 }
1722 errors.as_result()
1723 }
1724
1725 fn verify_encoding(&self, inst: Inst, errors: &mut VerifierErrors) -> VerifierStepResult<()> {
1728 if self.func.encodings.is_empty() {
1733 return Ok(());
1734 }
1735
1736 let isa = match self.isa {
1737 Some(isa) => isa,
1738 None => return Ok(()),
1739 };
1740
1741 let encoding = self.func.encodings[inst];
1742 if encoding.is_legal() {
1743 if self.func.dfg[inst].opcode().is_ghost() {
1744 return errors.nonfatal((
1745 inst,
1746 self.context(inst),
1747 format!(
1748 "Ghost instruction has an encoding: {}",
1749 isa.encoding_info().display(encoding),
1750 ),
1751 ));
1752 }
1753
1754 let mut encodings = isa
1755 .legal_encodings(
1756 &self.func,
1757 &self.func.dfg[inst],
1758 self.func.dfg.ctrl_typevar(inst),
1759 )
1760 .peekable();
1761
1762 if encodings.peek().is_none() {
1763 return errors.nonfatal((
1764 inst,
1765 self.context(inst),
1766 format!(
1767 "Instruction failed to re-encode {}",
1768 isa.encoding_info().display(encoding),
1769 ),
1770 ));
1771 }
1772
1773 let has_valid_encoding = encodings.any(|possible_enc| encoding == possible_enc);
1774
1775 if !has_valid_encoding {
1776 let mut possible_encodings = String::new();
1777 let mut multiple_encodings = false;
1778
1779 for enc in isa.legal_encodings(
1780 &self.func,
1781 &self.func.dfg[inst],
1782 self.func.dfg.ctrl_typevar(inst),
1783 ) {
1784 if !possible_encodings.is_empty() {
1785 possible_encodings.push_str(", ");
1786 multiple_encodings = true;
1787 }
1788 possible_encodings
1789 .write_fmt(format_args!("{}", isa.encoding_info().display(enc)))
1790 .unwrap();
1791 }
1792
1793 return errors.nonfatal((
1794 inst,
1795 self.context(inst),
1796 format!(
1797 "encoding {} should be {}{}",
1798 isa.encoding_info().display(encoding),
1799 if multiple_encodings { "one of: " } else { "" },
1800 possible_encodings,
1801 ),
1802 ));
1803 }
1804 return Ok(());
1805 }
1806
1807 let opcode = self.func.dfg[inst].opcode();
1810
1811 if opcode == Opcode::Fallthrough
1814 || opcode == Opcode::FallthroughReturn
1815 || opcode == Opcode::Safepoint
1816 {
1817 return Ok(());
1818 }
1819
1820 let mut needs_enc = None;
1822 if opcode.is_branch() {
1823 needs_enc = Some("Branch");
1824 } else if opcode.is_call() {
1825 needs_enc = Some("Call");
1826 } else if opcode.is_return() {
1827 needs_enc = Some("Return");
1828 } else if opcode.can_store() {
1829 needs_enc = Some("Store");
1830 } else if opcode.can_trap() {
1831 needs_enc = Some("Trapping instruction");
1832 } else if opcode.other_side_effects() {
1833 needs_enc = Some("Instruction with side effects");
1834 }
1835
1836 if let Some(text) = needs_enc {
1837 match self.func.encode(inst, isa) {
1840 Ok(enc) => {
1841 return errors.nonfatal((
1842 inst,
1843 self.context(inst),
1844 format!(
1845 "{} must have an encoding (e.g., {})))",
1846 text,
1847 isa.encoding_info().display(enc),
1848 ),
1849 ));
1850 }
1851 Err(_) => {
1852 return errors.nonfatal((
1853 inst,
1854 self.context(inst),
1855 format!("{} must have an encoding", text),
1856 ))
1857 }
1858 }
1859 }
1860
1861 Ok(())
1862 }
1863
1864 fn immediate_constraints(
1865 &self,
1866 inst: Inst,
1867 errors: &mut VerifierErrors,
1868 ) -> VerifierStepResult<()> {
1869 let inst_data = &self.func.dfg[inst];
1870
1871 match *inst_data {
1872 ir::InstructionData::Store { flags, .. }
1873 | ir::InstructionData::StoreComplex { flags, .. } => {
1874 if flags.readonly() {
1875 errors.fatal((
1876 inst,
1877 self.context(inst),
1878 "A store instruction cannot have the `readonly` MemFlag",
1879 ))
1880 } else {
1881 Ok(())
1882 }
1883 }
1884 ir::InstructionData::ExtractLane {
1885 opcode: ir::instructions::Opcode::Extractlane,
1886 lane,
1887 arg,
1888 ..
1889 }
1890 | ir::InstructionData::InsertLane {
1891 opcode: ir::instructions::Opcode::Insertlane,
1892 lane,
1893 args: [arg, _],
1894 ..
1895 } => {
1896 let ty = self.func.dfg.value_type(arg);
1899 if u16::from(lane) >= ty.lane_count() {
1900 errors.fatal((
1901 inst,
1902 self.context(inst),
1903 format!("The lane {} does not index into the type {}", lane, ty,),
1904 ))
1905 } else {
1906 Ok(())
1907 }
1908 }
1909 _ => Ok(()),
1910 }
1911 }
1912
1913 fn verify_safepoint_unused(
1914 &self,
1915 inst: Inst,
1916 errors: &mut VerifierErrors,
1917 ) -> VerifierStepResult<()> {
1918 if let Some(isa) = self.isa {
1919 if !isa.flags().enable_safepoints() && self.func.dfg[inst].opcode() == Opcode::Safepoint
1920 {
1921 return errors.fatal((
1922 inst,
1923 self.context(inst),
1924 "safepoint instruction cannot be used when it is not enabled.",
1925 ));
1926 }
1927 }
1928 Ok(())
1929 }
1930
1931 fn typecheck_function_signature(&self, errors: &mut VerifierErrors) -> VerifierStepResult<()> {
1932 self.func
1933 .signature
1934 .params
1935 .iter()
1936 .enumerate()
1937 .filter(|(_, ¶m)| param.value_type == types::INVALID)
1938 .for_each(|(i, _)| {
1939 errors.report((
1940 AnyEntity::Function,
1941 format!("Parameter at position {} has an invalid type", i),
1942 ));
1943 });
1944
1945 self.func
1946 .signature
1947 .returns
1948 .iter()
1949 .enumerate()
1950 .filter(|(_, &ret)| ret.value_type == types::INVALID)
1951 .for_each(|(i, _)| {
1952 errors.report((
1953 AnyEntity::Function,
1954 format!("Return value at position {} has an invalid type", i),
1955 ))
1956 });
1957
1958 if errors.has_error() {
1959 Err(())
1960 } else {
1961 Ok(())
1962 }
1963 }
1964
1965 pub fn run(&self, errors: &mut VerifierErrors) -> VerifierStepResult<()> {
1966 self.verify_global_values(errors)?;
1967 self.verify_heaps(errors)?;
1968 self.verify_tables(errors)?;
1969 self.verify_jump_tables(errors)?;
1970 self.typecheck_entry_block_params(errors)?;
1971 self.typecheck_function_signature(errors)?;
1972
1973 for ebb in self.func.layout.ebbs() {
1974 if self.func.layout.first_inst(ebb).is_none() {
1975 return errors.fatal((ebb, format!("{} cannot be empty", ebb)));
1976 }
1977 for inst in self.func.layout.ebb_insts(ebb) {
1978 self.ebb_integrity(ebb, inst, errors)?;
1979 self.instruction_integrity(inst, errors)?;
1980 self.verify_safepoint_unused(inst, errors)?;
1981 self.typecheck(inst, errors)?;
1982 self.verify_encoding(inst, errors)?;
1983 self.immediate_constraints(inst, errors)?;
1984 }
1985
1986 #[cfg(feature = "basic-blocks")]
1987 self.encodable_as_bb(ebb, errors)?;
1988 }
1989
1990 verify_flags(self.func, &self.expected_cfg, self.isa, errors)?;
1991
1992 if !errors.is_empty() {
1993 debug!(
1994 "Found verifier errors in function:\n{}",
1995 pretty_verifier_error(self.func, None, None, errors.clone())
1996 );
1997 }
1998
1999 Ok(())
2000 }
2001}
2002
2003#[cfg(test)]
2004mod tests {
2005 use super::{Verifier, VerifierError, VerifierErrors};
2006 use crate::entity::EntityList;
2007 use crate::ir::instructions::{InstructionData, Opcode};
2008 use crate::ir::{types, AbiParam, Function};
2009 use crate::settings;
2010
2011 macro_rules! assert_err_with_msg {
2012 ($e:expr, $msg:expr) => {
2013 match $e.0.get(0) {
2014 None => panic!("Expected an error"),
2015 Some(&VerifierError { ref message, .. }) => {
2016 if !message.contains($msg) {
2017 #[cfg(feature = "std")]
2018 panic!(format!(
2019 "'{}' did not contain the substring '{}'",
2020 message, $msg
2021 ));
2022 #[cfg(not(feature = "std"))]
2023 panic!("error message did not contain the expected substring");
2024 }
2025 }
2026 }
2027 };
2028 }
2029
2030 #[test]
2031 fn empty() {
2032 let func = Function::new();
2033 let flags = &settings::Flags::new(settings::builder());
2034 let verifier = Verifier::new(&func, flags.into());
2035 let mut errors = VerifierErrors::default();
2036
2037 assert_eq!(verifier.run(&mut errors), Ok(()));
2038 assert!(errors.0.is_empty());
2039 }
2040
2041 #[test]
2042 fn bad_instruction_format() {
2043 let mut func = Function::new();
2044 let ebb0 = func.dfg.make_ebb();
2045 func.layout.append_ebb(ebb0);
2046 let nullary_with_bad_opcode = func.dfg.make_inst(InstructionData::UnaryImm {
2047 opcode: Opcode::F32const,
2048 imm: 0.into(),
2049 });
2050 func.layout.append_inst(nullary_with_bad_opcode, ebb0);
2051 func.layout.append_inst(
2052 func.dfg.make_inst(InstructionData::Jump {
2053 opcode: Opcode::Jump,
2054 destination: ebb0,
2055 args: EntityList::default(),
2056 }),
2057 ebb0,
2058 );
2059 let flags = &settings::Flags::new(settings::builder());
2060 let verifier = Verifier::new(&func, flags.into());
2061 let mut errors = VerifierErrors::default();
2062
2063 let _ = verifier.run(&mut errors);
2064
2065 assert_err_with_msg!(errors, "instruction format");
2066 }
2067
2068 #[test]
2069 fn test_function_invalid_param() {
2070 let mut func = Function::new();
2071 func.signature.params.push(AbiParam::new(types::INVALID));
2072
2073 let mut errors = VerifierErrors::default();
2074 let flags = &settings::Flags::new(settings::builder());
2075 let verifier = Verifier::new(&func, flags.into());
2076
2077 let _ = verifier.typecheck_function_signature(&mut errors);
2078 assert_err_with_msg!(errors, "Parameter at position 0 has an invalid type");
2079 }
2080
2081 #[test]
2082 fn test_function_invalid_return_value() {
2083 let mut func = Function::new();
2084 func.signature.returns.push(AbiParam::new(types::INVALID));
2085
2086 let mut errors = VerifierErrors::default();
2087 let flags = &settings::Flags::new(settings::builder());
2088 let verifier = Verifier::new(&func, flags.into());
2089
2090 let _ = verifier.typecheck_function_signature(&mut errors);
2091 assert_err_with_msg!(errors, "Return value at position 0 has an invalid type");
2092 }
2093
2094 #[test]
2095 fn test_printing_contextual_errors() {
2096 let mut func = Function::new();
2098 let ebb0 = func.dfg.make_ebb();
2099 func.layout.append_ebb(ebb0);
2100
2101 let inst = func.dfg.make_inst(InstructionData::UnaryImm {
2103 opcode: Opcode::Iconst,
2104 imm: 42.into(),
2105 });
2106 func.dfg.append_result(inst, types::I32);
2107 func.dfg.append_result(inst, types::I32);
2108 func.layout.append_inst(inst, ebb0);
2109
2110 let mut errors = VerifierErrors::default();
2112 let flags = &settings::Flags::new(settings::builder());
2113 let verifier = Verifier::new(&func, flags.into());
2114
2115 let _ = verifier.typecheck_results(inst, types::I32, &mut errors);
2118 assert_eq!(
2119 format!("{}", errors.0[0]),
2120 "inst0 (v0, v1 = iconst.i32 42): has more result values than expected"
2121 )
2122 }
2123
2124 #[test]
2125 fn test_empty_ebb() {
2126 let mut func = Function::new();
2127 let ebb0 = func.dfg.make_ebb();
2128 func.layout.append_ebb(ebb0);
2129
2130 let flags = &settings::Flags::new(settings::builder());
2131 let verifier = Verifier::new(&func, flags.into());
2132 let mut errors = VerifierErrors::default();
2133 let _ = verifier.run(&mut errors);
2134
2135 assert_err_with_msg!(errors, "ebb0 cannot be empty");
2136 }
2137}