veri_engine_lib/
verify.rs1use crate::type_inference::type_rules_with_term_and_types;
2use crate::Config;
3use cranelift_isle::error::Errors;
4use cranelift_isle::{self as isle};
5use isle::compile::create_envs;
6use isle::sema::{Pattern, RuleId, TermEnv, TypeEnv};
7use std::collections::HashMap;
8use std::path::PathBuf;
9
10use crate::annotations::parse_annotations;
11use crate::solver::run_solver;
12use crate::type_inference::RuleSemantics;
13use crate::{interp::Context, termname::pattern_contains_termname};
14use veri_ir::{ConcreteTest, TermSignature, VerificationResult};
15
16pub fn verify_rules(
17 inputs: Vec<PathBuf>,
18 config: &Config,
19 widths: &Option<Vec<String>>,
20) -> Result<(), Errors> {
21 let (typeenv, termenv, defs) = create_envs(inputs).unwrap();
24
25 let annotation_env = parse_annotations(&defs, &termenv, &typeenv);
26
27 let types = annotation_env
29 .get_term_signatures_by_name(&termenv, &typeenv)
30 .get(&config.term as &str)
31 .unwrap_or_else(|| panic!("Missing term type instantiation for {}", config.term))
32 .clone();
33
34 let types_filtered = if let Some(widths) = widths {
35 let mut width_types = Vec::new();
36
37 for w in widths {
38 let width_type = match w.as_str() {
39 "I8" => veri_ir::Type::BitVector(Some(8)),
40 "I16" => veri_ir::Type::BitVector(Some(16)),
41 "I32" => veri_ir::Type::BitVector(Some(32)),
42 "I64" => veri_ir::Type::BitVector(Some(64)),
43 _ => panic!("Invalid width type: {}", w),
44 };
45 width_types.push(width_type);
46 }
47
48 types
49 .into_iter()
50 .filter(|t| {
51 if let Some(canonical_type) = &t.canonical_type {
52 width_types.contains(canonical_type)
53 } else {
54 false
55 }
56 })
57 .collect::<Vec<_>>()
58 } else {
59 types
60 };
61
62 for type_instantiation in types_filtered {
63 let type_sols = type_rules_with_term_and_types(
64 &termenv,
65 &typeenv,
66 &annotation_env,
67 config,
68 &type_instantiation,
69 &None,
70 );
71 verify_rules_for_term(
72 &termenv,
73 &typeenv,
74 &type_sols,
75 type_instantiation,
76 &None,
77 config,
78 );
79 }
80 Ok(())
81}
82
83pub fn verify_rules_for_term(
84 termenv: &TermEnv,
85 typeenv: &TypeEnv,
86 typesols: &HashMap<RuleId, RuleSemantics>,
87 types: TermSignature,
88 concrete: &Option<ConcreteTest>,
89 config: &Config,
90) -> VerificationResult {
91 let mut rules_checked = 0;
92 for rule in &termenv.rules {
93 if !pattern_contains_termname(
95 &Pattern::Term(
97 cranelift_isle::sema::TypeId(0),
98 rule.root_term,
99 rule.args.clone(),
100 ),
101 &config.term,
102 termenv,
103 typeenv,
104 ) {
105 continue;
106 }
107 if let Some(names) = &config.names {
108 if rule.name.is_none() {
109 continue;
110 }
111 let name = &typeenv.syms[rule.name.unwrap().index()];
112 if !names.contains(name) {
113 continue;
114 } else {
115 log::debug!("Verifying rule: {}", name);
116 }
117 }
118 let ctx = Context::new(typesols);
119 if ctx.typesols.get(&rule.id).is_none() {
120 continue;
121 }
122 let rule_sem = &ctx.typesols[&rule.id];
123 log::debug!("Term: {}", config.term);
124 log::debug!("Type instantiation: {}", types);
125 let result = run_solver(rule_sem, rule, termenv, typeenv, concrete, config, &types);
126 rules_checked += 1;
127 if result != VerificationResult::Success {
128 return result;
129 }
130 }
131 if rules_checked > 0 {
132 VerificationResult::Success
133 } else {
134 panic!("No rules checked!")
135 }
136}